update the progressBar value from emitted signal - python

getting the CPU percentage from psutil and display it on a progress bar.
i was able to display the value of the CPU percentage but it's not updating.
i have a file from QT designer called Progress i convert it using pyuic5 to py file and import it in the main file called cpuprogress.py, also i created a python file called sysinfo to get the value of CPU percentage and import it to the main file.
import sys
from PyQt5 import QtGui, QtCore
from PyQt5.QtCore import QThread, pyqtSignal
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import (QWidget, QApplication)
from progress import Ui_Form
import sysinfo
class MyTest(QWidget, Ui_Form):
def __init__(self, parent = None):
super(MyTest, self).__init__(parent)
self.setupUi(self)
self.threadclass = ThreadCLass()
self.threadclass.start()
self.threadclass.change_value.connect(self.updateProgressBar)
def updateProgressBar(self, val):
self.progressBar.setValue(val)
class ThreadCLass(QThread):
change_value = pyqtSignal(int)
def __init__(self, parent = None):
super(ThreadCLass, self).__init__(parent)
def run(self):
while 1:
val = int(sysinfo.getCPU())
self.change_value.emit(val)
a =QApplication(sys.argv)
window = QWidget()
app = MyTest()
app.setupUi(window)
app.show()
sys.exit(a.exec_())
enter image description here

tl;dr
The problem is that you called setupUi twice, and the second time it was using another widget as argument.
Why doesn't it work?
When you generate a file with pyuic, it actually creates a class, based on Python's object type. That class doesn't do anything on itself, is just an "interface" to load the elements of the ui in a "pythonic way".
If you try to open one of those files (which should never be edited!), you'll see something like this:
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
self.progressBar = QtWidgets.QProgressBar(Form)
self.progressBar.setProperty("value", 24)
# ...
def retranslateUi(self, Form):
# things related to the localization of the ui
The official guide on using Designer reports as a first example that actually does nothing, besides showing the window.
from PyQt5.QtWidgets import QApplication, QWidget
from ui_form import Ui_Form
# create an instance of the base class
window = QWidget()
# create an instance of the Ui "builder"
ui = Ui_Form()
# apply the ui to the base class created before
ui.setupUi(window)
The last step is the most important to understand: look carefully to what object the setupUi method belongs, and its argument, then go back to the contents of the file created with pyuic:
def setupUi(self, Form):
Form.setObjectName("Form")
self.progressBar = QtWidgets.QProgressBar(Form)
Form is the QWidget instance created before ("window"), while obviously self refers to the instance of Ui_Form; let's translate the variables with the name of the instancies they represent:
def setupUi(ui, window):
window.setObjectName("Form")
ui.progressBar = QtWidgets.QProgressBar(window)
In the example at the beginning it means that, while window is displayed with its children widgets, they are not attributes of the instance: there's no window.progressBar.
The second example in the documentation shows the "single inheritance" method, that allows the implementation of interactions between widgets (the "logic"). I'll use the class names as I did above:
from PyQt5.QtWidgets import QApplication, QWidget
from ui_form import Ui_Form
class MyWidget(QWidget):
def __init__(self):
super(MyWidget, self).__init__()
self.ui = Ui_Form()
self.ui.setupUi(self)
Now ui is an attribute of the window instance; let's "translate" setupUi once again, assuming that now "self" is the instance of MyWidget that is being created:
class Ui_Form(object):
def setupUi(window.ui, window):
window.setObjectName("Form")
window.ui.progressBar = QtWidgets.QProgressBar(window)
This means that now you can have access to the widgets from the window instance, but only through self.ui (as in, window.ui).
Now, let's see the multiple inheritance approach, which is very similar:
class MyWidget(QWidget, Ui_Form):
def __init__(self):
super(MyWidget, self).__init__()
self.setupUi(self)
In this case, MyWidget inherits from the methods and attributes of both Qwidget and Ui_Form. Let's translate it again (note the class):
class MyWidget(object):
def setupUi(window, window):
window.setObjectName("Form")
window.progressBar = QtWidgets.QProgressBar(window)
This approach makes all widgets as direct attributes of the instance (self.progressBar, etc), and I usually suggest it as it's more direct and simple (it often happens that you try to access a widget and forget that ui prefix, with this method it doesn't happen).
Now, finally, your problem.
window = QWidget()
app = MyTest()
setupUi is called in the __init__ of MyTest, which means that app has an attribute called progressBar, which at this point should be "visible" as soon as we call app.show().
You also created another widget, though (window), and used setupUi using that as parameter:
app.setupUi(window)
Let's translate it one last time (to avoid confusion, let's change the name of the "window" QWidget you created by mistake):
def setupUi(app, otherWindow):
otherWindow.setObjectName("Form")
app.progressBar = QtWidgets.QProgressBar(otherWindow)
As you can see, now you've "overwritten" the app.progressBar attribute, but that progress bar is actually a new one, and it is a child of window (which you never show).
The updateProgressBar function then will successfully modify the value of the progress bar, but not the one you see.
Finally, there's also another way of using ui files, and it is through the uic module, which can directly load ui files.
from PyQt5 import QtWidgets, uic
class MyTest(QtWidgets.QWidget):
def __init__(self, parent=None)
super().__init__(parent)
uic.loadUi('mywindow.ui', self)
This approach as a big advantage on the other: you don't have to create files with pyuic anymore, and it behaves exactly as the multiple inheritance method, so you can use self.progressBar as you did before.

