Pyqtgraph with QML

1,660 views
Skip to first unread message

Papee

unread,
Oct 31, 2012, 10:35:34 AM10/31/12
to pyqt...@googlegroups.com
Hi,
Could anyone point me to a simple example where we can use pyqtgraph inside a QML generated window?
Thanks in advance - papee

Luke Campagnola

unread,
Oct 31, 2012, 3:23:51 PM10/31/12
to pyqt...@googlegroups.com
I have not worked with QML at all, but my impression is that it is still very new and QML+Python is experimental at best. PySide claims to have some support for QML but I have not seen this in use anywhere outside of some very basic examples. PyQt appears to have incomplete support for QML (notably, it does not support qmlRegisterType).

So I think the answer for now is no, but in time this could become a possibility. 

Luke


-- [ You are subscribed to pyqt...@googlegroups.com. To unsubscribe, send email to pyqtgraph+...@googlegroups.com ]

Papee

unread,
Nov 5, 2012, 3:54:07 PM11/5/12
to pyqt...@googlegroups.com

Luke,

I have raised a question regarding pyqtgraph and qml in stackoverflow http://stackoverflow.com/questions/13240066/graph-pyqtgrapg-is-not-getting-plotted-inside-qml-generated-window . I got the graph window but no plotting. If you have any suggestion please reply.

regards ,

--afilash

Luke Campagnola

unread,
Nov 5, 2012, 5:12:14 PM11/5/12
to pyqt...@googlegroups.com
On Mon, Nov 5, 2012 at 3:54 PM, Papee <afi...@gmail.com> wrote:

Luke,

I have raised a question regarding pyqtgraph and qml in stackoverflow http://stackoverflow.com/questions/13240066/graph-pyqtgrapg-is-not-getting-plotted-inside-qml-generated-window . I got the graph window but no plotting. If you have any suggestion please reply.


Cool! I'm impressed it works at all. Thanks for figuring that out!

My best guess is that the problem is related to this bug:

However it only appears to be a problem within the QML context. 
You can work around the problem by commenting out the 'itemChange' method in pyqtgraph/graphicsItems/GraphicsObject.py.

Luke

Papee

unread,
Nov 6, 2012, 6:21:52 AM11/6/12
to pyqt...@googlegroups.com
Thanks Luke, It worked.

Papee

unread,
Nov 6, 2012, 6:36:36 AM11/6/12
to pyqt...@googlegroups.com
I know how hard to search for working examples, This is my code, if it helps someone!

#! /usr/bin/python

 

'''

Created on 03-Nov-2012

@author: Afilash

Main.py : Executable for creating application GUI

Created with QML, Having  custom QtDeclarative

item to show a pyqtgraph inside a QGraphicsProxyWidget

( PySide specific 'Python version 2.7.3')

 

Do comment the 'itemChange' method in pyqtgraph/graphicsItems/GraphicsObject.py

as suggested by Luke, then only this will work.

'''

 

__credits__ =['afilash' , 'Luke Campagnola for bugfix']

__version__ = 'V1.0'

 

import os

import sys

from   PySide import QtGui                  #'PySide version 1.1.2'                      

from   PySide import QtCore                 #'setuptools version 0.6c11'

from   PySide import QtDeclarative

import numpy as np                          #'numpy version 1.7.0b2' , 'scipy version 0.11.0'

import pyqtgraph as pg                      #'pyqtgraph REVISION 218'

 

 

 

class Graph (QtDeclarative.QDeclarativeItem):

    """ This is where we are actually creating the graphics widget to show inside QML window"""

   

    def __init__(self, parent = None):

        QtDeclarative.QDeclarativeItem.__init__(self, parent)

       

        self.setFlag(QtGui.QGraphicsItem.ItemHasNoContents, False )        

       

        #----------------------------------- only required for moving Sine Graph

        self.framelength = 400

        self.flowwindow = 2

        self.index =0

        self.indexmax = (1000 -  self.framelength) / self.flowwindow

       

        #----------------------------------- Data points for the sine wave graph

        self.dataPlot = np.cos(np.linspace(0, 10*np.pi , 1000))

       

        #-------------------------- Creating PlotItem for pyqtgraph-GraphicsView

        self.graph = pg.PlotItem()

        #------------------------------------ supplying datapoints for the graph

        self.graph.plot( self.dataPlot, pen=(0,255,0))

        #------------------------------------------------------ Back ground grid

        self.graph.showGrid(x=True, y=True)

       

        #-------------------------------------------- Actual pyqtgraph view item

        self.view = pg.GraphicsView()

        #------------------- Putting our previously created Graph into View Item

        self.view.setCentralItem(self.graph)

 

        #-------------- Since there is no main window as in PyQt we are creating

        #-------------------------------------- a GraphicsProxyWidget inisde QML

        #------------------ and then putting our View item into the Proxy Widget

        mProxy = QtGui.QGraphicsProxyWidget(self)

        mProxy.setWidget(self.view)

       

        #-------------------------------- Just required for the moving sine wave

        self.timer = QtCore.QTimer()

        self.timer.timeout.connect(self.UpdatePlotData)

        self.timer.start(50)

       

    #-------------------------------- Just required for the moving sine wave 

    def UpdatePlotData(self):

        self.index += 1

        if (self.indexmax == self.index):

            self.index = 0        

        self.graph.clear()

        self.graph.plot(self.dataPlot[ self.index * self.flowwindow : self.framelength + self.index * self.flowwindow], pen=(0,255,0) , clear=True)

       

 

