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

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_())

Related

update the progressBar value from emitted signal

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.

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.

Open a GUI file from another file PyQT

I've created many GUI interfaces in PyQT using QT Designer, but now I'm trying to open an interface from another one, and I don't know how to do it..
Start.py is the file which run the GUI Interface Authentification_1 and Acceuil_start.py is the file which run the GUI interface Acceuil_2.py, now I want from Start.py to lunch Acceuil_start.py.
Do you have any idea about that ? Thank you.
Here's my code :
Start.py :
import sys
from PyQt4 import QtCore, QtGui
from Authentification_1 import Ui_Fenetre_auth
from Acceuil_2 import Ui_MainWindow #??? Acceuil_2.py is the file which I want to open
class StartQT4(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_Fenetre_auth()
self.ui.setupUi(self)
def authentifier(val): #Slot method
self.Acceuil = Acceuil() #???
self.Acceuil.show() #???
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp = StartQT4()
myapp.show()
sys.exit(app.exec_())
Acceuil_start.py
import sys
from PyQt4 import QtCore, QtGui
from Authentification_1 import Ui_Fenetre_auth
from Acceuil_2 import Ui_MainWindow
class StartQT4(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp = StartQT4()
myapp.show()
sys.exit(app.exec_())
First, you should to name your GUI classes so they have a different name, and not the generic one, so you could distinct them.
Why you would need to do that? Well - simply, because it makes sense - if every class is representing different type of dialog, so it is the different type - and it should be named differently. Some of the names are/may be: QMessageBox, AboutBox, AddUserDialog, and so on.
In Acceuil_start.py (you should rename class in other module, too).
import sys
from PyQt4 import QtCore, QtGui
from Authentification_1 import Ui_Fenetre_auth
from Acceuil_2 import Ui_MainWindow
class Acceuil(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp = Acceuil()
myapp.show()
sys.exit(app.exec_())
in the parent class, when you want to create the window, you are close (but it should work in any case):
def authentifier(val): #Slot method
self.Acceuil = Acceuil(self) # You should always pass the parent to the child control
self.Acceuil.show() #???
About parent issue: If your widget/window is creating another widget, setting creator object to be parent is always a good idea (apart from some singular cases), and you should read this to see why is that so:
QObjects organize themselves in object trees. When you create a QObject with another object as parent, it's added to the parent's children() list, and is deleted when the parent is. It turns out that this approach fits the needs of GUI objects very well. For example, a QShortcut (keyboard shortcut) is a child of the relevant window, so when the user closes that window, the shorcut is deleted too.
Edit - Minimal Working Sample
To see what I am trying to tell you, I've built a simple example. You have two classes - MainWindow and
ChildWindow. Every class can work without other class by creating separate QApplication objects. But, if you import ChildWindow in MainWindow, you will create ChildWindow in slot connected to singleshot timer which will trigger in 5 seconds.
MainWindow.py:
import sys
from PyQt4 import QtCore, QtGui
from ChildWindow import ChildWindow
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
QtCore.QTimer.singleShot(5000, self.showChildWindow)
def showChildWindow(self):
self.child_win = ChildWindow(self)
self.child_win.show()
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp = MainWindow()
myapp.show()
sys.exit(app.exec_())
ChildWindow.py:
import sys
from PyQt4 import QtCore, QtGui
class ChildWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.setWindowTitle("Child Window!")
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp = ChildWindow()
myapp.show()
sys.exit(app.exec_())
To reference the other dialog from Start.py, you must prefix it by the module name, which in this case is Acceuil_start. As such, it is OK if there are duplicated function names in each module. So, you would have:
def authentifier(val): #Slot method
dlg = Acceuil_start.StartQT4()
dlg.exec_()
However, if you want these to run from the same process, keep in mind that you can't have two app objects. You would probably want to structure Acceuil_start.py to act like a dialog, rather than a main window. If these are two distinct main windows, you might find it easier to just invoke another Python interpreter with the Acceuil_start.py as a parameter.

Signals and slots in PySide - defining slot in class

I'm new to Qt and PySide and try to get a feeling for signals and slots in PySide.
While following the documentation of Signals and Slots in PySide, I tried to transfer some code to be used in my class.
The following code creates a DoubleSpinBox. When changing the value I expect the value to be printed by both functions value_changed_func and value_changed_class, but only value_changed_func gets called.
from PySide import QtCore
from PySide import QtGui
#QtCore.Slot(float)
def value_changed_func(value):
print "Event func:"
print value
class MainController(QtCore.QObject):
def __init__(self, parent):
self._ui = QtGui.QDoubleSpinBox(parent)
self._ui.valueChanged.connect(self.value_changed_class)
self._ui.valueChanged.connect(value_changed_func)
#QtCore.Slot(float)
def value_changed_class(self, value):
print "Event class:"
print value
app = QtGui.QApplication([])
main_window = QtGui.QMainWindow()
MainController(main_window)
main_window.show()
app.exec_()
What am I doing wrong? How do I get value_changed_class to be called?
You didn't call the parent constructor:
def __init__(self, parent):
super(MainController, self).__init__(parent)
...

Categories