Python PyQt:app.exec_() 停止所有以下代码运行

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23142719/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 02:20:00  来源:igfitidea点击:

PyQt: app.exec_() stops all following code from running

pythonpyqtpyqt4

提问by cgf

I have a code which looks like:

我有一个代码,看起来像:

app = QApplication(sys.argv)
self.interface = Interface()

# The figure
self.fig = self.interface.fig
self.ax = self.fig.add_subplot(111)

self.interface.show()
app.exec_()

print 'this is not printed'

The problem is that once app.exec_()is executed, nothing is until I close the window that pops up.

问题是,一旦app.exec_()执行,直到我关闭弹出的窗口。

How can I continue running the code?

如何继续运行代码?

采纳答案by Hyman

That is intended. What you have to do is use signals/slots, code inside your Qt classes, or spawn off threads before you call app.exec().

这是有意的。您需要做的是在调用 app.exec() 之前使用信号/插槽、Qt 类中的代码,或者生成线程。

Signals and slots are your defacto way of interacting with Qt. Basically a signal is any "event" or custom "event" and slots can be thought of as "event handlers". For instance when someone hits a button on a GUI it creates a signal that seeks out any handler that is connected to it. You can connect none, one, or many slots to each signal (you can even connect the same one multiple times)! Here is a good referencefor this in python.

信号和槽是您与 Qt 交互的实际方式。基本上,信号是任何“事件”或自定义“事件”,槽可以被认为是“事件处理程序”。例如,当有人点击 GUI 上的按钮时,它会创建一个信号,寻找连接到它的任何处理程序。您可以将一个、一个或多个插槽连接到每个信号(您甚至可以多次连接相同的一个)!这是python中的一个很好的参考

Coding inside your Qt classes usually means creating slots that do useful work for you. Remember you don't want to hold up the event loop too long so spawn a new thread if you do this.

在 Qt 类中编码通常意味着创建对您有用的插槽。请记住,您不想让事件循环拖得太久,因此如果您这样做,请生成一个新线程。

The third option available to you is to spin off other threads. Be careful interacting with Qt from threads, if you do you MUST us signals and slots. Implement threading as suggested in this SO.

您可以使用的第三个选项是剥离其他线程。小心从线程与 Qt 交互,如果你这样做,你必须使用信号和插槽。按照此 SO 中的建议实施线程。

回答by Oliver

app.exec_()does not lock anything, it runs a GUI event loop that waits for user actions (events) and dispatches them to the right widget for handling. It does this until there are no top level windows left open; if you leave at least one top level window of your app open, then exec() never returns, it can't (your app will be terminated during system shutdown). When no more top level windows the app cleans up and returns from exec(). At that point the GUI is no longer in the event loop.

app.exec_()不锁定任何东西,它运行一个 GUI 事件循环,等待用户操作(事件)并将它们分派到正确的小部件进行处理。它会这样做,直到没有顶层窗口打开;如果您将应用程序的至少一个顶级窗口保持打开状态,则 exec() 永远不会返回,它不能(您的应用程序将在系统关闭期间终止)。当没有更多的顶级窗口时,应用程序会清理并从exec(). 此时 GUI 不再处于事件循环中。

Whatever it is you want to do after exec()it is likely you would either put it in a QThread or in a signal handler (which you would connect, for example, to a "Go!" button; you would connect a "Cancel" button to a handler that closes the app window).

无论您想做什么,exec()您都可能会将它放在 QThread 或信号处理程序中(例如,您可以将其连接到“Go!”按钮;您可以将“取消”按钮连接到关闭应用程序窗口的处理程序)。

You can put code after exec()but it would be rather unconventional: if anything goes wrong it is unlikely that user can see the problem since the GUI is no longer visible, a GUI app doesn't usually have a console terminal open where the error might be seen, there will not typically be a console for a GUI app (ie you will run the app via pythonw.exeinstead of python.exe), or you have to open a new window and exec() again in order to show an error message and wait till user clicks ok, destroy message window in ok handler so app.exec()once again returns.

您可以在其后放置代码,exec()但这将是非常规的:如果出现任何问题,用户不太可能看到问题,因为 GUI 不再可见,GUI 应用程序通常不会在可能出现错误的地方打开控制台终端可以看到,GUI 应用程序通常没有控制台(即您将通过pythonw.exe而不是运行应用程序python.exe),或者您必须再次打开一个新窗口和 exec() 以显示错误消息并等待用户单击好的,在 ok 处理程序中销毁消息窗口,以便app.exec()再次返回。

回答by Виталий Белоусов

In addition to the previous answer, not every time when all windows are closed does the GUI event loop, run by app.exec_(), stop. If you want to terminate it manually you can use app.quit()inside any of the event handlers. It stops GUI event loop and launches your code after app.exec_().

除了前面的答案之外,并非每次关闭所有窗口时都会执行 GUI 事件循环、 run by app.exec_()、 stop 。如果您想手动终止它,您可以app.quit()在任何事件处理程序中使用。它停止 GUI 事件循环并在app.exec_().

First answer is a lot of words about nothing.

第一个答案是很多关于无的词。

回答by user12835412

A dirty trick to remove blocking would be to abuse mathplot lib:

消除阻塞的一个肮脏技巧是滥用 mathplot lib:

import matplotlib
import matplotlib as mpl

import matplotlib.cbook as cbook
import matplotlib.collections as mcol
import matplotlib.patches as mpatches
import matplotlib.mlab as mlab
import matplotlib.pyplot as plt
import matplotlib.cm as cm       # colors 
from   mpl_toolkits.mplot3d import Axes3D   # imports options for 3-D plotting
from   matplotlib.backends.backend_pdf import PdfPages

from PyQt5 import QtWidgets, uic
# ============================================================== 
if not QtWidgets.QApplication.instance():
    app = QtWidgets.QApplication(sys.argv)
else:
    app = QtWidgets.QApplication.instance() 
#endelse

MainWindow =  QtWidgets.QMainWindow()
MainWindow=uic.loadUi('E:\Python\Python_lib\MyGui.ui',MainWindow)
MainWindow.show()

# There are two ways to start the gui, and i.e. it looping 
# The correct way if to use app.exec_(), which 
# blocks the command line :


#d=app.exec_()

# However, this will block the command line making 
# We can misuse mathplot lib creating a Figure instead
# which seems to start the Gui loop without blocking the command line: 

ImageFig = Figure((3,4))
ImagePanel = FigureCanvas(ImageFig)
ImagePanel.draw()