Qt 学习笔记(二):常用控件、信号与槽

发布于 11 天前  42 次阅读


Qt 学习笔记(二):常用控件、信号与槽

学习常见 Widgets 控件的使用方式,理解 Qt 信号与槽机制,并完成自定义信号槽、消息对话框和调试输出。

常用控件

标签

用于显示文本与图片, 常用属性:大小、位置、文本、字体、对齐方式、边框、图像显示等


// 设置标签的文本
ui->label_title->setText("这是标题");
// 设置边框形状
ui->label_title->setFrameShape(QFrame::Box);
ui->label_title->setFrameShadow(QFrame::Sunken);
// 设置对齐方式
ui->label_title->setAlignment(Qt::AlignCenter);
// 设置字体
QFont font;
font.setFamily("宋体");
font.setPointSize(20);
font.setBold(true);
ui->label_title->setFont(font);
// 设置几何属性, this表示当前界面
int x = this->width()/2 - ui->label_title->width()/2;
int y = this->height()/2 - ui->label_title->height()/2;
ui->label_title->move(x, y); // 调整位置到界面的中间

// 标签显示静态图片
ui->label_img->setPixmap(QPixmap("../../../pics/32.png"));
ui->label_img->resize(200,200);
ui->label_img->setScaledContents(true); // 自动缩放

// 标签显示动态图片
mv = new QMovie;
mv->setFileName("../../../pics/1.gif");
ui->label_gif->setMovie(mv);
ui->label_gif->resize(200,200);
ui->label_gif->setScaledContents(true);
mv->start();

按钮


// 普通按钮
ui->pushButton_connet->setText("连接");
ui->pushButton_cancle->setText("取消");
ui->pushButton_connet->setFlat(true); // 扁平模式,不显示边框
ui->pushButton_connet->setShortcut(Qt::Key_Return);// 设置快捷键为 主键盘上的Enter键

// 设置控件的大小
ui->checkBox_save_sesstion->resize(90, ui->checkBox_save_sesstion->height());
// 设置复选框的状态
ui->checkBox_save_sesstion->setCheckState(Qt::Checked);
ui->checkBox_game->setChecked(true);
ui->checkBox_study->setChecked(true);
// 设置单选按钮的状态
ui->radioButton_female->setChecked(true);

文本框


// 大小、位置、文本、对齐方式 与 标签的设置方式相同
// 设置单行文本编辑框的显示模式为密码模式
ui->lineEdit->setEchoMode(QLineEdit::Password);

组合框


// 设置combBox的大小
ui->comboBox_protocal->resize(ui->comboBox_protocal->width()+10, ui->comboBox_protocal->height());
// 给combBox添加内容
ui->comboBox_protocal->addItem("SSH");
ui->comboBox_protocal->addItem("SSH2");
ui->comboBox_protocal->addItem("Telnet");
ui->comboBox_protocal->addItem("Serial");
// 设置当前显示的文本
ui->comboBox_protocal->setCurrentText("Serial");
// 获取组合框当前显示的文本,设置到文本框中
ui->textEdit->setText(ui->comboBox_protocal->currentText());

信号和槽

信号和槽是Qt的核心特性,用于Qt对象(QObject类及其派生类对象)之间的通信。

当我们改变一个控件的状态时,希望其他控件能得到通知。例如,用户点击一个关闭按钮,我们希望界面调用它的close函数。

其他界面框架可能用的是回调机制,但Qt不是,Qt用的是信号和槽,来实现Qt对象之间的通信。

Qt的控件有许多预定义的信号和槽,如果预定义的信号和槽不能满足需求,则可以自定义信号和槽。

信号和槽是类型安全的:信号的签名必须与接收槽函数的签名匹配。(事实上,槽的参数个数可能比它接收到的信号短,因为它可以忽略额外的参数。)。基于字符串的SIGNAL和SLOT语法将在运行时检测类型不匹配。

信号和插槽是松散耦合的:发出信号的类既不知道也不关心哪个槽接收信号。Qt的信号和槽机制确保,如果你将信号连接到槽,槽将在正确的时间被调用。信号和插槽可以接受任意数量的任何类型的参数。它们是完全类型安全的。
从QObject或其子类(例如QWidget)继承的所有类都可以包含信号和插槽。当对象的内部状态发生改变时,它们会发出信号。这就是对象进行通信的全部操作。它不知道也不在乎是否有任何对象在接收它发出的信号。

槽可用于接收信号,但它们也是普通的成员函数。正如对象不知道是否有任何其他对象接收到它的信号一样,槽也不知道它是否有任何信号连接到它。这确保了可以使用Qt创建真正独立的组件。

