Search code examples
c++qtsignals-slotsqt-designer

Qt Designer - How to connect a signal to a static function?


Okay I'm using Qt Designer to build a GUI. I've managed to figure out how to make the menuBar and I've added some actions to the bar, but now I need to connect the actions to make them do something.

Specifically, on my file menu, I have the simple open action. I want this action to run a function that calls my QFileDialog and so on, but I don't know how to do this.

So, how do I connect my actionOpen to my static function?

I am using the latest Qt, 5.0.2

I'm a little frustrated here. This is obviously one of the most basic things someone might need to do, yet I cannot find any real solution to this anywhere on the web. From the lacking Qt wiki, to other people's questions, nobody really seems to have a clear answer. There are answers for older versions of Qt, yet in those old versions apparently signals couldn't connect to static functions, so those are irrelevant. And nobody seems to know how to do this through the Qt Designer. Also, nobody ever clarifies where to put what.

I have this line in my main.cpp file:

QObject::connect(actionOpen, &actionOpen::triggered, fileOpen)

I have an object called 'actionOpen' made in Qt Designer, there is a signal called triggered, and I have a function defined just below my main inside main.cpp called 'fileOpen'. This seems to follow the proper syntax, yet it throws many errors.

Also, I can repeatedly click build in Qt Creator and every single time it comes up with a different number of errors, disappearing and reappearing, without me even touching the code. I'm starting to think this IDE is sort of a POS.

EDIT:

Here are my files. Maybe this will help somewhat.

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

public slots:
    void fileOpen();

private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

main.cpp

#include "mainwindow.h"
#include <QApplication>
#include <iostream>
#include <fstream>

using namespace std;


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

    w.show();


    return a.exec();
}

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <iostream>

using namespace std;



MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    QObject::connect(ui->actionOpen, &QAction::triggered, &MainWindow::fileOpen);
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;

}

void fileOpen()
{

    /*
    QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"), QString(),
        tr("Text Files (*.txt);;C++ Files (*.cpp *.h)"));

    if (!fileName.isEmpty()) {
        QFile file(fileName);
        if (!file.open(QIODevice::ReadOnly)) {
            QMessageBox::critical(this, tr("Error"), tr("Could not open file"));
            return;
        }
        QTextStream in(&file);
        ui->textEdit->setText(in.readAll());
        file.close();
    }
    */

    cout << "Hello!";
}

Solution

  • The second argument is incorrect. You should specify the class name, not object name. So it should be:

    QObject::connect(actionOpen, &QAction::triggered, fileOpen);
    

    Complete working example (tested):

    void fileOpen() {
      qDebug() << "ok";
    }
    
    int main(int argc, char *argv[]) {
      QApplication a(argc, argv);
      QMenu menu;
      QAction* actionOpen = menu.addAction("test");
      QObject::connect(actionOpen, &QAction::triggered, fileOpen);
      menu.show();
      return a.exec();
    }