2

I made a simple Qt project to cover the issue of calling Ui from another class.

The Files:
mainwindow.h | mainwindow.cpp | client.h | client.cpp | main.cpp

The Issue:
Connecting a signal from client.cpp to a slot in mainwindow.cpp worked very well.
But when I added a

ui->statusBar->showMessage("message");
in the slot, it didn't work.
NOTE: When I made the signal and the slot both in mainwindow.cpp it worked, but calling a slot from mainwindow.cpp from a signal and connect() in client.cpp doesn't work.

The Codes: (trimmed to the essentials)

mainwindow.h

namespace Ui {
    class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT


signals:

public slots:
    void doSomething();

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


private:
    Ui::MainWindow *ui;

};


mainwindow.cpp

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


void MainWindow::doSomething()
{
    QMessageBox::information(0, "test", "BINGO!!");
    ui->statusBar->showMessage("testing");
}


client.h

class client : public QObject
{
    Q_OBJECT
public:
    explicit client(QObject *parent = 0);
    void call();

signals:
    void connected();

public slots:

};


client.cpp

client::client(QObject *parent) :
    QObject(parent)
{
    MainWindow main;
    connect(this, SIGNAL(connected()), &main, SLOT(doSomething()));
    call();
}

void client::call()
{
    emit connected();
}



Added:
main.cpp

#include <QtGui/QApplication>
#include "mainwindow.h"

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

    return a.exec();
}

Thanks.

L'algerien
  • 41
  • 1
  • 4
  • Please post your main.cpp, thanks. – trooper Sep 27 '14 at 20:44
  • ok, editted the post – L'algerien Sep 27 '14 at 20:56
  • 1
    So... where do you create and use a client object? It looks like that code on the client is never run. – trooper Sep 27 '14 at 20:58
  • I have another big project that did this, but i made a small project to cover this issue, the code of the client runs, and the messagebox also, but the ui didn't. so here's the problem. – L'algerien Sep 27 '14 at 21:03
  • Ok. So the doSomething slot on MainWindow is definitely invoked - you see the message box? The problem is that the following line doesn't seem to get executed and you don't see a change in the status bar? – trooper Sep 27 '14 at 21:09
  • Well, now even the QMessageBox isn't called, wtf ?! Please compile it in your Qt and tell me what happens – L'algerien Sep 27 '14 at 21:15
  • You create an instance of `MainWindow` in the main function, then you go and create another instance of `MainWindow` in the `Client`'s constructor. Doesn't seem like something you really intend to do, or do you really want to create two instances of the `MainWindow` class? – thuga Sep 29 '14 at 09:23

2 Answers2

1
client::client(QObject *parent) :
    QObject(parent)
{
    MainWindow main;
    connect(this, SIGNAL(connected()), &main, SLOT(doSomething()));
    call();
}

Your MainWindow lives on the stack. I think by the time your doSomething slot is triggered, the MainWindow object is already long gone. Try creating your MainWindow on the heap instead.

trooper
  • 4,444
  • 5
  • 32
  • 32
  • Sorry to ask you this sillly question: How ? – L'algerien Sep 27 '14 at 20:25
  • Take a look at http://stackoverflow.com/questions/599308/proper-stack-and-heap-usage-in-c . You need to use `new` and store a pointer to the MainWindow. Pass the client as the MainWindow's parent and Qt will take care of cleaning up after the MainWindow when the client object is destroyed. – trooper Sep 27 '14 at 20:31
  • I did what you said, "MainWindow *main = new MainWindow;" but still the same issue . – L'algerien Sep 27 '14 at 20:36
-2

I see a major mistake in the code you have posted.

You have created an instance of MainWindow in the file main.cpp and thats the window you see when you run the application. But in your client.cpp you are creating a second instance of MainWindow and connecting the signal from the client object to the slot of the second MainWindow object you create. You are not seeing two main windows because you do not run the exec or show methods of this second instance.

Now coming to the solution, you will have to connect the signal from client to the proper MainWindow instance. I will suggest two methods below.

First:

I believe you create an instance of client in one of the member functions of the class MainWindow. If so then shift the connect method to the file mainwindow.cpp

Something like:

void MainWindow::someFunction()
{
    client* c = new client();
    connect(c, SIGNAL(connected()), this, SLOT(doSomething()));
    c->call();
}

Second:

If you cannot do what is explained above, then you can use a combination of a static pointer and a static function to get the instance of MainWindow. Note that this method can also be used to ensure that there is only one instance of MainWindow at any given time.

mainwindow.h

namespace Ui {
    class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT


signals:

public slots:
    void doSomething();

public:
    explicit MainWindow(QWidget* parent = 0);
    ~MainWindow();
    static MainWindow* GetInstance(QWidget* parent = 0);

private:
    Ui::MainWindow *ui;
    static MainWindow* mainInstance;

};

mainwindow.cpp

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

MainWindow* MainWindow::mainInstance = 0;

MainWindow* MainWindow::GetInstance(QWidget *parent)
{
    if(mainInstance == NULL)
    {
        mainInstance = new MainWindow(parent);
    }
    return mainInstance;
}

void MainWindow::doSomething()
{
    QMessageBox::information(0, "test", "BINGO!!");
    ui->statusBar->showMessage("testing");
}

Now in whatever class you need to get the instance of MainWindow in use, simply use the static function MainWindow::GetInstance to get the pointer to the MainWindow instance and use that as the parameter for connect. i.e.,

MainWindow* instance = MainWindow::GetInstance();
client* c = new client();
connect(c, SIGNAL(connected()), instance , SLOT(doSomething()));
Nithish
  • 1,580
  • 12
  • 21