《Qt应用开发》笔记p3

信号和槽机制

信号(Signal)和槽机(Slot)制 是Qt 特有的,独创的一种对象间通信的机制。

信号 是指发送对象给出的函数和参数的一种通知机制。

槽是指接受者和接收对象执行的函数。

QAbstractButton 的信号

复制代码
void clicked(bool checked = false)  // 点击信号(给出按钮的值)
void pressed()  // 按钮按下
void released() // 释放按钮
void toggled(bool checked) // 按钮状态变化。

槽是对象自定义的函数,他可以象普通成员函数一样调用。还可以连接某个对象的信号。

槽函数的定义方法

复制代码
class MyWidget: public QObject类或他的子类 {
    Q_OBJECT // 必须添加此宏
public slots:
    返回类型 槽函数名1(参数列表) {函数体}
    返回类型 槽函数名2(参数列表) {函数体}
};

信号和槽的连接方式

使用QObject::connect() 函数进行连接

复制代码
// 方法1(QT4及之前必须使用此种方法)
//connect(发送信号的对象, SIGNAL(发送对象的信号函数),
//   接收对象, SLOT(接收对象的成员函数));
QObject::connect(btn, SIGNAL(clicked(int)),
                   obj,  SLOT(onBtnPressed()));

// 方法2(QT5之后可用的方法)
//connect(发送信号的对象, 发送对象的信号成员函数地址),
//   接收对象, 接收对象的成员函数地址);
QObject::connect(btn, &PushButton::clicked(int)),
                   obj,  &MyWidget::onBtnPressed);

// 方法3(QT5之后可用的方法)
//connect(发送信号的对象, 发送对象的信号成员函数地址), 全局函数或lambda表达式);
QObject::connect(btn, &PushButton::clicked(int)),
                   lambda表达式);

信号的定义和触发

定义信号时在类声明中使用 singals 关键字,声明槽函数(仅声明,不用实现)。

语法格式

复制代码
class MyWidget: public QObject类或他的子类 {
    Q_OBJECT // 必须添加此宏
signals:
    返回类型 信号函数名1(参数列表);
    返回类型 信号函数名1(参数列表);
};

触发信号

触发信号也叫提交信号,在Qt的QObject类的成员函数内使用 emit 关键字来触发信号。

触发信号会调用所有已经连接此信号的函数。

语法如下

复制代码
emit 信号函数名(调用实参);

示例:登录对话框

loginwidget.h

复制代码
#ifndef LOGINWIDGET_H
#define LOGINWIDGET_H

#include <QLineEdit>
#include <QCheckBox>
#include <QLabel>
#include <QWidget>

class LoginWidget : public QWidget
{
    Q_OBJECT
public:
    explicit LoginWidget(QWidget *parent = nullptr);
public slots:
    void onBtnLogin(void);  // 点击登陆的槽函数
signals:
private:
    QLineEdit * username;
    QLineEdit * password;
    QCheckBox * autoSavePasswd;
    QLabel * errorHint; // 用于显示错误提示
};

#endif // LOGINWIDGET_H

loginwidget.cpp

复制代码
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QPushButton>
#include <QLabel>
#include <QLineEdit>
#include <QCheckBox>
#include <QDebug>

#include "loginwidget.h"

