通过 ipython/jupyter notebook 单元格更新 PyQt 小部件

4

我有一个烦人的问题,过去几个月来一直没有解决。基本上,我使用jupyter/ipython笔记本调用pyqt并显示3D几何数据。这是如何将应用程序初始化为对象的方式,添加一些多边形和点之后,我调用show():

class Figure(object):
    '''
    Main API functions
    '''

    def __init__(self):
        print "... initializing canvas ..."
        self.app = QApplication(sys.argv)
        self.app.processEvents()
        ...

    def show(self):   #Show
        self.GUI = GLWindow(data)   
        self.app.exec_()

我希望能够通过笔记本单元格持续地与小部件进行交互/更新。但是,一旦我在Jupyter笔记本中调用show()命令,我就无法再运行任何单元格或更新小部件,因为笔记本输出会被排队(?)并锁定:

#Initialize figure object inside the notebook
fig = plb.figure()
...
fig.show()  #Locks out any further jupyter commands while widget on screen
fig.update() #Does not get executed until widget is closed

似乎通过notebook调用的.show()函数会放弃对python内核的控制,但如何重新获取控制权以及如何连接到正在显示的小部件仍然不清楚。
鼠标和键盘事件确实与小部件交互,但它们使用内在的函数,例如mouseMoveEvent(),这些函数在小部件代码中。
    class GLWindow(QtGui.QWidget):

        def __init__(self, fig, parent=None):
            QtGui.QWidget.__init__(self, parent)

            self.glWidget = GLWidget(fig, parent=self)
            ...

    class GLWidget(QtOpenGL.QGLWidget):

            def __init__(self, fig, parent=None):
                QtOpenGL.QGLWidget.__init__(self, parent)
                ...

            def mouseMoveEvent(self, event):
                buttons = event.buttons()
                modifiers = event.modifiers()
                dx = event.x() - self.lastPos.x()
                dy = event.y() - self.lastPos.y()
                ...

我尝试按照相关建议进行操作,但是我不知道如何在小部件之外使用连接或事件。

如果能得到帮助,我将非常感激,因为我已经花了很多时间来尝试解决这个问题,这让我感到很尴尬。 Cat

1个回答

8
我在Jupyter论坛上得到帮助,找到了解决方案。显然,笔记本中有一个运行时技巧,可以在这里动态地与glwindow交互。非常高兴终于解决了这个问题...。以下是整个函数,以防那个示例在将来被删除:

https://github.com/ipython/ipython/blob/master/examples/IPython%20Kernel/gui/gui-qt.py

#!/usr/bin/env python
"""Simple Qt4 example to manually test event loop integration.
This is meant to run tests manually in ipython as:

In [5]: %gui qt

In [6]: %run gui-qt.py

Ref: Modified from http://zetcode.com/tutorials/pyqt4/firstprograms/
"""

from PyQt4 import QtGui, QtCore

class SimpleWindow(QtGui.QWidget):
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)

        self.setGeometry(300, 300, 200, 80)
        self.setWindowTitle('Hello World')

        quit = QtGui.QPushButton('Close', self)
        quit.setGeometry(10, 10, 60, 35)

        self.connect(quit, QtCore.SIGNAL('clicked()'),
                     self, QtCore.SLOT('close()'))

if __name__ == '__main__':
    app = QtCore.QCoreApplication.instance()
    if app is None:
        app = QtGui.QApplication([])

    sw = SimpleWindow()
    sw.show()

    try:
        from IPython.lib.guisupport import start_event_loop_qt4
        start_event_loop_qt4(app)
    except ImportError:
        app.exec_()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接