Related

Transfer QMessageBox setting to a separate class in Python

I've used QtDesigner to make ui files that I then use to make classes, like
class MyPopup1(MyBaseClass, MyClass):
def __init__(self, parent=None):
super(MyPopup1, self).__init__(parent)
self.setupUi(self)
...
Granted I used some tutorial for this so I'm not actually sure what all of that does. But now I have written code that generates a popup that uses the QMessageBox class and I would like to move this code to a separate class so I can call it from multiple places.
How do I move this code to make a MyPopup2 class?
MyPopup2 = QtWidgets.QMessageBox(parent = self.central_widget)
MyPopup2.setWindowTitle("My Popup 2")
MyPopup2.setText("Some text")
MyPopup2.setIcon(QtWidgets.QMessageBox.Question)
MyPopup2.addButton("Btn1", QtWidgets.QMessageBox.RejectRole)
MyPopup2.addButton("Btn2", QtWidgets.QMessageBox.ActionRole)
choice = MyPopup2.exec_()
I know I probably need to connect the button signals to functions and use self.done() to send the result back to a call.
I am mostly confused on what to put as MyBaseClass and MyClass for the second popup.
Qt Designer provides a class that serves to fill a widget, so a recommended way is to inherit a widget and inherit from the generated class of Qt Designer, for example the structure that Qt Designer provides has the following structure:
class MyClass(object):
def setupUi(self, AAA):
...
self.retranslateUi(AAA)
QtCore.QMetaObject.connectSlotsByName(AAA)
def retranslateUi(self, AAA):
...
Then depending on the template you should choose as MyBaseClass to QMainWindow, QDialog or QWidget and call setupUi() which is the method that you add the other widget to the window as you point out:
class MyPopup1(MyBaseClass, MyClass):
def __init__(self, parent=None):
super(MyPopup1, self).__init__(parent)
self.setupUi(self)
...
But in the case that you are going to create the widget, MyClass is not necessary, so in your case the solution is the following:
from PyQt5 import QtWidgets
class MyPopup2(QtWidgets.QMessageBox):
def __init__(self, parent=None):
super(MyPopup2, self).__init__(parent)
self.setWindowTitle("My Popup 2")
self.setText("Some text")
self.setIcon(QtWidgets.QMessageBox.Question)
self.addButton("Btn1", QtWidgets.QMessageBox.RejectRole)
self.addButton("Btn2", QtWidgets.QMessageBox.ActionRole)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
popup = MyPopup2()
if popup.exec_() == QtWidgets.QMessageBox.Accepted:
print("Btn2")
else:
print("Btn1")
The full solution for the example is
class MyPopup2(QtWidgets.QMessageBox):
def __init__(self, parent=None):
super(NoMatch, self).__init__(parent)
self.setWindowTitle("My Popup 2")
self.setText("Some text")
self.setIcon(QtWidgets.QMessageBox.Question)
self.Btn1 = self.addButton("Btn1", QtWidgets.QMessageBox.RejectRole)
self.Btn2 = self.addButton("Btn2", QtWidgets.QMessageBox.ActionRole)
self.Btn1.clicked.connect(lambda: self.done(QtWidgets.QMessageBox.RejectRole))
self.Btn2.clicked.connect(lambda: self.done(QtWidgets.QMessageBox.ActionRole))
Which can be called with choice = MyPopup2.exec_() from anywhere