LoginWidget::LoginWidget(QWidget *parent) : QWidget(parent)
{
    QVBoxLayout *vlayout1 = new QVBoxLayout(this);

    // 用水平布局将QLabel 和 QLineEdit放在一起。
    QHBoxLayout *hlayout1 = new QHBoxLayout;
    vlayout1->addLayout(hlayout1); // 加入垂直布局
    QLabel * label = new QLabel("用户名:");
    label->setMinimumWidth(60);
    label->setAlignment(Qt::AlignRight);
    // 用户名的编辑框
    username = new QLineEdit();
    hlayout1->addWidget(label);
    hlayout1->addWidget(username);

    // 用水平布局将QLabel 和 QLineEdit放在一起。
    QHBoxLayout *hlayout2 = new QHBoxLayout;
    vlayout1->addLayout(hlayout2); // 加入垂直布局
    QLabel * label2 = new QLabel("密码:");
    label2->setAlignment(Qt::AlignRight);
    label2->setMinimumWidth(60);
    // 密码的编辑框
    password = new QLineEdit();
    hlayout2->addWidget(label2);
    hlayout2->addWidget(password);

    autoSavePasswd = new QCheckBox("记住密码");
    vlayout1->addWidget(autoSavePasswd);

    // 登陆失败提示:
    errorHint = new QLabel("用户名或密码错误!");
    errorHint->hide(); // 默认隐藏。
    vlayout1->addWidget(errorHint);

    // 注册登陆按钮
    QHBoxLayout *hlayout3 = new QHBoxLayout;
    vlayout1->addLayout(hlayout3);
    hlayout3->addWidget(new QPushButton("注册"));
    QPushButton * loginBtn = new QPushButton("登陆");
    hlayout3->addWidget(loginBtn);
    // 设置登陆和注册的间距
    hlayout3->setSpacing(30);
    // 设置 垂直方向的间距。
    vlayout1->setSpacing(15);
    // 设置外边距。
    vlayout1->setContentsMargins(50, 50, 50, 50);

    // 按钮的Pressed 信号 当前对象的 onBtnLogin 连接
    // 方法1
//    connect(loginBtn, SIGNAL(pressed()),
//            this, SLOT(onBtnLogin()));
    // 方法2
    connect(loginBtn, &QPushButton::pressed,
            this, &LoginWidget::onBtnLogin);
    // 方法3
//    connect(loginBtn, &QPushButton::pressed,
//            [=](){
//        qDebug() << "登陆按钮被点击";
//        errorHint->show();
//    });
}

void LoginWidget::onBtnLogin(void)
{
    QString name = username->text();
    QString pass = password->text();
    qDebug() << "用户名:" << username->text();
    qDebug() << "密码:" << password->text();
    qDebug() << "记住密码:" << autoSavePasswd->isChecked();
    //以下做登陆的操作。
    if (name=="root" && pass == "123456") {
        // 新建另外一个对话框并打开
        QWidget *chatWidget = new QWidget;
        chatWidget->setWindowTitle(QString("用户:") +name);
        chatWidget->show();
        this->close();
    } else {
        errorHint->show();
    }
}

键盘事件

基于QWidget 的对象在有键盘按下时会收到 KeyPressEvent 事件,按键抬起时会收到 KeyReleaseEvent事件。用户可以通过重写此函数来接收来自键盘的事件。

键盘事件的处理函数:

复制代码
void QWidget::keyPressEvent(QKeyEvent *event);
void QWidget::keyReleaseEvent(QKeyEvent *event)

event是指向按键信息的对象。

QKeyEvent对象的常用成员函数如下:

复制代码
int key() const
bool isAutoRepeat() const

鼠标事件

时间处理函数

复制代码
void QWidget::mousePressEvent(QMouseEvent *event);
void QWidget::mouseReleaseEvent(QMouseEvent *event);
void QWidget::mouseDoubleClickEvent(QMouseEvent *event);
void QWidget::mouseMoveEvent(QMouseEvent *event);

event 对象是QMouseEvent 对象,内部有鼠标按键的信息

相关推荐
147API7 分钟前
Python批量生成蒸馏数据,并发、重试、幂等和断点续跑
开发语言·jvm·python
青 春 记 忆9 分钟前
零基础入门python04:用注册校验理解字典、集合和条件判断
开发语言·vscode·python·python3.11
IT摆渡者10 分钟前
VM EXSI7.0存储硬盘故障处理
大数据·linux·github
kels889913 分钟前
实战排坑:黄金实时API开发,XAUUSD Tick报文异常处理实践
开发语言·python·websocket·网络协议·信息可视化
今天AI了吗16 分钟前
MCP 协议打通 AI 与国产数据库,SQL 调优全流程一站式闭环
数据库·人工智能·sql
阿pin17 分钟前
Java随笔-JDK7 HashMap头插法为何能导致死循环?
java·开发语言·hashmap
FBI HackerHarry浩19 分钟前
Pandas 库中用于分类变量独热编码(One-Hot Encoding)的函数 pd.get_dummies() 函数
开发语言·人工智能·python·pandas
赵民勇22 分钟前
systemd-cgtop命令详解
linux·运维
灯澜忆梦29 分钟前
【MySQL11】进阶篇 | 索引_#3使用规则
数据库·sql·mysql·性能优化
名字还没想好☜34 分钟前
Go 的 sync.Cond 实战:用条件变量做等待/通知,比忙轮询省 CPU
开发语言·数据库·后端·golang·go