Question QT designer GUI keeps freezing

salm2s

Honorable
Jul 21, 2017
266
6
10,815
Hi there,
So i was experimenting and designing some gui i created in QT Designer. I converted the .ui file to a .py file and wanted to link a "Start" button to a test command i set up. I managed to do that, but now everytime i click on start and the command prompt opens, the gui just freezes until i quit the command prompt? Is there a way to fix this?

Full code:

main.py:
from PyQt5 import QtCore, QtGui, QtWidgets import prompt class Ui_Form(object): def setupUi(self, Form): Form.setObjectName("Form") Form.resize(600, 300) Form.setMinimumSize(QtCore.QSize(600, 300)) Form.setMaximumSize(QtCore.QSize(600, 300)) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(""), QtGui.QIcon.Normal, QtGui.QIcon.Off) Form.setWindowIcon(icon) self.label_3 = QtWidgets.QLabel(Form) self.label_3.setGeometry(QtCore.QRect(10, 10, 431, 141)) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.label_3.sizePolicy().hasHeightForWidth()) self.label_3.setSizePolicy(sizePolicy) self.label_3.setFrameShape(QtWidgets.QFrame.Box) self.label_3.setFrameShadow(QtWidgets.QFrame.Raised) self.label_3.setWordWrap(True) self.label_3.setObjectName("label_3") self.label = QtWidgets.QLabel(Form) self.label.setGeometry(QtCore.QRect(10, 150, 66, 31)) self.label.setWordWrap(True) self.label.setObjectName("label") self.label_4 = QtWidgets.QLabel(Form) self.label_4.setGeometry(QtCore.QRect(10, 180, 71, 31)) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.label_4.sizePolicy().hasHeightForWidth()) self.label_4.setSizePolicy(sizePolicy) self.label_4.setWordWrap(True) self.label_4.setObjectName("label_4") self.label_9 = QtWidgets.QLabel(Form) self.label_9.setGeometry(QtCore.QRect(10, 210, 61, 41)) self.label_9.setWordWrap(True) self.label_9.setObjectName("label_9") self.label_10 = QtWidgets.QLabel(Form) self.label_10.setGeometry(QtCore.QRect(10, 250, 61, 41)) self.label_10.setWordWrap(True) self.label_10.setObjectName("label_10") self.lineEdit = QtWidgets.QLineEdit(Form) self.lineEdit.setGeometry(QtCore.QRect(70, 160, 211, 21)) self.lineEdit.setText("") self.lineEdit.setObjectName("lineEdit") self.lineEdit_2 = QtWidgets.QLineEdit(Form) self.lineEdit_2.setGeometry(QtCore.QRect(70, 190, 211, 21)) self.lineEdit_2.setObjectName("lineEdit_2") self.lineEdit_3 = QtWidgets.QLineEdit(Form) self.lineEdit_3.setGeometry(QtCore.QRect(70, 220, 211, 21)) self.lineEdit_3.setObjectName("lineEdit_3") self.lineEdit_4 = QtWidgets.QLineEdit(Form) self.lineEdit_4.setGeometry(QtCore.QRect(70, 250, 211, 21)) self.lineEdit_4.setObjectName("lineEdit_4") self.comboBox = QtWidgets.QComboBox(Form) self.comboBox.setGeometry(QtCore.QRect(300, 160, 51, 20)) self.comboBox.setObjectName("comboBox") self.comboBox.addItem("") self.comboBox.addItem("") self.label_2 = QtWidgets.QLabel(Form) self.label_2.setGeometry(QtCore.QRect(510, 0, 71, 71)) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.label_2.sizePolicy().hasHeightForWidth()) self.label_2.setSizePolicy(sizePolicy) self.label_2.setMaximumSize(QtCore.QSize(511, 16777215)) self.label_2.setText("") self.label_2.setPixmap(QtGui.QPixmap("")) self.label_2.setObjectName("label_2") self.label_5 = QtWidgets.QLabel(Form) self.label_5.setGeometry(QtCore.QRect(450, 10, 47, 13)) self.label_5.setOpenExternalLinks(True) self.label_5.setObjectName("label_5") self.label_6 = QtWidgets.QLabel(Form) self.label_6.setGeometry(QtCore.QRect(450, 30, 31, 16)) self.label_6.setOpenExternalLinks(True) self.label_6.setObjectName("label_6") self.label_7 = QtWidgets.QLabel(Form) self.label_7.setGeometry(QtCore.QRect(450, 50, 47, 13)) self.label_7.setOpenExternalLinks(True) self.label_7.setObjectName("label_7") self.label_8 = QtWidgets.QLabel(Form) self.label_8.setGeometry(QtCore.QRect(450, 70, 141, 51)) self.label_8.setWordWrap(True) self.label_8.setObjectName("label_8") self.pushButton = QtWidgets.QPushButton(Form) self.pushButton.setGeometry(QtCore.QRect(420, 270, 75, 23)) self.pushButton.setObjectName("pushButton") self.pushButton_2 = QtWidgets.QPushButton(Form) self.pushButton_2.setGeometry(QtCore.QRect(500, 270, 75, 23)) self.pushButton_2.setObjectName("pushButton_2") self.label_11 = QtWidgets.QLabel(Form) self.label_11.setGeometry(QtCore.QRect(300, 190, 61, 20)) self.label_11.setWordWrap(True) self.label_11.setObjectName("label_11") self.lineEdit_5 = QtWidgets.QLineEdit(Form) self.lineEdit_5.setGeometry(QtCore.QRect(360, 190, 20, 20)) self.lineEdit_5.setObjectName("lineEdit_5") self.label_12 = QtWidgets.QLabel(Form) self.label_12.setGeometry(QtCore.QRect(390, 180, 111, 41)) self.label_12.setWordWrap(True) self.label_12.setObjectName("label_12") self.pushButton_2.clicked.connect(self.cmd) self.retranslateUi(Form) QtCore.QMetaObject.connectSlotsByName(Form) def retranslateUi(self, Form): _translate = QtCore.QCoreApplication.translate Form.setWindowTitle(_translate("Form", "Yeetr")) self.label_3.setText(_translate("Form", "<html><head/><body><p><span style=\" font-weight:600;\">Some more random stufffff </span><span style=\" font-weight:600; font-style:italic; color:#ff0000;\">Evern more renreifeawodom</span></p><p><span style=\" font-weight:600; color:#000000;\">More random</span></p><p><span style=\" font-weight:600; text-decoration: underline; color:#000000;\">Lol random</span><span style=\" font-weight:600; color:#000000;\"> Click here \'Hehe\'.</span></p><p><span style=\" font-weight:600; text-decoration: underline; color:#000000;\">More random</span><span style=\" font-weight:600; color:#000000;\"> RANDOMRANDOM</span></p><p><br/></p></body></html>")) self.label.setText(_translate("Form", "MORE RANDOM")) self.label_4.setText(_translate("Form", "RandomXTXTXT")) self.label_9.setText(_translate("Form", "<html><head/><body><p>randomttz</p></body></html>")) self.label_10.setText(_translate("Form", "<html><head/><body><p>Randomttxtxtxt</p></body></html>")) self.comboBox.setItemText(0, _translate("Form", "Random")) self.comboBox.setItemText(1, _translate("Form", "More random")) self.label_5.setText(_translate("Form", "<html><head/><body><p><a href=\"https://google.com/\"><span style=\" text-decoration: underline; color:#0000ff;\">Googl</span></a></p></body></html>")) self.label_6.setText(_translate("Form", "<html><head/><body><p><a href=\"https://google.com.au\"><span style=\" text-decoration: underline; color:#0000ff;\">GOOGEL</span></a></p></body></html>")) self.label_7.setText(_translate("Form", "<html><head/><body><p><a href=\"https://forums.tomshardware.com\"><span style=\" text-decoration: underline; color:#0000ff;\">Lol what?</span></a></p></body></html>")) self.label_8.setText(_translate("Form", "<html><head/><body><p><span style=\" font-style:italic;\">\'Random </span><span style=\" font-weight:600; font-style:italic;\">More random</span><span style=\" font-style:italic;\"> Even more random\'</span></p></body></html>")) self.pushButton.setText(_translate("Form", "Stop")) self.pushButton_2.setText(_translate("Form", "Start")) self.label_11.setText(_translate("Form", "chchchchhcch")) self.label_12.setText(_translate("Form", "<html><head/><body><p>random text</p></body></html>")) def cmd(self): prompt.commandpmp() if __name__ == "__main__": import sys app = QtWidgets.QApplication(sys.argv) Form = QtWidgets.QWidget() ui = Ui_Form() ui.setupUi(Form) Form.show() sys.exit(app.exec_())


