Can't use X at top, right of app to stop the app have while loop is running
-
hello guy! i have this problem:
- i use qt designer 5.14.1 to make an app and use pycharm to make python code
- if in my code have while loop and i try to stop the program with X at top, right of app it's not working, my app is freeze and error
- i can stop while loop with a button use thread and keyboard, but it's not a good program, because nowadays all apps are off by click X at top, right of app
- please help me, how can i use X to stop the app have while loop inside
-
hello guy! i have this problem:
- i use qt designer 5.14.1 to make an app and use pycharm to make python code
- if in my code have while loop and i try to stop the program with X at top, right of app it's not working, my app is freeze and error
- i can stop while loop with a button use thread and keyboard, but it's not a good program, because nowadays all apps are off by click X at top, right of app
- please help me, how can i use X to stop the app have while loop inside
-
@tran-con Please provide minimal compilable code because the solution depends on your implementation.
@eyllanesc here is my code
import sys
from PyQt6.QtWidgets import QApplication, QMainWindow
from gui import Ui_MainWindow
import timeclass MainWindow:
def init(self):self.main_win = QMainWindow() self.uic = Ui_MainWindow() self.uic.setupUi(self.main_win) self.uic.Button_read_cell.clicked.connect(self.start_while) def start_while(self): print("start run") global a a = True self.while_loop() def while_loop(self): print("ready") while a == True: time.sleep(0.5) print('run') def show(self): self.main_win.show()if name == "main":
app = QApplication(sys.argv) main_win = MainWindow() main_win.show() sys.exit(app.exec()) -
@eyllanesc here is my code
import sys
from PyQt6.QtWidgets import QApplication, QMainWindow
from gui import Ui_MainWindow
import timeclass MainWindow:
def init(self):self.main_win = QMainWindow() self.uic = Ui_MainWindow() self.uic.setupUi(self.main_win) self.uic.Button_read_cell.clicked.connect(self.start_while) def start_while(self): print("start run") global a a = True self.while_loop() def while_loop(self): print("ready") while a == True: time.sleep(0.5) print('run') def show(self): self.main_win.show()if name == "main":
app = QApplication(sys.argv) main_win = MainWindow() main_win.show() sys.exit(app.exec()) -
@tran-con You say: i can stop while loop with a button use thread and keyboard, could you show that code?
this code stop while loop by use thread method
sorry about the way it show the code, i don't know why it show all the code like that
hope in future i can stop the app only press X at top, right of the app
if you want the code to stop while loop with the keyboard tell meimport sys
from PyQt6.QtWidgets import QApplication, QMainWindow
from gui import Ui_MainWindow
import time
import threading
class MainWindow:
def init(self):
self.main_win = QMainWindow()
self.uic = Ui_MainWindow()
self.uic.setupUi(self.main_win)
self.uic.Button_read_cell.clicked.connect(self.start_while)
self.uic.Button_add_row.clicked.connect(self.stop_while)
def stop_while(self):
print("stop")
global a
a = False
def start_while(self):
print("start run")
global a
a = True
self.while_loop()
def while_loop(self):
print("ready")
def run():
while a == True:
time.sleep(0.5)
print('run')
if a == False:
break
t1 = threading.Thread(target=run)
t1.start()def show(self): self.main_win.show()if name == "main":
app = QApplication(sys.argv)
main_win = MainWindow()
main_win.show()
sys.exit(app.exec()) -
this code stop while loop by use thread method
sorry about the way it show the code, i don't know why it show all the code like that
hope in future i can stop the app only press X at top, right of the app
if you want the code to stop while loop with the keyboard tell meimport sys
from PyQt6.QtWidgets import QApplication, QMainWindow
from gui import Ui_MainWindow
import time
import threading
class MainWindow:
def init(self):
self.main_win = QMainWindow()
self.uic = Ui_MainWindow()
self.uic.setupUi(self.main_win)
self.uic.Button_read_cell.clicked.connect(self.start_while)
self.uic.Button_add_row.clicked.connect(self.stop_while)
def stop_while(self):
print("stop")
global a
a = False
def start_while(self):
print("start run")
global a
a = True
self.while_loop()
def while_loop(self):
print("ready")
def run():
while a == True:
time.sleep(0.5)
print('run')
if a == False:
break
t1 = threading.Thread(target=run)
t1.start()def show(self): self.main_win.show()if name == "main":
app = QApplication(sys.argv)
main_win = MainWindow()
main_win.show()
sys.exit(app.exec()) -
@tran-con I think that is the correct way since you should not execute a while loop in the main thread and less use time.sleep. The only bad thing is that you use global variables.
@eyllanesc please give me an example the code to stop the while loop with "X close" button
-
The basic idea is quite simple: A single thread can only do one thing at a time. If you let it handle your while loop it cannot respond to user interactions at the same time. The main thread (which will start running when you start your application) has an event loop running which will react to mouse and keyboard input (besides other things). Whenever you block the main thread (in your case by running you own loop) it cannot handle any input. Even the
sleepwill put the main thread to sleep and not allow the event loop to run instead. You should return to the main thread as soon as possible (in Qt, but also in any GUI application) for your app to stay reactive. Putting your workload into a separate thread is one common solution.I am not sure about your real application of a while loop. However, if you do sleeps in between you might want to try a timer instead. For each timeout there will be an event in the event loop. But, this event is interleaved with other events. This would avoid blocking any input from happening.
Another trick is to call
QCoreApplication.processEventsevery now and then in your own loop. This will also process the event which are stuck in the event loop you are blocking. From my own experience this approach can slow your actual work down by a lot if you have a really heavy workload. Using a separate thread is preferred then.