No subject


Thu Mar 8 10:26:06 GMT 2007


>>> app.newFigure()    # this is the FIRST command for an *interactive*
plotter

and a new Document window should pop up, take over control and listen to
further user commands.

My problem is, when I try to create a new 'Document 2' in ANY WAY FROM THE
COMMAN LINE EVERYTHING LOCKS UP!.

In this attached example I send a string
message to the very same message thread that talks successfully (kind of) to
the QTextEdit widget of the current Document:

>>> app.sendMsg("newDoc")     # the string "newDoc" needs to be EXACT with
capitalization (for starters)!

"newDoc" is the 'message' from the command thread to the Qt event loop is
calls exactly the same slot as the File->New menu command.
The new Document window appears but now EVERY GUI ACTION IS BLOCKED!
I DO NOT UNDERSTAND WHY!!!

You still can send messages to the newly created window
>>> app.sendMsg("print this works even when the GUI is blocked")

the only way out from here is to kill the python process (^C).

I DO NOT understand what is the difference of creating a new Document window
via button or menu item or via a command line
message to the message thread.

I tried to put the message thread into a QThread  - no difference!
I tried to have a separate message thread for each Document window (both
python and Qt verions) - no difference
.


 Thanks in advance for anybody who is willing to spend time on this problem
or who knows how to tackle it!

Cheers
Peter Lipa
porl3141 at hotmail.com
plipa at earthlink.net







---------------  REPLIES I GOT SO
FAR ------------------------------------------------



----- Original Message -----
From: "Phil Thompson" <phil at river-bank.demon.co.uk>
To: "Peter Lipa" <porl3141 at hotmail.com>
Cc: <pykde at mats.gmd.de>; <plipa at earthlink.net>; <thaneplummer at hotmail.com>
Sent: Thursday, September 05, 2002 12:17 AM
Subject: Re: [PyKDE] How to do *INTERACTIVE* plotting with PyQt (or PyQwt)


>
> eric is able to do pretty much what you describe. It presents you with a
> Python interpreter that you can interactively enter Python statements in
> while the same interpreter is running a PyQt application. There may be
> easier ways of doing it though.
>
> The problem you describe with QThread sounds like you weren't using it
> properly - although I couldn't say if running the event loop from a
> thread is expected to work. (Might do, so long as you manage the Qt lock
> properly.)
>
> Phil
>


----- Original Message -----
From: "Gerard Vermeulen" <gvermeul at grenoble.cnrs.fr>
To: "Peter Lipa" <porl3141 at hotmail.com>
Sent: Thursday, September 05, 2002 12:44 AM
Subject: Re: INTERACTIVE plotting with PyQwt?


> Hi,
>
> Thanks for your feedback. I do agree that the term "interactive data
plotting"
> is confusing or misleading.  My use is interactive data fitting from a
file
> (16000 complex data points per plot) and PyQwt has been proven to be
> extremely fast.
>
> Personally, I have already felt the necessity to use PyQwt in the way you
> described, but I solved it in a quick and dirty manner (piping data into
> Grace, an interactive plotting) program. To be honest: the hard copy
output of
> Grace is better than PyQwt.
>
> One possibility is maybe to steal ideas from Eric (the PyQt debugger) to
> send commands to a "slave" interpreter. I have been thinking about this.
> (check the PyKDE mailing list, where to get the latest Eric).
>
> If I have something more concrete (a few lines of code) after this weekend
> I will send it to you.
>
> Best regards -- Gerard
>


----- Original Message -----
From: "Boudewijn Rempt" <boud at valdyas.org>
To: "Peter Lipa" <porl3141 at hotmail.com>
Sent: Wednesday, September 04, 2002 10:15 PM
Subject: Re: [PyKDE] How to do *INTERACTIVE* plotting with PyQt (or PyQwt)


On Thursday 05 September 2002 02:29, Peter Lipa wrote:
> This seems to be a simple and natural approach to interactive plotting,
but
> I have not found any example or idea based on pyQt that would give me a
> hint how to prevent the Qt eventloop qApp.exec_loop() blocking the
> interpreter or how to add new QMainWindows from the interpreter after the
> eventloop is already running in a separate python thread.