How to load second .ui into self with PyQt4.uic.loadUi?

I'm creating an application which loads a couple of .ui files. The first one is of type QMainWindow and the others are of type QWidget.
I can't figure out how to load the second UI (module.ui) into self, making widgets accessible through self.<widget_name>.
How can this be achieved?
from PyQt4 import QtGui
from PyQt4 import uic
class TestApp(QtGui.QMainWindow):
def __init__(self):
super(TestApp, self).__init__()
# Load main window and the module
uic.loadUi('main_window.ui', self) # QMainWindow, contains testLayout, loads into self
ui_module = uic.loadUi('module.ui') # QWidget
# Attach module to main window
self.testLayout.addWidget(ui_module) # this works fine
# Edit widget in UI module
self.label.setText('Hello') # does not work (since self.label doesn't exist)
I could do this:
self.label = ui_module.label
self.label.setText('Hello')
...but I'd like to instead load the UI into self from the start.
If I try to load the UI into self, I get an error:
uic.loadUi('module.ui', self)
>>> QLayout: Attempting to add QLayout "" to TestApp "Form", which already has a layout
You need to create a widget to load the ui file onto
self.widget = QWidget(self)
uic.loadUi('module.ui', self.widget)
self.widget.label.setText('Hello')
That being said, it would probably be better if you created a separate class for the other widget.
class MyWidget(QWidget):
def __init__(self, **args, **kwargs):
super(MyWidget, self).__init__(*args, **kwargs)
uic.loadUi('module.ui', self)
self.label.setText('Hello')
class TestApp(QtGui.QMainWindow):
def __init__(self):
...
self.widget = MyWidget(self)

PyQt5 signal-slot decorator example

