美文网首页
添加槽函数

添加槽函数

作者: downdemo | 来源:发表于2018-08-06 11:11 被阅读21次

QtCreator直接转到槽

  • 在QtCreator中添加槽很简单,直接在设计界面中右键Button选择转到槽,再选择信号即可
右键Button 选择信号

VS手动添加槽函数

  • 实际上,完成上述操作,QtCreator会自动给对应界面的头文件的类中添加槽函数声明,并在.cpp文件中添加函数体
QtCreator自动在头文件中添加槽函数 QtCreator自动在.cpp文件中添加函数体
  • 在VS中不会自动完成这些操作,手动完成即可。先在头文件中类的private slots作用域中添加槽函数声明
在头文件中声明槽函数
  • 再在.cpp文件中添加实现
添加实现
  • 随后打开ui界面,添加一个PushButton控件,按下F4,拖动Button拉出配置连接选项界面
配置连接界面
  • 点击右侧的编辑会弹出新窗口,点击上侧的加号,手动添加需要响应的槽函数,即之前声明的on_toolButton_5_clicked(),点击OK。这里虽然函数名是toolButton,按钮是PushButton,但是名字和实际功能没有关系,用这个名字是因为我之前已经添加了几个toolButton的槽函数,这里写文章记录为了方便直接复制函数名
  • 此时回到配置连接界面,右侧就会出现添加的槽函数。左侧选择信号,右侧选择槽,点击OK
右侧多出了手动添加的槽
  • 此时就完成了信号槽的连接配置
  • 保存后关闭设计界面,给槽函数添加需要实现的功能,运行后点击按钮即可执行槽函数

通过代码手动连接信号槽

  • 通过代码完成效率更高,无需打开设计师界面即可完成所需功能
  • 在需要操作的界面的构造函数中添加控件,然后使用connect函数连接已声明和实现的槽函数即可
dlg::dlg(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::dlg)
{
    ui->setupUi(this);

    QPushButton* btn = new QPushButton();
    btn->setText("run slot");
    
    connect(btn, &QPushButton::clicked, this, &dlg::slot);
}

void dlg::slot()
{
    QLabel* label = new QLabel();
    label->setText("show");
    label->show();
}
  • connect有五种重载形式
// Qt4的写法,用SIGNAL()和SLOT()两个宏将信号和槽转为const char*
QMetaObject::Connection connect(const QObject *, const char *,
                                const QObject *, const char *,
                                Qt::ConnectionType);
// QMetaMethod是Qt中一个能获取函数详细信息的类,也是Qt4的写法
QMetaObject::Connection connect(const QObject *, const QMetaMethod &,
                                const QObject *, const QMetaMethod &,
                                Qt::ConnectionType);
// 省略接受者,实际将this设为接受者
QMetaObject::Connection connect(const QObject *, const char *,
                                const char *,
                                Qt::ConnectionType) const;
// Qt5写法,信号和槽可以是成员函数指针
QMetaObject::Connection connect(const QObject *, PointerToMemberFunction,
                                const QObject *, PointerToMemberFunction,
                                Qt::ConnectionType)
// 省略接受者,不需要this,第三个参数也可以是一个lambda,或者static函数、全局函数
QMetaObject::Connection connect(const QObject *, PointerToMemberFunction,
                                Functor);

通过自定义信号为槽函数传参

  • 通常使用的信号由Qt控件自带,而槽函数的参数必须比信号的参数少,原生信号没有参数(实际上QPushButton::clicked有一个参数,但不能自己指定),因此槽函数也不能指定参数
connect(btn, &QPushButton::clicked, this, &dlg::slot); // slot不能有参数
  • 要实现传参,需要自定义信号。信号在头文件signals作用域中声明,没有返回值,也不需要在源文件中实现(实际上为了通过编译,moc会自动添加函数体)
class dlg : public QMainWindow
{
    Q_OBJECT

public:
    explicit dlg(QWidget* parent = 0);
    ~dlg();
    
private:
    Ui::Form* ui;
    QPushButton* btn;

signals:
    void send(int n); // 自定义信号

private slots:
    void rcv(int n); // 用于接受自定义信号的槽函数
    void clk(); // 连接给btn的无参数槽函数
};
  • 连接自定义信号后,使用emit即可触发所有连接到此信号的槽函数
connect(this, &dlg::send, this, &dlg::rcv);
emit send(3); // 触发槽函数

void widget::rcv(int n)
{
    btn->setText(QString::number(n));
}
  • 因此如果希望使用原生信号,又想传参给槽函数,只要在无参的槽函数中发送信号,即可触发有参数版本的槽函数
connect(btn, &QPushButton::clicked, this, &dlg::clk);

void dlg::clk()
{
    emit send(4); // 传递参数4
}
  • 信号槽不是GUI提供的,在Qt控制台程序中也可以使用,只需要让类继承QObject即可

父子窗口来回切换

  • 在父窗口中设置一个按钮,点击将隐藏父窗口,创建并显示一个子窗口。在子窗口设置一个返回按钮,点击将关闭子窗口,并重新显示隐藏的父窗口
// file "parent.h"
#include "child.h"
class parent {
    ...
private slots:
    void clickBtn();
    void reshow();
};

// file "parent.cpp"
void parent::clickBtn()
{
    this->hide();
    child* w = new child;
    connect(w, &child::reshowSignal, this, &parent::reshow);
    w->show();
}

void parent::reshow()
{
    this->show();
}


// file "child.h"
#include "parent.h"
class child {
    ...
signals:
    void reshowSignal();
private slots:
    void goBack();
};

// file "child.cpp"
void child::goBack()
{
    emit reshowSignal();
    this->close();
}

相关文章

网友评论

      本文标题:添加槽函数

      本文链接:https://www.haomeiwen.com/subject/kyywvftx.html