prompt.py:
import os def commandpmp(): command = 'start "" /D "test batch file" /W hi.bat' os.system(command)
 
but now everytime i click on start and the command prompt opens, the gui just freezes until i quit the command prompt?
Probably the GUI main thread/dispatcher gets blocked.
You need a thread in order to keep GUI thread responsive.

The GUI is not dead/freez, it's simply doing something else(doing all terminal/your command), so when command is done, it back to its business.

Doing long background using main GUI thread is not a good practice, so try do it using a thread to avoid GUI block.

Also mind, if the command you mentioned opens/pipes any process, so you might have blocked by some IO if you avoid any read from piped process(or vice versa).
So even if you run your command by another thread to avoid GUI thread block, you may experience the command gets blocked/freezed! That's because(for example) the piped process(you command, and its childs) echo on STDOUT where it gets filled without any read at other side, so it gets blocked becasue of blocked-IO.

Either redirect the outs to /dev/null or a file, or simply read from piped process to avoid IO block.
 
Probably the GUI main thread/dispatcher gets blocked.
You need a thread in order to keep GUI thread responsive.

The GUI is not dead/freez, it's simply doing something else(doing all terminal/your command), so when command is done, it back to its business.

Doing long background using main GUI thread is not a good practice, so try do it using a thread to avoid GUI block.