I am currently in the process of creating a class that produces a pyqtSignal(int) and pyqtSlot(int). The difficulty lies in creating a signal that emits a specific value.
Suppose I want to produce something similar to the following simple example:
import sys
from PyQt5.QtCore import (Qt, pyqtSignal, pyqtSlot)
from PyQt5.QtWidgets import (QWidget, QLCDNumber, QSlider,
QVBoxLayout, QApplication)
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def printLabel(self, str):
print(str)
#pyqtSlot(int)
def on_sld_valueChanged(self, value):
self.lcd.display(value)
self.printLabel(value)
def initUI(self):
self.lcd = QLCDNumber(self)
self.sld = QSlider(Qt.Horizontal, self)
vbox = QVBoxLayout()
vbox.addWidget(self.lcd)
vbox.addWidget(self.sld)
self.setLayout(vbox)
self.sld.valueChanged.connect(self.on_sld_valueChanged)
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Signal & slot')
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
My first question for the above code is:
Why use the pyqtSlot() decorator at all when removing pyqtSlot(int) has no effect on the code?
Can you give an example of when it would be necessary?
For specific reasons, I would like to produce my own signal using the pyqtSignal() factory and am given decent documentation here. The only problem however, is that the very simple example does not give a solid foundation for how to emit specific signals.
Here is what I am trying to do but have found myself lost:
Create a metaclass that allows for the implementation of many different types of QWidget subclasses.
Have the metaclass produce its own signal that can be called from outside the class.
This is what I am going for:
from PyQt5.QtWidgets import QPushButton, QWidget
from PyQt5.QtCore import pyqtSignal, pyqtSlot
from PyQt5.QtWidgets import QSlider
def template(Q_Type, name: str, *args):
class MyWidget(Q_Type):
def __init__(self) -> None:
super().__init__(*args)
self._name = name
def setSignal(self,type):
self.signal = pyqtSignal(type)
def callSignal(self):
pass
return MyWidget
As you can see. I give the widget a name because I find this to be useful, and I also try to instantiate the QWidget from within the class to simplify code.
This is how I would like a main class to produce the widgets from the first example:
import sys
from PyQt5.QtCore import (Qt, pyqtSignal, pyqtSlot)
from PyQt5.QtWidgets import (QWidget, QLCDNumber, QSlider,
QVBoxLayout, QApplication)
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def printLabel(self, str):
print(str)
#pyqtSlot(int)
def sld_valChanged(self, value):
self.lcd.display(value)
self.printLabel(value)
def initUI(self):
#instantiate the QWidgets through template class
self.lcd = template(QLCDNumber,'lcd_display')
self.sld = template(QSlider, 'slider', Qt.Horizontal)
#create signal
#self.sld.setSignal(int)
vbox = QVBoxLayout()
vbox.addWidget(self.lcd)
vbox.addWidget(self.sld)
self.setLayout(vbox)
#connect signal - this won't send the value of the slider
#self.sld.signal.connect(self.sld_valChanged)
self.sld.valueChanged.connect(self.sld_valChanged)
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Signal & slot')
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
There are only 2 problems that need to be solved here:
The template metaclass is set up incorrectly, and I am unable to instantiate the QWidget from within the metaclass. The Q_Type is telling me that its type is PyQt5.QtCore.pyqtWrapperType when it should be PyQt5.QtWidgets.QSlider.
Even though I am creating a newSignal via the templated class, how do I get the QSlider to send the changed value that I want it to send. I believe this is where emit() comes into play but do not have enough knowledge as to how it is useful.
I know I could make some sort of function call self.sld.emit(35) if I would like the signal to pass the value 35 to the slot function. The question becomes not how but where should I implement this function?
I may be totally offbase and overthinking the solution, feel free to correct my code so that I can have my signal emit the value of the slider.
Why use the pyqtSlot() decorator at all when removing pyqtSlot(int)
has no effect on the code? Can you give an example of when it would be
necessary?
Already addressed in your previous question, but I'll re-iterate again.
Although PyQt4 allows any Python callable to be used as a slot when
connecting signals, it is sometimes necessary to explicitly mark a
Python method as being a Qt slot and to provide a C++ signature for
it. PyQt4 provides the pyqtSlot() function decorator to do this.
Connecting a signal to a decorated Python method also has the
advantage of reducing the amount of memory used and is slightly
faster.
Also, as addressed in your previous question, you cannot create signals as instance variables, they must be class attributes.
This will never work
def setSignal(self,type):
self.signal = pyqtSignal(type)
It must be
class MyWidget(QWidget):
signal = pyqtSignal(int)
Create a metaclass that allows for the implementation of many different types of QWidget subclasses.
You cannot define a metaclass for QObjects, since they already use their own metaclass (this is what allows the signal magic to work). However, you can still make a QObject subclass factory using the type function.
def factory(QClass, cls_name, signal_type):
return type(cls_name, (QClass,), {'signal': pyqtSignal(signal_type)})
MySlider = factory(QSlider, 'MySlider', int)
self.sld = MySlider(Qt.Horizontal)
self.sld.signal.connect(self.on_signal)
Have the metaclass produce its own signal that can be called from outside the class.
In short, don't do this. You shouldn't be emitting signals from outside the class. The factory example above isn't very useful, because you're not defining custom methods on those classes to emit those signals. Typically, this is how you would utilize custom signals
class MyWidget(QWidget):
colorChanged = pyqtSignal()
def setColor(self, color):
self._color = color
self.colorChanged.emit()
class ParentWidget(QWidget):
def __init__(self):
...
self.my_widget = MyWidget(self)
self.my_widget.colorChanged.connect(self.on_colorChanged)
# This will cause the colorChanged signal to be emitted, calling on_colorChanged
self.my_widget.setColor(Qt.blue)
def on_colorChanged(self):
# do stuff

Is it possible to have PySide's QUIloader act like PyQt's uic.loadUi? [duplicate]

