可视化Qt信号与槽

Qt5 中的信号与槽

对于已经有了IDE的Qt而言,我们拥有更多的建立信号-槽方法的选择,但是作为一名自然人类,我们最喜欢的还是眼见为实,既然Qt为我们设计了 Qt Creator,那么我们就应该充分利用它,然而国内的教程大都停留在非可视化操作下,这里记录在 Qt Creator 下我们该如何设计一个信号-槽机制

准备工作

打开Qt Creator,创建Qt Gui项目,我使用的是Qt5,但是同样也适用于Qt4,两者的在本次中的区别就在于建立连接(QObject::connect)的时候,Qt5更加灵活。

项目是MainWindow类,建立完成之后, Qt Creator 自动生成一系列文件

  1. 打开mainwindow.h头文件,进行添加测试函数 void test();
  2. 首先包含以下测试使用的头文件<QDebug> <QMessageBox>
    该函数原型需要首先加在private:下,作为私有成员函数。

  3. 其次打开mainwindow.cpp文件,进行测试函数的定义:

    void MainWindow::test()
    {
        qDebug() << "Test Successful!";
        QMessageBox::information(this, tr("Tip"), tr("Test"));
    }
    
  4. 上方的系列操作,2这个功能在Qt5下成功,Qt4需要在标签public slots:下放置该函数声明。3这个操作中定义了test()的函数体,其中qDebug()是在终端调试的时候使用的一个函数,我们使用它来在 应用程序输出 窗口显示是否成功。QMessageBox::information(...)则是用来显示一个窗口,也用来显示是否成功。

方法1

  1. 双击.ui文件,进入Qt Designer,至于不懂这个的也无所谓,只是个叫法而已,只需要知道如何在这个界面操作即可。

    • 这时候我们为了演示,拖动添加一个Push Button按钮进窗口,这时候发现主界面上多了一个 PushButton,这时候看到你的右下方,有一个属性窗口,有过设计经验的都很熟悉,
    • objectName代表的是在代码中这个控件的名字,记好它,当然你也可以修改它
    • QAbstractButton下的text代表的是,你的程序运行起来以后该控件在你面前显示出来的名字。
    • statusTip代表的是,当你鼠标移动到这个控件上时,在整个窗口中的下部有一块区域 Status Bar ,在此处显示你在其中填写的信息
    • shortcut顾名思义就是快捷键的意思,但是此处快捷键使用Qt Designer设置有一个不太好的地方便是,无法很好的跨平台支持,如Mac OS下是Command代替了很多Windows下的Ctrl操作,使用代码则可以调用Qt所配置好的API。
    • 以上几个是常用的几个属性。
  2. 做完PushButton的准备工作之后,objectNameButton_1

    • 由于Qt Designer只支持Qt的内置槽函数的建立连接,但是我们可以想办法让它变为可行,右键主窗体,选择 改变信号/槽,在出现的窗口中的槽里,点击加号,在其中输入刚才预先做好的测试函数test(),点击OK即可
    • 这时候我们在下方找到一个窗口Signals & Slots Editor,如果没有可以仔细找找,或者上网查询如何打开它,在此处我们可以很轻松的使用Qt中的信号与槽的连接,点击加号,出现一个新的记录,记录中包含 发送者(sender), 信号(signal), 接收者(receiver), 槽(slot) 犹如字面意思
    • 在其中发送者选择Button_1,信号选择triggered,接收者选择MainWindow,槽选择open()
  3. 这样做完就行,这时候只需要保证main.cpp中包含有如下代码

    MainWindow win_1;
    win_1.show();
    

    就行,这时候编译运行,OK,你想要的效果就出来啦

    • 这就是全程的可视化操作,省去了一部份精力

      方法2

  4. 步骤1与上方的方法1一致,直到

  5. 在此处我们记下了PushButtonobjectName之后,在mainwindow.cpp文件的类构造函数的定义中,修改代码,以代码形式得到我们上面使用可视化操作的效果,在这一步,往往有人会卡住,总是发现,明明关联没有错误,但是总是提示错误: QObject connect invaild null parameter,这是为什么?我们看一下mainweindow.cpp的构造函数的原始状态

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

    其中最后一句代码是将Qt Designer中的实现自动转化为代码,如果你在这句代码之前使用使用QObject::connect那么会导致,无法找到刚才创建的控件对象。所以我们只需要把connect放在后面即可。

    ui->setupUi(this);
    QObject::connect(ui->pushButton, &QPushButton::click, 
                    this, this->open);
    

    在此处QObject::connect可以简写为connect,因为此刻我们正处于MainWindow::MainWindow这个对象的作用域当中。

  6. 最后也是保证main.cpp的代码即可。

对于可视化

虽然Qt Creator给予了我们极大的便利,但是在实际的复杂功能实现中,个人感觉还是需要代码操作占到主体,而界面设计毕竟只是一小部分,虽然Qt这个框架十分之大,但是其命名却是非常的人性化,常见的几个属性:

ui->button_name->setText(tr("button_name_you_want"));
ui->button_name->setStatusTip(tr(""));
ui->button_name->setShortcut(QKeySequence::shortcut_you_want);
ui->button_name->setIcon(QIcon(":/adressofpicture"));
...

如此看,基本只要是属性的函数命名都是以set...开头,每个成员函数都能很清楚的看出功能。

并且其中大部分都是以QString为类型参数,即tr("...")代表的就是将C风格字符串转为QString类型。

而某些特殊的则需要记住,例如QKeySequence::...代表的是由Qt自带的快捷键API,使用它能更好的适应跨平台的问题。QKeySequence::Open在Windows下默认为Ctrl+O,Mac下为Command+O

最后的最后感谢 Haavard Nord 和 Eirik Chambe-Eng 为我们无私贡献了这么强大的Qt开源库