if __name__ == '__main__':

    #---------------------------------------------- Creating a QtGui application

    app = QtGui.QApplication(sys.argv)

   

    #--------------- Here is our custom graph item, which is imported inside QML

    QtDeclarative.qmlRegisterType(Graph, 'myPyQtGraph', 1, 0, 'PyQtGraph')

   

    #--------------------------------------- Generating the view based on our QML

    view = QtDeclarative.QDeclarativeView()   

    view.setSource(QtCore.QUrl('main.qml'))

    view.setResizeMode(QtDeclarative.QDeclarativeView.SizeRootObjectToView)

   

    #------------------ only required if you want to communicate with QML window

    rootObject = view.rootObject()

    #---------------------------------------------------- connecting quit signal

    view.connect(view.engine() , QtCore.SIGNAL('quit()') ,app.instance( ) , QtCore.SLOT('quit()') )

   

    #----------------------------------------------------------- Show the window

    view.show()   

    #------------------------- Exit the python program when application finishes

    sys.exit(app.exec_())

   

This is my main.qml:


import QtQuick 1.1

import myPyQtGraph 1.0

Rectangle {

    id : page

    width: 900

    height: 400

    color:  "#343434"

    PyQtGraph {

        id: angleGraphID

        anchors{

            top: parent.top

            left: parent.left

            topMargin: 50

            leftMargin: 50

        }

        width: 800

        height: 300

        //color: "#f5deb3"

    }

    Text {

        id: text_Heading

        anchors{

            top: parent.top

            left: parent.left

            topMargin: 20

            leftMargin: 50

        }

        text: qsTr("PyqtGraph QML Test")

        font.pixelSize: 12

    }

}

 


Papee

unread,
Nov 11, 2012, 12:32:24 PM11/11/12
to pyqt...@googlegroups.com

Hi Luke,

When running the above program , Memory is getting eaten up. It is slowly getting increasing. If we leave the program like that I think the system will purge it. Any solution ?

Luke Campagnola

unread,
Nov 11, 2012, 1:55:41 PM11/11/12
to pyqt...@googlegroups.com
On Sun, Nov 11, 2012 at 12:32 PM, Papee <afi...@gmail.com> wrote:

Hi Luke,

When running the above program , Memory is getting eaten up. It is slowly getting increasing. If we leave the program like that I think the system will purge it. Any solution ?

No solution yet, but here's some detective work:

1) Stopping the timer also stops the memory leak
2) Removing QML from the system and using a regular GraphicsView instead does not help
3) Switching to PyQt4 instead of PySide fixes the problem.
4) It does not appear that there are any python objects being leaked (see below). Putting this together with #3 suggests that the leak is internal to the PySide library. The question remains, then, whether this is due to a PySide bug or improper use of the library.

Here's why I don't think there are any python objects being leaked:  If you disable the timer and add some code immediately before the Qt event loop is started:

    import pyqtgraph.console as con
    c = con.ConsoleWidget()
    c.show()

Then you'll get a console you can do some testing from (this is necessary because PySide still blocks the Python interactive prompt). In the console, I ran this code:

import __main__
graph = __main__.rootObject.children()[0]

## run updates many times to get the memory profile 'settled'
for i in range(500): 
    graph.UpdatePlotData()
    QtGui.QApplication.processEvents()

## take a snapshot of all python objects, then run again
## see help(pg.debug.ObjTracker) for more information on how this works.
ot = pg.debug.ObjTracker()
for i in range(500): 
    graph.UpdatePlotData()
    QtGui.QApplication.processEvents()

## take a second snapshot, run again
ot.diff()
for i in range(500): 
    graph.UpdatePlotData()
    QtGui.QApplication.processEvents()

## and take a third snapshot. This will give you a list of 'persistent' 
## objects--those that were created between the first and second snapshots,
## but were not re-collected by the third snapshot.
ot.diff()

This outputs a lot of information, but at the end is this:

----------- 116 Created since start (persistent): ------------

1 504 <type 'unicode'>

87 1566 <type 'long'>

28 12208 <type 'type'>


So only 116 'persistent' objects are present in this test, none of which are large objects like arrays, graphics items, etc.
I wouldn't consider this proof that nothing is being leaked from pyqtgraph, but it's  reasonably strong evidence.


Luke
Reply all
Reply to author
Forward
0 new messages