This question already has an answer here:
How do I load children from .ui file in PySide?
(1 answer)
Closed 12 months ago.
So I have an application where I'm considering moving from PyQt4 to PySide. In this application, I use .ui files pretty frequently, with the following usage pattern:
class BaseGUIWidget(QWidget):
def __init__(self, parent = None, ui_file = None):
'''
:param parent: parent widget of this widget
:param ui_file: path to UI file to load (optional)
'''
super(BaseGUIWidget, self).__init__(parent)
if ui_file is not None:
uic.loadUi(ui_file, self)
Let's assume I have similar classes for QFrame, QMainWindow, QGroupBox, etc.
This allows me to create python classes that use the data from the UI file, as well as any additional functionality I add manually in the code. Essentially, my BaseGUIWidget class acts as if it was extending the class generated by the UI file. A lot of the functionality in the application is pretty reliant on this behavior.
However, from what I can tell, PySide's QUIloader doesn't have a similar functionality. Instead of 'shimming' the UI file's contents into your class, it simply builds a widget from the UI file internally, then returns it, and you then embed it into your widget in a layout like you would any other widget., I.E:
class BaseGUIWidget(QWidget):
def __init__(self, parent = None, ui_file = None):
'''
:param parent: parent widget of this widget
:param ui_file: path to UI file to load (optional)
'''
super(BaseGUIWidget, self).__init__(parent)
self.setLayout(QVBoxLayout())
if ui_file is not None:
loader = QUILoader()
uifile = QFile(ui_file)
uifile.open(QFile.ReadOnly)
self.ui_widget = loader.load(ui_file, self)
self.layout().addWidget(self.ui_widget)
uifile.close()
This is a pretty massive difference. If, for example, you wanted your UI file to contain a QMainWindow and your python class to still be an extension of QMainWindow so it acts like one to other classes, you'd wind up with a QMainWindow inside a QMainWindow, which isn't what you want. It also means you have to do widget.ui_widget.XXX to access the widgets produced by the UI file.
Is there any way to make PySide's uic implementation act like PyQt's?
use QtPy package
pip3 install QtPy
it autodetect used binding(pyqt5 or pyside2)
from QtPy import uic # and all other QT modules
w = uic.loadUi("mywidget.ui")
w.show()
Yes it is possible.
I know it is old question, but suddenly someone will come in handy.
I found this solution on:
https://robonobodojo.wordpress.com/2017/10/03/loading-a-pyside-ui-via-a-class/
ui_loader.py:
#!/usr/bin/env python
from PySide.QtUiTools import QUiLoader
from PySide.QtCore import QMetaObject
class UiLoader(QUiLoader):
def __init__(self, base_instance):
QUiLoader.__init__(self, base_instance)
self.base_instance = base_instance
def createWidget(self, class_name, parent=None, name=''):
if parent is None and self.base_instance:
return self.base_instance
else:
# create a new widget for child widgets
widget = QUiLoader.createWidget(self, class_name, parent, name)
if self.base_instance:
setattr(self.base_instance, name, widget)
return widget
def load_ui(ui_file, base_instance=None):
loader = UiLoader(base_instance)
widget = loader.load(ui_file)
QMetaObject.connectSlotsByName(widget)
return widget
example:
#!/usr/bin/env python
from PySide import QtGui
from ui_loader import load_ui
import sys
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QMainWindow.__init__(self, parent)
load_ui('my_interface.ui', self)
def main():
app = QtGui.QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()
if __name__ == '__main__':
main()
Actually I was wondering about the same thing and just tried this:
Copy the uic package from a PyQt4 installation to your PySide package(its all python modules, no compiled libraries, so there should not be any incompatibilities)
Do a search & replace on the uic package, replacing "PyQt4" with "PySide"
Use it:
from PySide import uic
w = uic.loadUi("mywidget.ui")
w.show()
It also worked for me with the use case you describe (uic.loadUi(ui_file, self)) :)
Of course there is no guarantee that everything will work, but I was surprised that this hack made it work.

PySide: QMetaObject.connectSlotsByName emits warnings "No matching signal..." but still works..?

