python - 如何让 Qt 异步运行以实现像 Matplotlib ion 模式那样的交互式使用?

标签 python pyqt pyside2

我希望能够从 python 解释器启动 Qt 界面,并立即返回命令行,这样我就可以在能够使用该界面的同时继续使用 python。基本上,我希望能够通过解释器与 GUI 进行交互,就像使用 matplotlib 的 ion 交互模式、或者在 jupyter 笔记本中或在 Matlab 中一样。

我天真地尝试将应用程序的执行放在线程中:

from PyQt5.QtCore import QThread
from PyQt5.QtWidgets import QApplication, QGraphicsRectItem, QGraphicsScene, QGraphicsView, QMainWindow

class Rect(QGraphicsRectItem):
  def mousePressEvent(self, event):
    print("foo")

app = QApplication([])

class AppThread(QThread):
  def run(self):
    app.exec()
    print('bar')


window = QMainWindow()
window.setGeometry(100, 100, 400, 400)
view = QGraphicsView()
scene = QGraphicsScene()
rect = Rect(0, 0, 150, 150)
scene.addItem(rect)
view.setScene(scene)
window.setCentralWidget(view)
window.show()

thread = AppThread()
thread.start()

...但这不起作用,因为生成的 GUI 被卡住,因此无法使用。

matplotlib 的后端之一是 Qt5Agg,我天真地认为这意味着我可以使用 PyQt5 或 PySide2 来实现类似的效果。

这真的有可能实现吗?

最佳答案

没有必要使用线程或另一个库的补充,你只需要执行命令,但你不应该调用 QApplication 的 exec_() 方法,因为它使用 python 交互式控制台事件循环。

$ python
Python 3.8.2 (default, Feb 26 2020, 22:21:03) 
[GCC 9.2.1 20200130] on linux
Type "help", "copyright", "credits" or "license" for more information
>>> from PyQt5.QtWidgets import QApplication, QGraphicsRectItem, QGraphicsScene, QGraphicsView, QMainWindow
>>> class Rect(QGraphicsRectItem):
...   def mousePressEvent(self, event):
...     print("foo")
... 
>>> app = QApplication([])
>>> window = QMainWindow()
>>> window.setGeometry(100, 100, 400, 400)
>>> view = QGraphicsView()
>>> scene = QGraphicsScene()
>>> rect = Rect(0, 0, 150, 150)
>>> scene.addItem(rect)
>>> view.setScene(scene)
>>> window.setCentralWidget(view)
>>> window.show()

IPython

作为IPython docs指出,必须使用 %gui backend 来启用 GUI 事件循环。对于 PyQt5/PySide2,必须在开头使用 %gui qt5

$ ipython
Python 3.8.2 (default, Feb 26 2020, 22:21:03) 
Type 'copyright', 'credits' or 'license' for more information
IPython 7.13.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: %gui qt5                                                                                                                                                                                

In [2]: from PyQt5.QtWidgets import QApplication, QGraphicsRectItem, QGraphicsScene, QGraphicsView, QMainWindow                                                                                 

In [3]: class Rect(QGraphicsRectItem): 
   ...:   def mousePressEvent(self, event): 
   ...:     print("foo") 
   ...:                                                                                                                                                                                         

In [4]: app = QApplication([])                                                                                                                                                                  

In [5]: window = QMainWindow()                                                                                                                                                                  

In [6]: window.setGeometry(100, 100, 400, 400)                                                                                                                                                  

In [7]: view = QGraphicsView()                                                                                                                                                                  

In [8]: scene = QGraphicsScene()                                                                                                                                                                

In [9]: rect = Rect(0, 0, 150, 150)                                                                                                                                                             

In [10]: scene.addItem(rect)                                                                                                                                                                    

In [11]: view.setScene(scene)                                                                                                                                                                   

In [12]: window.setCentralWidget(view)                                                                                                                                                          

In [13]: window.show()  

关于python - 如何让 Qt 异步运行以实现像 Matplotlib ion 模式那样的交互式使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60576439/

相关文章:

python - 注销响应时未设置 session Cookie HTTPOnly 标志(Django)

python - 如何在 Python 中使用 'requests' 成功登录 (GET/POST) - 409 冲突

python - 有没有办法改变所有 QMessageBox 的 OK 按钮的样式表?

python - 对特定用户进行用户身份验证

python - Thread 内调用协程

python - redis-py : What's the difference between StrictRedis() and Redis()?

python - 将 cookie jar 分配给 QWebView 时出现段错误

python - PyQt 不会将我的答案显示为 float

python - 如何设置Qframe边框的颜色?

python - 将选项卡扩展到整个窗口大小?