Also mind, if the command you mentioned opens/pipes any process, so you might have blocked by some IO if you avoid any read from piped process(or vice versa).
So even if you run your command by another thread to avoid GUI thread block, you may experience the command gets blocked/freezed! That's because(for example) the piped process(you command, and its childs) echo on STDOUT where it gets filled without any read at other side, so it gets blocked becasue of blocked-IO.

Either redirect the outs to /dev/null or a file, or simply read from piped process to avoid IO block.
Well, i am actually on windows :coldsweat: so idk how to do that. However, i looked up on the ‘threading’ you suggested, I saw something called QEventloop? Is that in c++, or can i use it in python as well? Can you also give a short example, it would rly help
 
However, i looked up on the ‘threading’ you suggested, I saw something called QEventloop? Is that in c++, or can i use it in python as well?
I'm not QT expert, neither C++ fan, but note threading is possible in python too.

You could try run the command(that blocks the UI) using a thread/subroutine, example:

Can you also give a short example, it would rly help

Here it is, a simple app that does two jobs simultaneously, now run your command instead of sample commands. Hope it helps.
import threading;
import os;
from time import sleep;

Python:
import threading;
import os;
from time import sleep;

def run_cmd():
    cmd="echo \"Hello!\"";
    os.system(cmd);
    #if you are on unix, then sleep 10s should work, otherwise(windows)
    #hacky wait to wait for 10 seconds in CMD
    #https://stackoverflow.com/questions/735285/how-to-wait-in-a-batch-script
    cmd="ping 192.0.2.2 -n 1 -w 10000 > nul";
    os.system(cmd);
    print("Thread finished");

thread_ptr=threading.Thread(target=run_cmd);
print("starting thread...");
thread_ptr.start();
for i in range(5):
    print("HEy!");
    sleep(1);
print("joining thread(wait till it gets finished)");
thread_ptr.join();
print("App finished!");


Also mind about process pipes! if you app opens a new process, and associate the STDIN/STDOUT to a terminal, then you might not have any IO block, otherwise, make sure you free up the buffer/backlog in order to avoid IO block.
 
I'm not QT expert, neither C++ fan, but note threading is possible in python too.

You could try run the command(that blocks the UI) using a thread/subroutine, example:



Here it is, a simple app that does two jobs simultaneously, now run your command instead of sample commands. Hope it helps.
import threading;
import os;
from time import sleep;

Python:
import threading;
import os;
from time import sleep;

def run_cmd():
    cmd="echo \"Hello!\"";
    os.system(cmd);
    #if you are on unix, then sleep 10s should work, otherwise(windows)
    #hacky wait to wait for 10 seconds in CMD
    #https://stackoverflow.com/questions/735285/how-to-wait-in-a-batch-script
    cmd="ping 192.0.2.2 -n 1 -w 10000 > nul";
    os.system(cmd);
    print("Thread finished");

thread_ptr=threading.Thread(target=run_cmd);
print("starting thread...");
thread_ptr.start();
for i in range(5):
    print("HEy!");
    sleep(1);
print("joining thread(wait till it gets finished)");
thread_ptr.join();
print("App finished!");


Also mind about process pipes! if you app opens a new process, and associate the STDIN/STDOUT to a terminal, then you might not have any IO block, otherwise, make sure you free up the buffer/backlog in order to avoid IO block.
Ah thank you. I tried implementing your code into my program just as a test, but now it runs your program first before the GUI! How can i fix this? Sorry for asking you this much, your help is rly good!
 
now it runs your program first before the GUI! How can i fix this?
That's okay, becasue you have two threads, and each one would do its job ASAP, and logically since the background-cmd works is much easier/lighter than GUI thread, so it gets executed first.

In you app as you stated, when the start button is clicked, so you call a thread that performs your task at background in a separate thread to avoid UI blocking. My code is just an example.
You may run a new thread whenever you think it's needed, not always by app startup. So by your app start click event, you go for a thread run for your command. Hope it helps
 
That's okay, becasue you have two threads, and each one would do its job ASAP, and logically since the background-cmd works is much easier/lighter than GUI thread, so it gets executed first.

In you app as you stated, when the start button is clicked, so you call a thread that performs your task at background in a separate thread to avoid UI blocking. My code is just an example.
You may run a new thread whenever you think it's needed, not always by app startup. So by your app start click event, you go for a thread run for your command. Hope it helps
Well I don't really want the command to start first. I want to make it so that when the user presses start, it opens a new cmd window and executes the command in there. Is there a way I can make the app start first?
 
when the user presses start, it opens a new cmd window and executes the command in there
So it goes like this, run the app in GUI form(QT dispatch)
Set the click event for that(start) button you wish to run your app.
Later, when button is clicked, QT dispatch will run your associated handler. From there, create a new thread, and run your command with it.