I'm not sure about your exact requirements (and I'm still a bit sleepy --
just
out of bed), but you can have as many QMainWindows as you want, as long as
you've got only one QApplication. So, if you use one QMainWindow  to host
a Python shell, you could create as many QMainWindows to show graphs (but
are
you sure they must be QMainWindows? Won't QDialogs do?).

--
Boudewijn Rempt | http://www.valdyas.org

-----------------------ORIGINAL
MESSAGE---------------------------------------------------------------------
--------
> Peter Lipa wrote:
>
> > Hi,
> >
> > First, let me thank you for providing and maintaining the PyQt package!
> > As a feedback, we compiled and installed sucessfully your package and
demos
> >
> > for the commercial Qt3.0.4 and Qt3.0.5 versions on Win2K (the latest
> > PyQt 3.3 and sip3.3.2 versions!).
> >
> >
> >
> > Now my problem, which I think is a very fundamental one, that needs to
> > be resolved to make a  PyQt  based, interactive
> >
> > plotting package:
> >
> > I am banging my head against the wall in trying to get PyQt (or PyQwt)
> > to allow for INTERACTIVE plotting
> >
> > such as with the scipy.gplt (using gnuplot) or scipy.plt (using
> > wxWindows)  packages. I want a similar API as matlab plotting commands
or
> > the scipy.plt API but based on PyQt (and/or PyQwt but the problem is at
> > the PyQt eventloop and threading level).
> >
> >
> >
> > All examples with PyQt (and PyQwt demos etc) assume that one has only
> >
> > ONE pyqt app running and, if called as a script, block the python
> > interpreter until the PyQt window is closed -- or one runs each demo as
> > a stand alone app.
> >
> > In order to do INTERACTIVE plotting one needs to issue plot commands
> > from the  python interpeter command line such as:
> >
> >  >>>  import qplt
> >
> >  >>> x = [0,1,2,3, 4]; y = [0,1.5,3,1.5,0]
> >
> >  >>> fig1 = qplt.plot(x,y)   # creates a figure window with default axes
> > and line plot with x versus y and returns control to the interpreter
> >
> >  >>> qplt.xlabel("x-axis")  # adds a x-label to the current axes in the
> > current figure
> >
> >  >>> qplt.ylabel("y-axis")  # adds a y-label to the current axes in the
> > current figure
> >
> >  >>> fig2 = qplt.figure()    #  creates a second figure window and all
> > subsequent commands (plot(), xlabel() etc.)  apply to this new window
> >
> > etc, etc
> >
> > In order to get such functionality one needs to create a qt qApp
> > singleton, a figure main-window, start the eventloop in a separate
> > thread (either python thread or QThread) and gives control back to the
> > interpeter to let the user issue new commands (e.g. another figure
> > main-window) interactively.
> >
> > This seems to be a simple and natural approach to interactive plotting,
> > but I have not found any example or idea based on pyQt that would give
> > me a hint how to prevent the Qt eventloop qApp.exec_loop() blocking the
> > interpreter or how to add new QMainWindows from the interpreter after
> > the eventloop is already running in a separate python thread.
> >
> >  So far I have managed to to open a pyqt figure-window from the
> > interpreter by wrapping the main()  with the eventloop qApp.exec_loop()
> > into a python thread; but then I can't open another window from the main
> > thread. Using the QThread class didn't help at all: the subclassed
> > myQThread.run() does never give control back to the interpeter if it
> > contains the qApp.exec_loop(), and myQThread.start() does never call
> > myQThread.run() but the dummy QThread.run().  It is not clear from the
> > Qt (and PyQt) docu if it is possible to run the main Qt eventloop in a
> > QThread; in my experiments it always blocked
> >
> > any GUI.
> >
> >
> >
> > I have tried and tried (using all possible varaints of python threads as
> > well as QThread ) and can't figure out how to do it.
> >
> > Do you have any idea how to do real *INTERACTIVE* plotting with PyQt?
> > Essentially all that needs to be done is to start a qApp and qt
> > eventloop in a separate thread and launch several figure windows and
> > from the python interpreter thread.
> >
> > Since this is a fundamental problem that many people in the scientific
> > area need resolved I hope that someone on this list (or maybe someone
> > you know) knows alread how to do this!
> >
> > Any pointers, ideas or sample code would be GREAT!
>


------=_NextPart_000_0084_01C255D2.305FE800
Content-Type: text/plain;
	name="appThread5.py"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
	filename="appThread5.py"

#!/usr/bin/env python=0A=
=0A=
# A simple application.=0A=
=0A=
=0A=
import sys, string, threading, time=0A=
from qt import *=0A=
=0A=
=0A=
fileopen =3D [=0A=
    '16 13 5 1',=0A=
    '. c #040404',=0A=
    '# c #808304',=0A=
    'a c None',=0A=
    'b c #f3f704',=0A=
    'c c #f3f7f3',=0A=
    'aaaaaaaaa...aaaa',=0A=
    'aaaaaaaa.aaa.a.a',=0A=
    'aaaaaaaaaaaaa..a',=0A=
    'a...aaaaaaaa...a',=0A=
    '.bcb.......aaaaa',=0A=
    '.cbcbcbcbc.aaaaa',=0A=
    '.bcbcbcbcb.aaaaa',=0A=
    '.cbcb...........',=0A=
    '.bcb.#########.a',=0A=
    '.cb.#########.aa',=0A=
    '.b.#########.aaa',=0A=
    '..#########.aaaa',=0A=
    '...........aaaaa'=0A=
]=0A=
=0A=
filesave =3D [=0A=
    '14 14 4 1',=0A=
    '. c #040404',=0A=
    '# c #808304',=0A=
    'a c #bfc2bf',=0A=
    'b c None',=0A=
    '..............',=0A=
    '.#.aaaaaaaa.a.',=0A=
    '.#.aaaaaaaa...',=0A=
    '.#.aaaaaaaa.#.',=0A=
    '.#.aaaaaaaa.#.',=0A=
    '.#.aaaaaaaa.#.',=0A=
    '.#.aaaaaaaa.#.',=0A=
    '.##........##.',=0A=
    '.############.',=0A=
    '.##.........#.',=0A=
    '.##......aa.#.',=0A=
    '.##......aa.#.',=0A=
    '.##......aa.#.',=0A=
    'b.............'=0A=
]=0A=
=0A=
fileprint =3D [=0A=
    '16 14 6 1',=0A=
    '. c #000000',=0A=
    '# c #848284',=0A=
    'a c #c6c3c6',=0A=
    'b c #ffff00',=0A=
    'c c #ffffff',=0A=
    'd c None',=0A=
    'ddddd.........dd',=0A=
    'dddd.cccccccc.dd',=0A=
    'dddd.c.....c.ddd',=0A=
    'ddd.cccccccc.ddd',=0A=
    'ddd.c.....c....d',=0A=
    'dd.cccccccc.a.a.',=0A=
    'd..........a.a..',=0A=
    '.aaaaaaaaaa.a.a.',=0A=
    '.............aa.',=0A=
    '.aaaaaa###aa.a.d',=0A=
    '.aaaaaabbbaa...d',=0A=
    '.............a.d',=0A=
    'd.aaaaaaaaa.a.dd',=0A=
    'dd...........ddd'=0A=
]=0A=
=0A=
=0A=
fileOpenText =3D \=0A=
'''<img source=3D"fileopen">=0A=
Click this button to open a <em>new file</em>.<br><br>=0A=
You can also select the <b>Open</b> command from the <b>File</b> menu.'''=0A=
=0A=
fileSaveText =3D \=0A=
'''Click this button to save the file you are editing.<br><br>=0A=
You will be prompted for a filename.<br><br>=0A=
You can also select the <b>Save</b> command from the <b>File</b> menu.'''=0A=
=0A=
filePrintText =3D \=0A=
'''Click this button to print the file you are editing.<br><br>=0A=
You can also select the <b>Print</b> command from the <b>File</b> =
menu.'''=0A=
=0A=
=0A=
editorList =3D []
gMsg =3D ""
gCurrentFig =3D None
qMsgThread =3D None=0A=
=0A=
class ApplicationWindow(QMainWindow):
    =0A=
    def __init__(self):
        global qMsgThread=0A=
        QMainWindow.__init__(self,None,'example application main =
window',Qt.WDestructiveClose)=0A=
=0A=
        self.filename =3D QString.null=0A=
        self.printer =3D QPrinter()=0A=
=0A=
        self.fileTools =3D QToolBar(self,'file operations')=0A=
=0A=
        openIcon =3D QPixmap(fileopen)=0A=
        self.fileOpen =3D QToolButton(QIconSet(openIcon),'Open =
File',QString.null,self.load,self.fileTools,'open file')=0A=
=0A=
        saveIcon =3D QPixmap(filesave)=0A=
        self.fileSave =3D QToolButton(QIconSet(saveIcon),'Save =
File',QString.null,self.save,self.fileTools,'save file')=0A=
	      =0A=
        printIcon =3D QPixmap(fileprint)=0A=
        self.filePrint =3D QToolButton(QIconSet(printIcon),'Print =
File',QString.null,self.printDoc,self.fileTools,'print file')=0A=
=0A=
        QWhatsThis.whatsThisButton(self.fileTools)=0A=
=0A=
        QWhatsThis.add(self.fileOpen,fileOpenText)=0A=
        =
QMimeSourceFactory.defaultFactory().setPixmap('fileopen',openIcon)=0A=
        QWhatsThis.add(self.fileSave,fileSaveText)=0A=
        QWhatsThis.add(self.filePrint,filePrintText)=0A=
=0A=
        self.file =3D QPopupMenu(self)=0A=
        self.menuBar().insertItem('&File',self.file)=0A=
=0A=
        self.file.insertItem('&New',self.sendNewDocSignal,Qt.CTRL + =
Qt.Key_N)=0A=
=0A=
        id =3D =
self.file.insertItem(QIconSet(openIcon),'&Open',self.load,Qt.CTRL + =
Qt.Key_O)=0A=
        self.file.setWhatsThis(id,fileOpenText)=0A=
=0A=
        id =3D =
self.file.insertItem(QIconSet(saveIcon),'&Save',self.save,Qt.CTRL + =
Qt.Key_S)=0A=
        self.file.setWhatsThis(id,fileSaveText)=0A=
=0A=
        id =3D self.file.insertItem('Save &as',self.saveAs)=0A=
        self.file.setWhatsThis(id,fileSaveText)=0A=
=0A=
        self.file.insertSeparator()=0A=
=0A=
        id =3D =
self.file.insertItem(QIconSet(printIcon),'&Print',self.printDoc,Qt.CTRL =
+ Qt.Key_P)=0A=
        self.file.setWhatsThis(id,filePrintText)=0A=
=0A=
        self.file.insertSeparator()=0A=
=0A=
        self.file.insertItem('&Close',self,SLOT('close()'),Qt.CTRL + =
Qt.Key_W)=0A=
        =
self.file.insertItem('&Quit',qApp,SLOT('closeAllWindows()'),Qt.CTRL + =
Qt.Key_Q)=0A=
=0A=
        self.help =3D QPopupMenu(self)=0A=
        self.menuBar().insertSeparator()=0A=
        self.menuBar().insertItem('&Help',self.help)=0A=
=0A=
        self.help.insertItem('&About',self.about,Qt.Key_F1)=0A=
        self.help.insertItem('About &Qt',self.aboutQt)=0A=
=0A=
        self.e =3D QTextEdit(self,'editor')
        self.e.setTextFormat(Qt.PlainText)        =0A=
        self.e.setFocus()=0A=
        self.setCentralWidget(self.e)=0A=
=0A=
        self.statusBar().message('Ready',2000)=0A=
        self.resize(450,600)

        #new stuff
        global gCurrentFig
        gCurrentFig =3D self
        self.connect(self,PYSIGNAL("newDocSignal"),self.newDoc)
        if not qMsgThread.isAlive():
            qMsgThread.start()

=0A=
    def newDoc(self):=0A=
        ed =3D ApplicationWindow()=0A=
        editorList.append(ed)=0A=
        ed.setCaption('Document ' + str(len(editorList)))
        ed.show()=0A=

    def sendNewDocSignal(self):
        self.emit(PYSIGNAL("newDocSignal"), ())
=0A=
    def load(self):=0A=
        fn =3D =
QFileDialog.getOpenFileName(QString.null,QString.null,self)=0A=
        if fn.isEmpty():=0A=
            self.statusBar().message('Loading aborted',2000)=0A=
            return=0A=
=0A=
        fileName =3D str(fn)=0A=
=0A=
        self.e.setAutoUpdate(0)=0A=
        self.e.clear()=0A=
=0A=
        try:=0A=
            f =3D open(fileName,'r')=0A=
        except:=0A=
            return=0A=
=0A=
        for l in f.readlines():=0A=
            self.e.append(string.rstrip(l))=0A=
=0A=
        f.close()=0A=
=0A=
        self.e.setAutoUpdate(1)=0A=
        self.e.repaint()=0A=
        self.e.setModified(0)=0A=
        self.setCaption(fileName)=0A=
        self.statusBar().message('Loaded document %s' % (fileName),2000)=0A=
=0A=
    def save(self):=0A=
        if self.filename.isEmpty():=0A=
            self.saveAs()=0A=
            return=0A=
=0A=
        try:=0A=
            f =3D open(str(self.filename),'w+')=0A=
        except:=0A=
            self.statusBar().message('Could not write to %s' % =
(self.filename),2000)=0A=
            return=0A=
=0A=
        f.write(str(self.e.text()))=0A=
        f.close()=0A=
=0A=
        self.e.setModified(0)=0A=
        self.setCaption(self.filename)=0A=
        self.statusBar().message('File %s saved' % (self.filename),2000)=0A=
=0A=
    def saveAs(self):=0A=
        fn =3D =
QFileDialog.getSaveFileName(QString.null,QString.null,self)=0A=
        if not fn.isEmpty():=0A=
            self.filename =3D fn=0A=
            self.save()=0A=
        else:=0A=
            self.statusBar().message('Saving aborted',2000)=0A=
=0A=
    def printDoc(self):=0A=
        Margin =3D 10=0A=
        pageNo =3D 1=0A=
=0A=
        if self.printer.setup(self):=0A=
            self.statusBar().message('Printing...')=0A=
=0A=
            p =3D QPainter()=0A=
            p.begin(self.printer)=0A=
            p.setFont(self.e.font())=0A=
            yPos =3D 0=0A=
            fm =3D p.fontMetrics()=0A=
            metrics =3D QPaintDeviceMetrics(self.printer)=0A=
=0A=
            for i in range(self.e.numLines):=0A=
                if Margin + yPos > metrics.height() - Margin:=0A=
                    pageNo =3D pageNo + 1=0A=
                    self.statusBar().message('Printing (page %d)...' % =
(pageNo))=0A=
                    self.printer.newPage()=0A=
                    yPos =3D 0=0A=
=0A=
                p.drawText(Margin,Margin + =
yPos,metrics.width(),fm.lineSpacing(),Qt.ExpandTabs | =
Qt.DontClip,self.e.textLine(i))=0A=
                yPos =3D yPos + fm.lineSpacing()=0A=
=0A=
            p.end()=0A=
            self.statusBar().message('Printing completed',2000)=0A=
        else:=0A=
            self.statusBar().message('Printing aborted',2000)=0A=
 =0A=
    def closeEvent(self,ce):
        global gCurrentFig
        if not self.e.isModified():=0A=
            ce.accept()=0A=
            editorList.remove(self)
            gCurrentFig =3D editorList[-1]=0A=
            return=0A=
=0A=
        rc =3D QMessageBox.information(self,'Qt Application Example',=0A=
                    'The document has been changed since the last save.',=0A=
                    'Save Now','Cancel','Leave Anyway',0,1)=0A=
=0A=
        if rc =3D=3D 0:=0A=
            self.save()=0A=
            ce.accept()=0A=
            editorList.remove(self)
            gCurrentFig =3D editorList[-1]=0A=
        elif rc =3D=3D 2:=0A=
            ce.accept()=0A=
            editorList.remove(self)
            gCurrentFig =3D editorList[-1]=0A=
        else:=0A=
            ce.ignore()=0A=
=0A=
    def about(self):=0A=
        QMessageBox.about(self,'Qt Application Example',=0A=
            'This example demonstrates simple use of =
QMainWindow,\nQMenuBar and QToolBar.')=0A=
=0A=
    def aboutQt(self):=0A=
        QMessageBox.aboutQt(self,'Qt Application Example')
       =20
def stop():
    global stopped
    l =3D threading.Lock()
    l.acquire()
    stopped =3D 1
    l.release()
       =0A=
def msgThread():
    global gMsg, stopped, qMsgThread
    print 'msgThread entered!'
    stopped =3D 0
    idlecount =3D 0
    #qmutex =3D QMutex()
    #lock =3D threading.Lock()
    while 1:
        if stopped:
            break
        #qmutex.lock()
        #lock.acquire()
        # check the global gMsg string for messages from other threads
        if gMsg =3D=3D '':
            # idling
            idlecount +=3D 1
            if not idlecount % 100:
                msg =3D '%d msgThread %s alive and listening ...\n' % =
(idlecount, qMsgThread.getName())
                #print msg
                gCurrentFig.e.insert(msg)
               =20
        elif gMsg =3D=3D 'stop':
            print 'msgThread received a stop msg!'
            stopped =3D 1
        elif gMsg =3D=3D 'newDoc':
            print 'msgThread received a newDoc msg!'
            # create a new Doc window
            #gMsg =3D 'foo'
            gMsg =3D ''
            gCurrentFig.sendNewDocSignal()
            #gCurrentFig.newDoc()
        elif gMsg =3D=3D 'close':
            print 'msgThread received a close msg!'
            # close current Doc window
            gMsg =3D ''
            gCurrentFig.close()
        elif gMsg[:5] =3D=3D 'print':
            msg =3D 'msgThread %s received a msg: %s!\n' % =
(qMsgThread.getName(), gMsg)
            print msg
            gCurrentFig.e.insert(msg)
        else:
            print "msg not understood - no action taken!"

        gMsg =3D ''    # reset gMsg after it was processed               =
    =20
        #lock.release()
        #qmutex.unlock()
        time.sleep(0.1)
        #if gMsg =3D=3D 'foo':
        #    gCurrentFig.sendNewDocSignal()
        #gMsg =3D ''
       =20
    print 'msgThread exited!'


def sendMsg(msg=3D""):
    global gMsg
    # set the global gMsg string in a thread-safe manner
    print " sending Message", msg
    qm =3D threading.Lock()
    qm.acquire()
    gMsg =3D msg
    qm.release()
=0A=
def main(args=3D['']):
    global qMsgThread=0A=
    qMsgThread =3D threading.Thread(target=3DmsgThread)
    a =3D QApplication(args)
    mw =3D ApplicationWindow()
    editorList.append(mw)=0A=
    mw.setCaption('Document 1')
    mw.show()
    a.connect(a, SIGNAL('lastWindowClosed()'), a, SLOT('quit()'))
    a.exec_loop()


##if __name__ =3D=3D "__main__":
##qtThread =3D QMainThread(sys.argv)
##qtThread.run()
##plotThread =3D threading.Thread(target=3DqtThread.run)
plotThread =3D threading.Thread(target=3Dmain)
plotThread.start()


------=_NextPart_000_0084_01C255D2.305FE800--




More information about the PyQt mailing list