In Qt Designer, I created a QDialog window and used pysideuic to compile that to a base class which contains a setupUi method initialising all GUI elements and which I extend to implement the functionality, as so:
class MyDialog(QtGui.QDialog, ui_file.Ui_main_dialog):
def __init__(self, parent=None):
QtGui.QDialog.__init__(self, parent)
ui_file.Ui_main_dialog.__init__(self)
self.setupUi(self)
This setupUi method has calls to QtCore.QObject.connect for the signal-slot connections I created in Qt Designer, where I also added new slots to the GUI. These slots are non-existent in the base class generated by pysideuic and I added them to the MyDialog class, e.g.
def on_list_selection_changed(self):
self.run_btn.setEnabled(len(self.modules_list.selectedIndexes()) > 0)
For this example, the slot is called on_list_selection_changed() (with empty parameter list) in Qt Designer.
On initialisation, MyDialog.__init__ calls Ui_main_dialog.setupUi, which eventually calls QtCore.QMetaObject.connectSlotsByName (the latter two with the MyDialog instance's self which is currently being created). This emits the following line on sys.stderr:
QMetaObject::connectSlotsByName: No matching signal for on_list_selection_changed()
Still, the signal behaves correctly and the slot is called when the connected modules_list.itemSelectionChanged() (modules_list is a QListWidget).
So here is my question: why do I receive this warning? What can I do so it doesn't appear, given that it seems to be irrelevant?
Edit: Since I didn't receive any answers in the last 5 months, I thought I give a complete example to make reproducing the problem easier.
This example differs from the question above in that it only uses a QLineEdit instance. Here is the code:
import sys
from PySide import QtCore, QtGui
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
self.lineEdit = QtGui.QLineEdit(Dialog)
self.lineEdit.setObjectName("lineEdit")
QtCore.QObject.connect(self.lineEdit, QtCore.SIGNAL("textChanged(QString)"), Dialog.on_lineEdit_changed)
QtCore.QMetaObject.connectSlotsByName(Dialog)
class MainWindow(QtGui.QMainWindow, Ui_Dialog):
def __init__(self, parent=None):
QtGui.QMainWindow.__init__(self, parent)
Ui_Dialog.__init__(self)
Ui_Dialog.setupUi(self, self)
#QtCore.Slot(unicode) # signal with no arguments
def on_lineEdit_changed(self, text):
print 'Changed to', text
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
mw = MainWindow()
mw.show()
sys.exit(app.exec_())
Note that the code for the Ui_Dialog class is generated by the pysideuic from the Qt Designer's .ui file, but I shortened it a bit to better highlight the problem.
I have the same issue in C++. connectSlotsByName is hard-coded to output that message if it finds a slot it can't connect automatically, even though you don't need the automatic connection because you've done it explicitly yourself. You can use qInstallMsgHandler to suppress warnings in general or write the messages somewhere better but I don't think there's any way to tell connectSlotsByName that you don't care about this case in particular.
I'm late but in case someone else comes here for this same question.
PySide auto connects the signals, this is how it worked for me since I didn't want to be connecting manually.
Here I use python 3.9 and PySide2, but it is the same for PySide6 and also for other versions of python.
import sys
import typing
from PySide2.QtCore import QObject, SignalInstance, Signal, Slot
from PySide2.QtWidgets import QMainWindow, QApplication
from .ui_mainwindow import Ui_MainWindow # Don't forget to add your import
class MyQObject(QObject):
mySignal: SignalInstance = Signal()
otherSignal: SignalInstance = Signal(str)
def __init__(self, parent: typing.Optional[QObject] = None) -> None:
super().__init__(parent)
class MainWindow(QMainWindow, Ui_MainWindow):
def __init__(self):
QMainWindow.__init__(self)
# Instantiate before self.setupUI
self.myQObject = MyQObject(self)
self.myQObject.setObjectName("syncProduct") # do not forget this
# Load UI from designer & init
self.setupUi(self)
#Slot()
def on_myQObject_mySignal(self):
print("Handle mySignal")
#Slot(str)
def on_myQObject_otherSignal(self, text: str):
print(f"Handle otherSignal {text}")
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())

Categories