Example of calling a function to parent?
-
wrote on 30 Jan 2022, 17:35 last edited by Panoss
I 'm searching for a simple example of calling (from a form) a function to another form.
Let me explain: I have FormA with a button on it. Clicking this button I open FormB which also has a button.
When I click on FormB's button I want to call a function in FormA.From what I read it will be done with Signal, Slots and emit() (but to tell the truth I don't understand much).
Is there some example? -
wrote on 30 Jan 2022, 18:37 last edited by
Ok, I found a python example that works.
#!/usr/bin/python3 # Threading example with QThread and moveToThread (PyQt5) import sys import time from PyQt5 import QtWidgets, QtCore class WorkerThread(QtCore.QObject): signalExample = QtCore.pyqtSignal(str, int) def __init__(self): super().__init__() @QtCore.pyqtSlot() def run(self): while True: # Long running task ... self.signalExample.emit("leet", 1337) time.sleep(5) class Main(QtWidgets.QMainWindow): def __init__(self): super().__init__() self.worker = WorkerThread() self.workerThread = QtCore.QThread() self.workerThread.started.connect(self.worker.run) # Init worker run() at startup (optional) self.worker.signalExample.connect(self.signalExample) # Connect your signals/slots self.worker.moveToThread(self.workerThread) # Move the Worker object to the Thread object self.workerThread.start() def signalExample(self, text, number): print(text) print(number) if __name__ == '__main__': app = QtWidgets.QApplication(sys.argv) gui = Main() sys.exit(app.exec_())
I want to modify it (in python code for now) so that the WorkerThread class' code will 'move' to mainWindow (and WorkerThread class to be completely removed).
How can I do this? -
Ok, I found a python example that works.
#!/usr/bin/python3 # Threading example with QThread and moveToThread (PyQt5) import sys import time from PyQt5 import QtWidgets, QtCore class WorkerThread(QtCore.QObject): signalExample = QtCore.pyqtSignal(str, int) def __init__(self): super().__init__() @QtCore.pyqtSlot() def run(self): while True: # Long running task ... self.signalExample.emit("leet", 1337) time.sleep(5) class Main(QtWidgets.QMainWindow): def __init__(self): super().__init__() self.worker = WorkerThread() self.workerThread = QtCore.QThread() self.workerThread.started.connect(self.worker.run) # Init worker run() at startup (optional) self.worker.signalExample.connect(self.signalExample) # Connect your signals/slots self.worker.moveToThread(self.workerThread) # Move the Worker object to the Thread object self.workerThread.start() def signalExample(self, text, number): print(text) print(number) if __name__ == '__main__': app = QtWidgets.QApplication(sys.argv) gui = Main() sys.exit(app.exec_())
I want to modify it (in python code for now) so that the WorkerThread class' code will 'move' to mainWindow (and WorkerThread class to be completely removed).
How can I do this?wrote on 30 Jan 2022, 18:58 last edited by@Panoss
You have picked an example with threads. Why? That is the last thing you should be doing as a newcomer. In any case you cannot perform any UI actions in anything but the main thread in Qt, so what you describe will not work anyway.Have you read https://doc.qt.io/qt-5/signalsandslots.html ? That shows the sort of thing you were asking about, and does not mention threads.
-
@Panoss
You have picked an example with threads. Why? That is the last thing you should be doing as a newcomer. In any case you cannot perform any UI actions in anything but the main thread in Qt, so what you describe will not work anyway.Have you read https://doc.qt.io/qt-5/signalsandslots.html ? That shows the sort of thing you were asking about, and does not mention threads.
wrote on 30 Jan 2022, 18:59 last edited by Panoss@JonB said in Example of calling a function to parent?:
@Panoss
You have picked an example with threads. Why? That is the last thing you should be doing as a newcomer.Yes I know, but this was the only one I found that works.
-
@Panoss
You have picked an example with threads. Why? That is the last thing you should be doing as a newcomer. In any case you cannot perform any UI actions in anything but the main thread in Qt, so what you describe will not work anyway.Have you read https://doc.qt.io/qt-5/signalsandslots.html ? That shows the sort of thing you were asking about, and does not mention threads.
wrote on 30 Jan 2022, 19:02 last edited by Panoss@JonB said in Example of calling a function to parent?:
Have you read https://doc.qt.io/qt-5/signalsandslots.html ? That shows the sort of thing you were asking about, and does not mention threads.
This was the first I read, but as I mentioned, didn't understand much. This is why I'm looking for a working, simple, example.
-
@JonB said in Example of calling a function to parent?:
Have you read https://doc.qt.io/qt-5/signalsandslots.html ? That shows the sort of thing you were asking about, and does not mention threads.
This was the first I read, but as I mentioned, didn't understand much. This is why I'm looking for a working, simple, example.
wrote on 30 Jan 2022, 19:58 last edited byOk, I have an example in python which is exactly as I want it:
from PySide6 import QtWidgets, QtCore class FormB(QtWidgets.QWidget): form_done = QtCore.Signal(str) def __init__(self, *args, steps=5, **kwargs): super().__init__(*args, **kwargs) self.entry = QtWidgets.QLineEdit("Enter value here") self.button = QtWidgets.QPushButton("Done") self.button.clicked.connect(self.button_pressed) layout = QtWidgets.QVBoxLayout(self) layout.addWidget(self.entry) layout.addWidget(self.button) def button_pressed(self): #self.hide() self.form_done.emit(self.entry.text()) class FormA(QtWidgets.QWidget): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.form_b = None self.button = QtWidgets.QPushButton("Draw B") self.button.clicked.connect(self.draw_b) self.label = QtWidgets.QLabel("I display the result in this label") layout = QtWidgets.QVBoxLayout(self) layout.addWidget(self.button) layout.addWidget(self.label) def draw_b(self): if self.form_b is None: self.form_b = FormB() self.form_b.form_done.connect(self.b_done) self.form_b.show() def b_done(self, text): self.label.setText(text) def main(): app = QtWidgets.QApplication([]) form_a = FormA() form_a.show() app.exec() main()
So, how do I convert this python code:
form_done = QtCore.Signal(str)
to c++?
-
Hi,
The Qt documentation contains quite a lot of examples using signals and slots. You should go through the ones from the widgets module since it's the one you are implementing your application with.
-
Hi,
The Qt documentation contains quite a lot of examples using signals and slots. You should go through the ones from the widgets module since it's the one you are implementing your application with.
wrote on 30 Jan 2022, 20:15 last edited by@SGaist said in Example of calling a function to parent?:
The Qt documentation contains quite a lot of examples using signals and slots
Didn't find a full working example, only fragments of code I 'm trying to put together.
If you have found a full working example please post it! -
Here you have the full list of the widgets examples.
-
wrote on 30 Jan 2022, 20:26 last edited by Panoss
Ok, let me show you what I tried so far:
In my FormB 's class declaration added:
public slots: void setValue(int value); signals: void valueChanged(int newValue);
Am I on the correct way?
-
These lines are to be found in the class declaration.
-
wrote on 30 Jan 2022, 20:33 last edited by
Yes you 're right, I corrected it!
-
wrote on 30 Jan 2022, 20:36 last edited by Panoss
And this is the function in my FormB: ()
void FormB::setValue(int value) { emit valueChanged(value); }
Correct?
-
wrote on 30 Jan 2022, 20:47 last edited by Panoss
And now this:
QObject::connect(&a, &Counter::valueChanged, &b, &Counter::setValue);
I modified it to (this code is in the constructor of FormB):
connect(&parent, &parent::valueChanged, this, &FormB::setValue);
???
It's wrong...The 'parent' I mean.
The sender is FormB...so.. -
And now this:
QObject::connect(&a, &Counter::valueChanged, &b, &Counter::setValue);
I modified it to (this code is in the constructor of FormB):
connect(&parent, &parent::valueChanged, this, &FormB::setValue);
???
It's wrong...The 'parent' I mean.
The sender is FormB...so..wrote on 30 Jan 2022, 21:13 last edited by mpergand@Panoss
Everything is upside down :)let's recap, you want the main window (formA) to be inform when a value has changed in second window (formB)
The main window register to receive a signal from the second window.
In formA:
connect(formB, &FormB::valueChanged, this , &FormA::valueChangedInFormB);
-
wrote on 30 Jan 2022, 21:46 last edited by Panoss
@mpergand it works!!!
Thank you all!The actual name of FormA is 'ArticlesWindow' and of FormB 'positionsForm'.
(FormB is the sender)
I post the code in case someone needs it:articleswindow.h private slots: void positionChanged(); articleswindow.cpp void ArticlesWindow::positionChanged(){ qDebug() << "ArticlesWindow::positionChanged"; } void ArticlesWindow::openPositionsForm(){ class positionsForm *form = new class positionsForm(model, this); connect(form, &positionsForm::valueChanged, this , &ArticlesWindow::positionChanged);
And:
positionsform.h public slots: void setValue(int value); signals: void valueChanged(int newValue); positionsform.cpp void positionsForm::setValue(int value) { emit valueChanged(value); }
-
@mpergand it works!!!
Thank you all!The actual name of FormA is 'ArticlesWindow' and of FormB 'positionsForm'.
(FormB is the sender)
I post the code in case someone needs it:articleswindow.h private slots: void positionChanged(); articleswindow.cpp void ArticlesWindow::positionChanged(){ qDebug() << "ArticlesWindow::positionChanged"; } void ArticlesWindow::openPositionsForm(){ class positionsForm *form = new class positionsForm(model, this); connect(form, &positionsForm::valueChanged, this , &ArticlesWindow::positionChanged);
And:
positionsform.h public slots: void setValue(int value); signals: void valueChanged(int newValue); positionsform.cpp void positionsForm::setValue(int value) { emit valueChanged(value); }
wrote on 30 Jan 2022, 21:53 last edited byIt works but the message is printed twice, like if function ArticlesWindow::positionChanged is called twice??
-
It works but the message is printed twice, like if function ArticlesWindow::positionChanged is called twice??
-
wrote on 30 Jan 2022, 22:04 last edited by Panoss
Why is this wrong?
Every time I want to open the form I create an instance of it 's class.
When I close the form the instance is destroyed, right?What 's the correct way?
1/38