您可以将任意数量的信号连接到单个槽,也可以将信号连接到任意数量的插槽。甚至可以将一个信号直接连接到另一个信号。(每当发出第一个信号时,这将立即发出第二个信号。)
信号和插槽共同构成了一个强大的组件编程机制。

信号

当对象的内部状态发生变化时,对象会发出信号。信号是公共访问函数,可以从任何地方发出,但我们建议只从定义信号及其子类的类中发出。
当发出信号时,连接到它的槽函数通常会立即执行,就像正常的函数调用一样。当这种情况发生时,信号和槽机制完全独立于任何GUI事件循环。一旦所有槽函数都返回,就会执行emit语句后面的代码。使用排队连接时,情况略有不同;在这种情况下,emit关键字后面的代码将立即继续,稍后将执行槽函数。
如果多个槽函数连接到一个信号,则在发出信号时,这些槽函数将按照连接的顺序一个接一个地执行。
信号由元对象编译器(moc)自动生成,不得在.cpp文件中实现。

当连接到槽函数的信号发出时,会调用槽函数。槽是普通的C++函数,可以正常调用;它们唯一的特点是信号可以连接到它们。
由于槽是普通的成员函数,因此在直接调用时遵循普通的C++规则。
与回调相比,信号和槽的速度稍慢,因为它们提供了更大的灵活性,尽管在实际应用中差异不大。一般来说,发出连接到某些插槽的信号比使用非虚拟函数调用直接调用接收器慢大约十倍。

连接

信号和槽在通信之前必须进行连接,使用connect函数即可。


connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type = Qt::AutoConnection)
参数说明:
    sender		发出信号的对象的地址
    signal		发出的信号,一般需要使用 SIGNAL 进行包装
    receiver	信号接收对象的地址
    method		收到信号后,要执行的槽函数,一般需要使用 SLOT 进行包装
    type		连接类型,一般默认为AutoConnection。如果信号的发出者与接收者在同一线程中,则使用Qt::DirectConnection. 否则,使用 Qt::QueuedConnection. 

预定义的信号与槽示例:


// 连接界面上的关闭按钮与当前界面, 当关闭按钮被点击时,自动调用界面的close函数
connect(ui->pushButton_close, SIGNAL(clicked(bool)), this, SLOT(close()));

// 连接三个按钮
connect(ui->pushButton_hide, SIGNAL(clicked(bool)), ui->pushButton_close, SLOT(hide()));
connect(ui->pushButton_show, SIGNAL(clicked(bool)), ui->pushButton_close, SLOT(show()));

// 连接slider与spinbox
connect(ui->horizontalSlider, SIGNAL(valueChanged(int)), ui->spinBox, SLOT(setValue(int)));

说明:信号与槽在通信前必须连接,且只需要连接一次,多数时候,在构造函数中进行连接。

自定义槽函数

1、在头文件中声明


class 类名
{
public slots: 公有槽函数
	函数声明
private slots: 私有槽函数
    函数声明
protected slots: 保护的槽函数
	函数声明    	
};
说明:槽函数的返回值被忽略,一般返回类型为void即可

2、在源文件中定义


与普通的成员函数在类外定义相同
返回类型 类名::槽函数名(参数列表)
{
	函数体
}

3、调用


1、像普通函数一样的调用
2、在connect中与信号连接

练习:

实现一个简单的计算器

提示:从界面上获取的数据都是字符串,要进行计算,必须转成数字,得到数字结果后,如果要显示到界面的控件中,必须转成字符串

自定义信号

1.在头文件中声明一个信号


class 类名
{
signals:
	信号声明;
};

说明:
    信号本身就是公有的函数,不需要加访问修饰符!
    信号可以带参数!
    信号只需要声明,不需要用户定义!

2.发送信号


通过 emit  来发送信号!
注意:
	信号在发送前需要先连接槽函数,否则,信号发出以后没有Qt对象接收它,起不到作用!

信号与槽的另一种连接方式

右键界面设计器中的某个控件,在弹出的对话框中选择某个信号,点击确定,自动跳转到【编辑】模式,自动生成槽函数声明与定义
用户只需要填写槽函数定义即可,当信号发出时,此槽函数会自动执行。

例:

image-20251009143758992

image-20251009143602934

消息对话框

1、包含头文件 <QMessageBox>

2、使用示例


QMessageBox::information(this, "提示", "输入正确,即将跳转到主界面!");
QMessageBox::warning(this, "警告", "用户名或密码不能为空!");
QMessageBox::critical(this, "错误", "用户名或密码错误,请重试!");

调试输出

1、包含头文件 <QDebug>

2、使用示例


qDebug() << "用户名或密码不能为空!"; // 自带换行

"When faced with uncertainty, ask the spring breeze."