Update PyQt widget through ipython/jupyter notebook cells
我有一个令人讨厌的问题,在过去的几个月里我无法解决。基本上,我使用jupyter / ipython笔记本来调用pyqt并显示3d几何数据。这是我将应用程序初始化为对象的方式,在我添加一些多边形和点之后,我调用show():
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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()命令,我就无法运行任何更多单元格或更新小部件,因为笔记本输出排队(?)并被锁定:
1 2 3 4 5 | #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 |
似乎通过笔记本调用的.show()函数放弃了对python内核(?)的控制,但是不清楚如何将其取回,以及如何将其连接到正在显示的小部件。
鼠标和键盘事件确实与窗口小部件交互,但它们使用内部函数,如mouseMoveEvent(),它们位于窗口小部件代码中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | 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() ... |
我试图遵循相关的建议,但我不明白如何使用小部件之外的连接或事件。
任何帮助表示赞赏,我花了这么多时间试图解决这个问题令人尴尬。猫
我在jupyter论坛的帮助下找到了解决方案。 显然,笔记本中有一个运行时技巧,可以让你动态地与glwindow交互。 很高兴终于解决这个问题......
https://github.com/ipython/ipython/blob/master/examples/IPython%20Kernel/gui/gui-qt.py
这是整个函数,以防将来删除示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | #!/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_() |