[英]Pyqt5 freezes after button click
當我點擊一個按鈕 inf 它的工作並且它將進入無限循環並且我想點擊另一個按鈕來停止程序但是我無法點擊另一個按鈕(停止按鈕)的問題因為我的 GUI 正在凍結我的代碼
from PyQt5 import QtCore, QtGui, QtWidgets
import sys
def retranslateUi( MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
infButton.setText(_translate("MainWindow", "inf"))
stopButton.setText(_translate("MainWindow", "stop"))
def inf_lp():
while True:
print (1)
def stop_lp():
exit(0)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
MainWindow.setObjectName("MainWindow")
MainWindow.resize(800, 600)
centralwidget = QtWidgets.QWidget(MainWindow)
centralwidget.setObjectName("centralwidget")
infButton = QtWidgets.QPushButton(centralwidget)
infButton.setGeometry(QtCore.QRect(160, 110, 89, 25))
infButton.setObjectName("infButton")
infButton.clicked.connect(inf_lp)
stopButton = QtWidgets.QPushButton(centralwidget)
stopButton.setGeometry(QtCore.QRect(400, 100, 89, 25))
stopButton.setObjectName("stopButton")
stopButton.clicked.connect(stop_lp)
MainWindow.setCentralWidget(centralwidget)
menubar = QtWidgets.QMenuBar(MainWindow)
menubar.setGeometry(QtCore.QRect(0, 0, 800, 22))
menubar.setObjectName("menubar")
MainWindow.setMenuBar(menubar)
statusbar = QtWidgets.QStatusBar(MainWindow)
statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(statusbar)
retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
這個圖像用於我的 GUI
我試着按照這個。 但我不明白如何解決這個問題,因為我的代碼中沒有使用 class
您的程序凍結的原因是因為圖形用戶界面在計算完成之前不會響應。 要繞過這個問題,您必須使用threading
將計算傳遞給另一個線程。
像這樣的東西
def main():
def clicked():
#your infinite loop
t = threading.Thread(target=clicked,daemon=True)
t.start()
#then connect your buttons
infButton.clicked.connect(main)
stopButton.clicked.connect(sys.exit())
while True
循環阻止 GUI 更新和響應更改。 基本上你必須使用threading
,或者如果你有一個 CPU 密集型算法, multiprocessing
,但是,對於 GUI,我仍然建議使用線程。 我不太了解 pyqt5,但這是 tkinter 中的相同代碼:
from tkinter import *
import threading
root = Tk()
root.geometry("300x300")
# creating a thread event
event = threading.Event()
# You can also use a boolean: stopped = False
def start_inf():
# global stopped
# stopped = False
event.set()
# while not stopped:
while event.is_set():
print(1)
else:
print("Stopped")
def stop_loop():
# global stopped
# stopped = True
event.clear()
def start_threading():
threading.Thread(target=start_inf, daemon=True).start()
start_button = Button(root, text="Start loop", command=start_threading)
stop_button = Button(root, text="Stop loop", command=stop_loop)
start_button.pack(pady=10)
stop_button.pack()
root.mainloop()
一些注意事項:將start_threading
function 綁定到您的按鈕。 其次,將你的 function 傳遞到target=
中,不帶任何括號,你不是在調用它,你只是在傳遞它。 第三,如果你的 function 有任何 arguments,在target=
參數類型args=
之后將你的 arguments 作為一個元組傳遞,如果你的 function 只有一個參數,像這樣傳遞它這樣 python 就會知道它是在一個 tuplearg 中傳遞的: (my_only_arg,)
。 注意最后一個逗號。 第四,我將daemon=
設置為True
以便線程會自動結束你的 GUI,如果你希望你的線程在 GUI 被銷毀后繼續運行,你可以將其關閉。 最后,我使用threading.Event
在線程之間進行安全通信,它們有點像布爾值,如果您想將其設置為 True,請輸入: your_event.set()
,將其設置為 False,請輸入: your_event.clear()
並檢查它是否已設置,鍵入: your_event.is_set()
(如代碼中所述,您也可以使用普通布爾值)。 我希望這對你有幫助!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.