[PyQt] PyQt Digest, Vol 101, Issue 21

Patrick Moran pmoran at aptect.com
Fri Dec 21 23:09:31 GMT 2012


This seems to work (but I don't think its thread safe). You probably need to
use a mutex or semaphore somewhere.

"""
This demo demonstrates how to embed a matplotlib (mpl) plot 
into a PyQt4 GUI application, including:

* Using the navigation toolbar
* Adding data to the plot
* Dynamically modifying the plot's properties
* Processing mpl events
* Saving the plot to a file from a menu

The main goal is to serve as a basis for developing rich PyQt GUI
applications featuring mpl plots (using the mpl OO API).

Eli Bendersky (eliben at gmail.com)
License: this code is in the public domain
Last modified: 19.01.2009
"""
import sys, os, random
import time

from PyQt4.QtCore import *
from PyQt4.QtGui import *
#from PyQt4.QtCore import QThread
import matplotlib
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as
FigureCanvas
from matplotlib.backends.backend_qt4agg import NavigationToolbar2QTAgg as
NavigationToolbar
from matplotlib.figure import Figure


class AppForm(QMainWindow):
    def __init__(self, parent=None):
        QMainWindow.__init__(self, parent)
        self.setWindowTitle('Demo: PyQt with matplotlib')

        self.create_menu()
        self.create_main_frame()
        self.create_status_bar()

        self.textbox.setText('1 2 3 4')
        self.on_draw()

    def save_plot(self):
        file_choices = "PNG (*.png)|*.png"
        
        path = unicode(QFileDialog.getSaveFileName(self, 
                        'Save file', '', 
                        file_choices))
        if path:
            self.canvas.print_figure(path, dpi=self.dpi)
            self.statusBar().showMessage('Saved to %s' % path, 2000)
    
    def on_about(self):
        msg = """ A demo of using PyQt with matplotlib:
        
         * Use the matplotlib navigation bar
         * Add values to the text box and press Enter (or click "Draw")
         * Show or hide the grid
         * Drag the slider to modify the width of the bars
         * Save the plot to a file using the File menu
         * Click on a bar to receive an informative message
        """
        QMessageBox.about(self, "About the demo", msg.strip())
    
    def on_pick(self, event):
        # The event received here is of the type
        # matplotlib.backend_bases.PickEvent
        #
        # It carries lots of information, of which we're using
        # only a small amount here.
        # 
        box_points = event.artist.get_bbox().get_points()
        msg = "You've clicked on a bar with coords:\n %s" % box_points
        
        QMessageBox.information(self, "Click!", msg)
    
    def on_draw(self):
        """ Redraws the figure
        """
        str = unicode(self.textbox.text())
        self.data = map(int, str.split())
        
        x = range(len(self.data))

        # clear the axes and redraw the plot anew
        #
        self.axes.clear()        
        self.axes.grid(self.grid_cb.isChecked())
        
        self.axes.bar(
            left=x, 
            height=self.data, 
            width=self.slider.value() / 100.0, 
            align='center', 
            alpha=0.44,
            picker=5)
        
        self.canvas.draw()
    
    def create_main_frame(self):
        self.main_frame = QWidget()
        
        # Create the mpl Figure and FigCanvas objects. 
        # 5x4 inches, 100 dots-per-inch
        #
        self.dpi = 100
        self.fig = Figure((5.0, 4.0), dpi=self.dpi)
        self.canvas = FigureCanvas(self.fig)
        self.canvas.setParent(self.main_frame)
        
        # Since we have only one plot, we can use add_axes 
        # instead of add_subplot, but then the subplot
        # configuration tool in the navigation toolbar wouldn't
        # work.
        #
        self.axes = self.fig.add_subplot(111)
        
        # Bind the 'pick' event for clicking on one of the bars
        #
        self.canvas.mpl_connect('pick_event', self.on_pick)
        
        # Create the navigation toolbar, tied to the canvas
        #
        self.mpl_toolbar = NavigationToolbar(self.canvas, self.main_frame)
        
        # Other GUI controls
        # 
        self.textbox = QLineEdit()
        self.textbox.setMinimumWidth(200)
        self.connect(self.textbox, SIGNAL('editingFinished ()'),
self.on_draw)
        
        self.draw_button = QPushButton("&Draw")
        self.connect(self.draw_button, SIGNAL('clicked()'), self.on_draw)
        
        self.grid_cb = QCheckBox("Show &Grid")
        self.grid_cb.setChecked(False)
        self.connect(self.grid_cb, SIGNAL('stateChanged(int)'),
self.on_draw)
        
        slider_label = QLabel('Bar width (%):')
        self.slider = QSlider(Qt.Horizontal)
        self.slider.setRange(1, 100)
        self.slider.setValue(20)
        self.slider.setTracking(True)
        self.slider.setTickPosition(QSlider.TicksBothSides)
        self.connect(self.slider, SIGNAL('valueChanged(int)'), self.on_draw)
        
        #
        # Layout with box sizers
        # 
        hbox = QHBoxLayout()
        
        for w in [  self.textbox, self.draw_button, self.grid_cb,
                    slider_label, self.slider]:
            hbox.addWidget(w)
            hbox.setAlignment(w, Qt.AlignVCenter)
        
        vbox = QVBoxLayout()
        vbox.addWidget(self.canvas)
        vbox.addWidget(self.mpl_toolbar)
        vbox.addLayout(hbox)
        
        self.main_frame.setLayout(vbox)
        self.setCentralWidget(self.main_frame)
    
    def create_status_bar(self):
        self.status_text = QLabel("This is a demo")
        self.statusBar().addWidget(self.status_text, 1)
        
    def create_menu(self):        
        self.file_menu = self.menuBar().addMenu("&File")
        
        load_file_action = self.create_action("&Save plot",
            shortcut="Ctrl+S", slot=self.save_plot, 
            tip="Save the plot")
        quit_action = self.create_action("&Quit", slot=self.close, 
            shortcut="Ctrl+Q", tip="Close the application")
        
        self.add_actions(self.file_menu, 
            (load_file_action, None, quit_action))
        
        self.help_menu = self.menuBar().addMenu("&Help")
        about_action = self.create_action("&About", 
            shortcut='F1', slot=self.on_about, 
            tip='About the demo')
        
        self.add_actions(self.help_menu, (about_action,))

    def add_actions(self, target, actions):
        for action in actions:
            if action is None:
                target.addSeparator()
            else:
                target.addAction(action)

    def create_action(  self, text, slot=None, shortcut=None, 
                        icon=None, tip=None, checkable=False, 
                        signal="triggered()"):
        action = QAction(text, self)
        if icon is not None:
            action.setIcon(QIcon(":/%s.png" % icon))
        if shortcut is not None:
            action.setShortcut(shortcut)
        if tip is not None:
            action.setToolTip(tip)
            action.setStatusTip(tip)
        if slot is not None:
            self.connect(action, SIGNAL(signal), slot)
        if checkable:
            action.setCheckable(True)
        return action

class AThread(QThread):
    def __init__(self,theForm):
        QThread.__init__(self)
        self.theForm=theForm
    def run(self):
        count = 0
        while count < 5:
            time.sleep(1)
            print "Increasing"
            count += 1
            rv = [ random.randint(0, 10) for i in range(4) ]
            self.theForm.textbox.setText(' '.join(map(str, rv)))
            self.theForm.on_draw()
        
        
def main():
    app = QApplication(sys.argv)
    form = AppForm()
    thread = AThread(form)
    thread.finished.connect(thread.start)
    thread.start()    
    form.show()
    app.exec_()


        
if __name__ == "__main__":
    main()


-----Original Message-----
From: pyqt-bounces at riverbankcomputing.com
[mailto:pyqt-bounces at riverbankcomputing.com] On Behalf Of
pyqt-request at riverbankcomputing.com
Sent: Friday, December 21, 2012 6:07 AM
To: pyqt at riverbankcomputing.com
Subject: PyQt Digest, Vol 101, Issue 21

Send PyQt mailing list submissions to
	pyqt at riverbankcomputing.com

To subscribe or unsubscribe via the World Wide Web, visit
	http://www.riverbankcomputing.com/mailman/listinfo/pyqt
or, via email, send a message with subject or body 'help' to
	pyqt-request at riverbankcomputing.com

You can reach the person managing the list at
	pyqt-owner at riverbankcomputing.com

When replying, please edit your Subject line so it is more specific than
"Re: Contents of PyQt digest..."


Today's Topics:

   1. Support for Qt v5.0.0 (Phil Thompson)
   2. Re: Strange error loop... (David Cortesi)
   3.  Multithreading and plotting (Fabien Lafont)
   4. PyQt4 and Qt5 (Detlev Offenbach)
   5. Issue with latest PyQt4 snapshot and Qt 5.0.0 (Detlev Offenbach)
   6. Another issue with latest PyQt4 snapshot and Qt5
      (Detlev Offenbach)


----------------------------------------------------------------------

Message: 1
Date: Thu, 20 Dec 2012 15:01:49 +0000
From: Phil Thompson <phil at riverbankcomputing.com>
To: PyQt Mailing List <pyqt at riverbankcomputing.com>
Subject: [PyQt] Support for Qt v5.0.0
Message-ID: <65ca454b4bc09d662694355caf4fa6f1 at localhost>
Content-Type: text/plain; charset=UTF-8

For those interested the current PyQt4 and SIP snapshots fully support the
final release of Qt v5.0.0. Bug reports welcome.

Phil


------------------------------

Message: 2
Date: Thu, 20 Dec 2012 08:05:16 -0800
From: David Cortesi <davecortesi at gmail.com>
To: pyqt at riverbankcomputing.com
Subject: Re: [PyQt] Strange error loop...
Message-ID:
	<CALyzANvDTFDSXs6umU1aFPGYHythdqjj6kx7Yp-zQoXw88JaJw at mail.gmail.com>
Content-Type: text/plain; charset="iso-8859-1"

Sorry, googling some of the messages shows they come from the OSX Core
Graphics. So it's an issue between Qt and OSX. Sorry for the noise.

On Thu, Dec 20, 2012 at 4:00 AM, <pyqt-request at riverbankcomputing.com>wrote:

> CGErrorBreakpoint
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://www.riverbankcomputing.com/pipermail/pyqt/attachments/20121220/dc692
bdd/attachment-0001.html>

------------------------------

Message: 3
Date: Thu, 20 Dec 2012 17:32:23 +0100
From: Fabien Lafont <lafont.fabien at gmail.com>
To: "pyqt at riverbankcomputing.com" <pyqt at riverbankcomputing.com>
Subject: [PyQt]  Multithreading and plotting
Message-ID:
	<CAC9H_chunLCx2Mju8oAH=PpH2a5G7Q7v_UPAYZPQPfgENGU+Ug at mail.gmail.com>
Content-Type: text/plain; charset="iso-8859-1"

Hello everyone,

I'm trying to plot live datas using matplotlib and PyQt. I need a
multithreaded program beacause I use time.sleep and it freeze completely the
app during that moment. I've tried that but it crash immediatly:


from PyQt4 import QtCore, QtGui

import time

import sys

from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as
FigureCanvas

from matplotlib.backends.backend_qt4agg import NavigationToolbar2QTAgg as
NavigationToolbar

from matplotlib.figure import Figure

# Subclassing QThread

# http://doc.qt.nokia.com/latest/qthread.html

class Graph(FigureCanvas):

def __init__(self,parent):

self.fig = Figure()

self.ax = self.fig.add_subplot(111)

FigureCanvas.__init__(self, self.fig)

self.R1 = []

self.l_R1, = self.ax.plot([], self.R1,"-o")

self.fig.canvas.draw()

FigureCanvas.updateGeometry(self)

class ApplicationWindow(QtGui.QMainWindow):

"""Example main window"""

def __init__(self):

QtGui.QMainWindow.__init__(self)

self.main_widget = QtGui.QWidget(self)

vbl = QtGui.QGridLayout(self.main_widget)

qmc = Graph(self.main_widget)

vbl.addWidget(qmc,0,0,1,11)

self.setCentralWidget(self.main_widget)

class AThread(QtCore.QThread):

def run(self):

count = 0

while count < 5:

time.sleep(1)

print "Increasing"

count += 1

aw.l_R1.set_data(count, count)

def usingQThread():

app = QtCore.QCoreApplication([])

thread = AThread()

thread.finished.connect(app.exit)

thread.start()

sys.exit(app.exec_())

if __name__ == "__main__":

#

 qApp = QtGui.QApplication(sys.argv)

aw = ApplicationWindow()

aw.showMaximized()

usingQThread()

sys.exit(qApp.exec_())


Could you explain me why? The aim is to use one thread to acquire the data
and another to refresh the graph.


Thanks!


Fabien
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://www.riverbankcomputing.com/pipermail/pyqt/attachments/20121220/db252
1fa/attachment-0001.html>

------------------------------

Message: 4
Date: Fri, 21 Dec 2012 11:04:33 +0100
From: Detlev Offenbach <detlev at die-offenbachs.de>
To: pyqt at riverbankcomputing.com
Subject: [PyQt] PyQt4 and Qt5
Message-ID: <2755190.YHLBfl5yGU at saturn>
Content-Type: text/plain; charset="us-ascii"

Hello Phil,

will you eventually provide Windows installers including Qt5 as well? If you
will, will it be possible to install them in parallel, i.e. have PyQt4 with
Qt4 and Qt5 available at the same time?

Regards,
Detlev
--
Detlev Offenbach
detlev at die-offenbachs.de
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://www.riverbankcomputing.com/pipermail/pyqt/attachments/20121221/c55e2
94f/attachment-0001.html>

------------------------------

Message: 5
Date: Fri, 21 Dec 2012 12:01:08 +0100
From: Detlev Offenbach <detlev at die-offenbachs.de>
To: pyqt at riverbankcomputing.com
Subject: [PyQt] Issue with latest PyQt4 snapshot and Qt 5.0.0
Message-ID: <2812146.BFkD31vffh at saturn>
Content-Type: text/plain; charset="us-ascii"

Hello,

I built and installed Qt 5.0.0 myself on my openSUSE 12.2 machine.
Everything compiled and installed fine. However, when I tried to configure
the latest PyQt4 snapshot with a command like

~/py3qt50env/bin/python configure.py -b ~/py3qt50env/bin/ -v
~/py3qt50env/sip - c -j8

I am getting an error

Determining the layout of your Qt installation...
Error: Unable to find the qmake configuration file
/usr/local/Qt-5.0.0/mkspecs/default/qmake.conf. Use the QMAKESPEC
environment variable to specify the correct platform.

I checked the Qt5 installation and indeed, there is no default directory.
How can I tell configure.py which mkspec to use (other than through
QMAKESPEC)?

Regards,
Detlev
--
Detlev Offenbach
detlev at die-offenbachs.de
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://www.riverbankcomputing.com/pipermail/pyqt/attachments/20121221/8780d
124/attachment-0001.html>

------------------------------

Message: 6
Date: Fri, 21 Dec 2012 12:09:03 +0100
From: Detlev Offenbach <detlev at die-offenbachs.de>
To: pyqt at riverbankcomputing.com
Subject: [PyQt] Another issue with latest PyQt4 snapshot and Qt5
Message-ID: <3630416.fgq1txFdtm at saturn>
Content-Type: text/plain; charset="us-ascii"

Hello,

here is the next issue I faced. Having resolved the before reported issue
temporarily I tried to compile. However, the linking stage failed. Here is
the output.

g++ -c -m64 -pipe -fPIC -O2 -Wall -W -D_REENTRANT -DNDEBUG -
DQT_DISABLE_DEPRECATED_BEFORE=0x040900 -DSIP_PROTECTED_IS_PUBLIC -
Dprotected=public -DQT_NO_DEBUG -DQT_MULTIMEDIA_LIB -DQT_GUI_LIB
-DQT_CORE_LIB -I. -I/usr/include/python3.2mu
-I/usr/local/Qt-5.0.0/mkspecs/default -
I/usr/local/Qt-5.0.0/include/QtMultimedia
-I/usr/local/Qt-5.0.0/include/QtGui
-I/usr/local/Qt-5.0.0/include/QtWidgets -
I/usr/local/Qt-5.0.0/include/QtPrintSupport -
I/usr/local/Qt-5.0.0/include/QtCore -I/usr/local/Qt-5.0.0/include -o
sipQtMultimediapart6.o sipQtMultimediapart6.cpp
g++ -shared  -Wl,-O1 -Wl,-rpath,/usr/local/Qt-5.0.0/lib -Wl,--version-
script=QtMultimedia.exp -o QtMultimedia.so sipQtMultimediapart0.o
sipQtMultimediapart1.o sipQtMultimediapart2.o sipQtMultimediapart3.o
sipQtMultimediapart4.o sipQtMultimediapart5.o sipQtMultimediapart6.o -
L/usr/local/Qt-5.0.0/lib -L/usr/X11R6/lib64 -lQtMultimedia -lQtGui
-lQtWidgets -lQtPrintSupport -lQtCore -lXext -lX11 -lm -lpthread
/usr/lib64/gcc/x86_64-suse-linux/4.7/../../../../x86_64-suse-linux/bin/ld: 
cannot find -lQtWidgets
/usr/lib64/gcc/x86_64-suse-linux/4.7/../../../../x86_64-suse-linux/bin/ld: 
cannot find -lQtPrintSupport

That is correct because the installed Qt5 libraries are called
libQt5Widgets.so libQt5PrintSupport.so and so on.

Regards,
Detlev
--
Detlev Offenbach
detlev at die-offenbachs.de
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://www.riverbankcomputing.com/pipermail/pyqt/attachments/20121221/b0bdb
67a/attachment.html>

------------------------------

_______________________________________________
PyQt mailing list
PyQt at riverbankcomputing.com
http://www.riverbankcomputing.com/mailman/listinfo/pyqt

End of PyQt Digest, Vol 101, Issue 21
*************************************



More information about the PyQt mailing list