Как заставить Qt работать асинхронно для интерактивного использования, такого как ионный режим Matplotlib? - PullRequest
1 голос
/ 07 марта 2020

Я хочу иметь возможность запускать интерфейс Qt из интерпретатора python, с командной строкой, возвращающейся немедленно, чтобы я мог продолжать использовать python, при этом используя интерфейс. По сути, я хотел бы иметь возможность взаимодействовать с GUI из интерпретатора, как это можно сделать в интерактивном режиме ion matplotlib, или в блокноте 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 для достижения аналогичного эффекта.

Действительно ли это возможно?

1 Ответ

1 голос
/ 07 марта 2020

Нет необходимости использовать поток или дополнение другой библиотеки, вы просто должны выполнить команды, но не должны вызывать метод exec_ () QApplication, поскольку он использует интерактивную консоль python eventl oop .

$ 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()

I Python

Поскольку I Python 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()  
...