[RESOLVED] Signal from form to form



  • Hello how can I contro one form from another ?
    For example i have Two forms MainWindow and MyDialog. In each form there is QpushButton component.

    On MainWindow:

    When I press button MyDialog opens:

    @void MainWindow::on_pushButton_clicked()
    {
    Dialog mdialog;
    mdialog.setModal(true);
    mdialog.exec();
    }@

    On MyDialog:

    When I press button in MyDialog, Text of Button in MainWindow changes to "YES"

    I tried this:
    In Main window created this:
    @void MainWindow::on_pushButton_clicked()
    {
    ui->pushButton->setText("YES");
    }@

    And trying to acess this in MyDialog:

    @#include "mainwindow.h"
    void MyDialog::on_radioButton_clicked()
    {
    MainWindow *MW;
    MW->on_pushButton_clicked();
    }@

    ERROR: void MyDialog::on_radioButton_clicked() is private

    I also tried this:
    void Dialog::on_radioButton_clicked()

    @{
    MainWindow::on_pushButton_clicked();
    }
    @

    ERROR: error: cannot call member function 'void MainWindow::on_pushButton_clicked()' without object.

    Is there an easy way to control other form components and variables from other form ?
    I remember i Borland it was esasy to do...

    Sory for my english, I hope you understan my question.

    Thank you.



  • Ok i just found this: "LINK":http://stackoverflow.com/questions/6199962/how-to-pass-data-from-one-form-to-another-in-qt (Second post by MohammadAG).

    But its not working, it compiles, but when i run processText(); function program crashes, by runing time error.

    mainwindow.h
    @#ifndef MAINWINDOW_H
    #define MAINWINDOW_H

    #include <QMainWindow>
    #include "dialog.h"
    #include <QTextEdit>
    namespace Ui {
    class MainWindow;
    }

    class MainWindow : public QMainWindow
    {
    Q_OBJECT

    public:
    explicit MainWindow(QWidget parent = 0);
    ~MainWindow();
    QTextEdit
    textEdit();

    private slots:
    void on_Form1Button_clicked();

    private:
    Ui::MainWindow *ui;
    Dialog *mdialog;
    };

    #endif // MAINWINDOW_H@

    dialog.h
    @#ifndef DIALOG_H
    #define DIALOG_H

    #include <QDialog>

    namespace Ui {
    class Dialog;
    }

    class Dialog : public QDialog
    {
    Q_OBJECT

    public:
    explicit Dialog(QWidget *parent = 0);
    ~Dialog();

    void processText();
    

    private slots:
    void on_Form2Button_clicked();

    private:
    Ui::Dialog *ui;
    };

    #endif // DIALOG_H@

    mainwindow.cpp
    @#include "mainwindow.h"
    #include "ui_mainwindow.h"

    MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
    {
    ui->setupUi(this);
    }

    MainWindow::~MainWindow()
    {
    delete ui;
    }

    QTextEdit* MainWindow::textEdit()
    {
    return ui->textEdit;
    }

    void MainWindow::on_Form1Button_clicked()
    {
    mdialog = new Dialog(this);
    mdialog->show();
    }@

    dialog.cpp
    @#include "dialog.h"
    #include "ui_dialog.h"
    #include "mainwindow.h"
    Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
    {
    ui->setupUi(this);
    }

    Dialog::~Dialog()
    {
    delete ui;
    }

    void Dialog::processText()
    {
    static MainWindow *firstForm;
    QString text = firstForm->textEdit()->toPlainText();
    ui->Form2Button->setText(text);

    }

    void Dialog::on_Form2Button_clicked()
    {
    processText();
    }@

    main.cpp
    @#include "mainwindow.h"
    #include <QApplication>

    int main(int argc, char *argv[])
    {
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec&#40;&#41;;
    

    }@

    I dont understand, what I am doing wrong ?



  • Hii..
    1)Use connect() function for signal and slots
    2)make your own signal in the same class and connect it to the slot of other class

    1. donn't call slot using an object.
      4)instead of calling emit signal.
      hope it would help.


  • From what i understand u want to change text shown on a button in main window when a button is clicked in dialog in the dialog
    i can see that you have included the header file for main window in your dialog file
    first make sure that you initialize the pointer for main window
    next to change the text on button you can try this code in the dialog
    @
    firstForm->ui->pushButton->setText("yes");
    @



  • I can't access Ui from Dialog. I am geting this error:
    error: 'Ui::MainWindow* MainWindow::ui' is private

    @MainWindow *firstForm; // Is it corect ?
    firstForm->ui->pushButton->setText("yes");@

    I know that seting UI as public is not a good idea. But signals and slots method is too complex for me. Looks like there is no simple wai pf doing that.



  • I Found this: "LINK":http://stackoverflow.com/questions/1056247/passing-variables-from-one-form-to-another-in-qt

    It says:
    "The dialog box still exists after it closes. So you can, from the main form, do something like this:

    QString text = subform->textEdit->text();
    This assumes your dialog box is subform and the name you gave to the text edit box is textEdit. Make sure you make textEdit public in the designer.

    If you don't want to make textEdit public, then you can add a getter to subform."

    How can i make textEdit or other component public ?



  • U have to create Object of Second form in the constructor of First Form. and then u can do with second form using object of second.



  • I think you are trying to directly access the MainWindow from your dialog, which, in theory you can do... but it sort of breaks the rules of encapsulation (i.e reaching in to other objects and accessing their internals... generally a bad practice).

    What Qt has is the slot / signal message/event passing system which is made for just this purpose and its really nice and easy to use (once you learn its basics).

    So, in your dialog form you press a button and then you want the MainWindow to know that you have pressed a button and do something accordingly. This is how it can be done:

    in MainWindow.cpp
    @
    // Connect a signal from mdialog called somthingHasHappened to a slot in the MainWindow called handleSomthingFromDialog.
    QObject::connect(mdialog, SIGNAL(somthingHasHappened()), this SLOT(handleSomthingFromDialog()))

    // Make a slot (in the header it comes under "public slots:"
    void MainWindow::handleSomthingFromDialog(void)
    {
         ui->pushButton->setText("YES");
    }
    

    @

    in MainWindow.h
    @
    public slots:
    void handleSomthingFromDialog(void);
    @

    in dialog.cpp
    @
    void MyDialog::on_radioButton_clicked()
    {
    // emit the signal somthingHasHappened MainWindow will pick this up
    emit somthingHasHappened();
    }
    @

    in dialog.h
    @
    signals:
    void somthingHasHappened(void);
    @

    The result is that, when radio button is clicked in dialog, it "emits" a signal that is connected to the MainWindow slot.



  • Thank you for help ! Your example is realy helpful.

    The program compiles, but not starts. I am geting this line:
    The program has unexpectedly finished.
    But no error in code. What I am doing wrong ?

    @MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
    {
    ui->setupUi(this);
    QObject::connect(mdialog, SIGNAL(somthingHasHappened(void)), this, SLOT(handleSomthingFromDialog(void)));

    }
    void MainWindow::handleSomthingFromDialog(void)
    {
    ui->Form1Button->setText("YES");
    }@

    I tried to make mdialog public in mainwindow.h:
    @public:
    Dialog *mdialog;@
    And now program starts but when I press radio buton nothing hapens.

    @void MyDialog::on_radioButton_clicked()
    {
    emit somthingHasHappened();
    }@



  • hii
    The program has unexpectedly finished.
    it might be because you did not initialized mdialog (which is pointer) .
    view thread-->
    https://qt-project.org/forums/viewthread/19319



  • yeah, I agree with IamSumit, sounds like a pointer-y like error! (sudden crash - generally means bad memory access).

    You must instantiate (create an instance of) mdiaglog before you connect it, or use it in any way at all :)

    When you do this, check you debug/output if the connection fails (a slot or signal is missing or not correct) then Qt prints a warning.



  • I started debug. And it shows :

    "The iferior stopped becouse it recieved a signal from the Operating System.
    Signal name: SIGSEGV
    Signal meaning: Segmentation fault"

    I don't uderstund how corectly initialize mdialog. Is this not corect:

    @public:
    Dialog *mdialog;
    // with this program started but signal not worked
    //But after debuging it's not even starting anymore@

    I tried this:
    @private:
    Dialog *mdialog;
    // Same result@

    And:

    @#include<QDialog>
    Publlic:
    QDialog* mdialog;
    //Same again
    @

    EDIT:

    OK I tried this:
    @mdialog = new Dialog(this);
    QObject::connect(mdialog, SIGNAL(somthingHasHappened(void)), this, SLOT(handleSomthingFromDialog(void)));
    @
    And the program starts again but signal not working, I open dialog pres radio button and nothin is happening.



  • What about the connection debug? - do you see some failure with the connection in the debug output? (when you run the program in Qt Creator it should come up in the debug window.

    If you do not, then please print out all code in both files, header and cpp...
    Have you declared the signal somthingHasHappened(void) in mdialog? and implemented handleSomthingFromDialog(void) slot?



  • There is no error in debug window.

    My code:
    dialog.h
    @#ifndef DIALOG_H
    #define DIALOG_H

    #include <QDialog>

    namespace Ui {
    class Dialog;
    }

    class Dialog : public QDialog
    {
    Q_OBJECT

    public:
    explicit Dialog(QWidget *parent = 0);
    ~Dialog();
    void processText();

    signals:
    void somthingHasHappened(void);

    private slots:

    void on_radioButton_clicked();
    
    void on_pushButton_clicked();
    

    private:
    Ui::Dialog *ui;
    };

    #endif // DIALOG_H
    @

    dialog.cpp

    @#include "dialog.h"
    #include "ui_dialog.h"

    Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
    {
    ui->setupUi(this);
    }

    Dialog::~Dialog()
    {
    delete ui;
    }

    void Dialog::on_radioButton_clicked()
    {
    emit somthingHasHappened();
    }

    void Dialog::on_pushButton_clicked()
    {
    emit somthingHasHappened();

    }@

    mainwindow.h

    @#ifndef MAINWINDOW_H
    #define MAINWINDOW_H

    #include <QMainWindow>
    #include <dialog.h>
    #include <QDialog>
    #include <QtGui>
    #include <QtCore>

    namespace Ui {
    class MainWindow;
    }

    class MainWindow : public QMainWindow
    {
    Q_OBJECT

    public:
    explicit MainWindow(QWidget parent = 0);
    ~MainWindow();
    Dialog
    mdialog;

    public slots:
    void handleSomthingFromDialog(void);

    private slots:
    void on_pushButton_clicked();

    private:

    Ui::MainWindow *ui;
    

    };

    #endif // MAINWINDOW_H
    @

    mainwindow.cpp

    @#include "mainwindow.h"
    #include "ui_mainwindow.h"

    MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
    {
    ui->setupUi(this);
    mdialog = new Dialog(this);
    QObject::connect(mdialog, SIGNAL(somthingHasHappened(void)), this, SLOT(handleSomthingFromDialog(void)));

    }
    void MainWindow::handleSomthingFromDialog(void)
    {
    ui->textEdit->setText("YES");
    }

    MainWindow::~MainWindow()
    {
    delete ui;
    }

    void MainWindow::on_pushButton_clicked()
    {
    Dialog mydialog;
    mydialog.exec();

    //mdialog = new Dialog(this);
    //mdialog->show();

    }@

    main.cpp

    @#include "mainwindow.h"
    #include <QApplication>

    int main(int argc, char *argv[])
    {
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec&#40;&#41;;
    

    }
    @



  • Can you put some debug in
    void Dialog::on_radioButton_clicked()
    void MainWindow::handleSomthingFromDialog(void)

    to see if one or both functions are getting called?

    the signal / slots look good to me.

    However:
    What is this:
    @
    void MainWindow::on_pushButton_clicked()
    {
    Dialog mydialog;
    mydialog.exec();

    //mdialog = new Dialog(this);
    //mdialog->show();

    }
    @

    A second dialog? - if this is the dialog that is running, then it is a different instance of the dialog that you have connected your signal/slot to.

    mydialog != mdialog

    You probably want to do
    @
    mdialog->exec();
    @

    this is a guess because I don't know the order of how you do things.



  • or do:

    @
    void MainWindow::on_pushButton_clicked()
    {
    Dialog mydialog;

    QObject::connect(&mydialog, SIGNAL(somthingHasHappened(void)), this, SLOT(handleSomthingFromDialog(void)));
    

    mydialog.exec();
    }
    @



  • [quote author="code_fodder" date="1393943815"]or do:

    @
    void MainWindow::on_pushButton_clicked()
    {
    Dialog mydialog;

    QObject::connect(&mydialog, SIGNAL(somthingHasHappened(void)), this, SLOT(handleSomthingFromDialog(void)));
    

    mydialog.exec();
    }
    @[/quote]

    YES ! :DDDD
    It's working !

    THANK YOU !
    You helped alot. I think now I will use signals and slots more often in my projects, they are realy useful. I will read more about it.

    One last thing, this can sound stupid, becouse I think this is not even Qt but C++ related, but what does & sign before mydialog, in conection line mean ? (connect(&mydialog) ?
    Sory I just learning stuf and not facetd with this before.

    By the way how can I mark subject as SOLVED ? (God it's even more stupid question :D)

    Thanks again for everyone, and sory for my english.



  • Ah, that is because you have to pass in a pointer in the connect() function.

    Dialog mydialog; - is a variable of type Dialog.
    Dialog *mdialog; - is a pointer (address) to a Dialog variable.

    So to make pass the address of a variable you have to use to the "&" operator, therefore &mydialog becomes (Dialog *) type (address of).

    To mark this thread as resolved, just change the title of your post to:
    "[RESOLVED] Signal from form to form"

    This is the convention


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.