作业
完善登录框
点击登录按钮后,判断账号(admin)和密码(123456)是否一致,如果匹配失败,则弹出错误对话框,文本内容“账号密码不匹配,是否重新登录”,给定两个按钮ok和cancel,点击ok后,会清除密码框中的内容,继续进行登录;如果点击cancel按钮,则关闭界面。
如果账号和密码匹配,则弹出信息对话框,给出提示信息为“登录成功”,给出一个按钮ok,点击ok后,关闭整个登录界面,跳转到其他界面
点击取消按钮后,弹出问题对话框,询问是否确定要退出登录,给出两个按钮,yes|no,点击yes,则直接关闭整个登录界面,如果点击no则进行进行登录
要求:消息对话框,对象版和静态成员函数版至少各实现一个
【免费】2023/9/18-C++/QT实现简易登录资源-CSDN文库https://download.csdn.net/download/weixin_54147737/88354416
一、信号与槽机制
1.1 简介
1> 信号与槽机制,是qt引以为傲的、能够立于编程界而不倒的核心机制
2> 作用:实现多个组件之间的互相通信,一个组件发信号,另一个组件接收信号后,做相应的响应
3> 原理类似于IO中的两个进程间通过信号通信,但是,这里的信号,是可以传递信息的
1.2 信号与槽
1> 信号:信号函数,定义在类体内signals权限下的特殊成员函数,该函数是不完整的函数,只有声明,没有定义,返回值为void,参数就是传递的信息
2> 槽:槽函数,定义在类体内slots权限下的成员函数,该函数是完整的函数,既有声明也有定义,返回值为void类型,参数就是接收信号的信息
3> 槽函数可以被当作普通函数一样调用,但是普通函数不能当作槽函数一样连接信号
4> 信号函数和槽函数,不是标准的C++代码,通过moc.exe工具将其自动转化为标准的C++代码
5> 信号函数和槽函数可以是组件自带的,也可以由用户自定义,系统提供的每个组件都会自带信号与槽
6> 包含信号与槽的类体定义
class Widget : public QWidget
{
Q_OBJECT //有关信号与槽的元对象
signals: //该权限下定义属于自己的信号
void my_signal(); //自定义一个无参无返回值的信号函数
private slots:
void my_slot(); //自定义无参无返回值的槽函数
public:
Widget(QWidget *parent = nullptr);
~Widget();
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
1.3 信号与槽的连接
1> 基于ui界面的,手动选中信号与槽的连接,该连接只适用于系统提供的信号与槽的连接,连接函数也是由系统实现
2> 也是基于ui界面,在组件上右键转到槽,手动实现槽函数的内容,该方法只能更改槽函数逻辑,信号、连接都是由系统实现
3> qt4版本手动连接信号与槽,该连接是不友好的连接,因为两个宏的原因,它会将所有传递的数据都改成字符串类型
[static] QMetaObject::Connection //返回值:是建立的信号与槽的连接,是一个静态成员函数
QObject::connect( //函数名
const QObject *sender, //信号发射者,是组件的指针
const char *signal, //要发射的信号函数,函数是函数指针,要的是字符串类型,所以需要使用SIGNAL()宏进行转换后使用
const QObject *receiver, //信号接收者,是组件的指针
const char *method) //接收信号后,接收者要处理的槽函数,函数是函数指针,要的是字符串类型,所以需要使用SLOT()宏进行转换后使用
举个例子:
QLabel *label = new QLabel;
QScrollBar *scrollBar = new QScrollBar;
QObject::connect(scrollBar, SIGNAL(valueChanged(int)),
label, SLOT(setNum(int)));
4> qt5版本的信号与槽的连接
[static] QMetaObject::Connection //返回值:是建立的信号与槽的连接,是一个静态成员函数
QObject::connect( //函数名
const QObject *sender, //信号发射者,是组件的指针
PointerToMemberFunction signal, //信号函数的指针,要指定是哪个类中的哪个成员函数
const QObject *receiver, //信号接收者,是组件的指针
PointerToMemberFunction method) //槽函数的指针,要指定是哪个类中的哪个成员函数
举个例子:
QLabel *label = new QLabel;
QLineEdit *lineEdit = new QLineEdit;
QObject::connect(lineEdit, &QLineEdit::textChanged,
label, &QLabel::setText);
5> 信号连接功能函数
[static] QMetaObject::Connection //返回值:是建立的信号与槽的连接,是一个静态成员函数
QObject::connect( //函数名
const QObject *sender, //信号发射者,是组件的指针
PointerToMemberFunction signal, //信号函数的指针,要指定是哪个类中的哪个成员函数
Functor functor) //功能函数:全局函数作为功能函数、仿函数作为功能函数、lambda表达式作为功能函数
举个例子1,全局函数作为功能函数:
void someFunction();
QPushButton *button = new QPushButton;
QObject::connect(button, &QPushButton::clicked, someFunction);
举个例子2:lambda作为功能函数
QByteArray page = ...;
QTcpSocket *socket = new QTcpSocket;
socket->connectToHost("qt-project.org", 80);
QObject::connect(socket, &QTcpSocket::connected, [=] () {
socket->write("GET " + page + "\r\n");
});
6> 信号与槽的断开
只需将之前的连接函数的connect改成disconnect即可,参数不变
1.4 信号的定义与发射
1、在类体的signals权限下,定义属于自己的信号
2、信号函数只有声明,没有定义,返回值为void,可用有参数
3、在程序所需处,使用关键字emit发射自定义的信号,格式:emit 信号名(实参);
4、信号函数可以连接到槽函数中,也可以连接另一个信号函数,表明发射第一个信号时,第二个信号跟着发射
1.5 信号与槽的总结
1> 一个信号可以连接多个槽函数
2> 一个槽函数可以连接多个信号函数
3> 一个信号函数可以连接到槽函数中,也可以连接另一个信号
4> 信号函数和槽函数参数个数
1、信号函数和槽函数进行链接时,一般要求信号函数和槽函数的参数保持一致
connect(信号发送者, SIGNAL(signalFun()),信号接收者, SLOT(slotFun())); //Ok
connect(信号发送者, SIGNAL(signalFun(int)),信号接收者, SLOT(slotFun(int))); //Ok
connect(信号发送者, SIGNAL(signalFun(int, char)),信号接收者, SLOT(slotFun(int, char))); //Ok
connect(信号发送者, SIGNAL(signalFun(char, int)),信号接收者, SLOT(slotFun(int, char))); //False
connect(信号发送者, SIGNAL(signalFun(int)),信号接收者, SLOT(slotFun(char))); //False
2、当信号函数的参数大于槽函数的参数时
connect(信号发送者, SIGNAL(signalFun(int, char)),信号接收者, SLOT(slotFun())); //Ok
connect(信号发送者, SIGNAL(signalFun(int, char)),信号接收者, SLOT(slotFun(int))); //Ok
connect(信号发送者, SIGNAL(signalFun(int, char)),信号接收者, SLOT(slotFun(char))); //False
3、当信号函数的参数小于槽函数的参数时
connect(信号发送者, SIGNAL(signalFun(int)),信号接收者, SLOT(slotFun(int, char))); //False
connect(信号发送者, SIGNAL(signalFun(int)),信号接收者, SLOT(slotFun(int, char=0))); //Ok
1.6 使用信号与槽实现简单的页面跳转
1> 准备两个界面
2> 在第一个界面中,定义跳转的信号函数,第二个界面定义槽函数
3> 可以在主程序中实例化两个界面,第一个界面调用show函数,第二个不调用,并且在主调函数中将第一个界面的信号与第二个界面的槽函数连接
1) 头文件
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include"second.h"
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
signals:
void jump(); //自定义跳转信号函数
private slots:
void on_loginBtn_clicked();
private:
Ui::Widget *ui;
Second *s1; //定义另一个界面的指针
};
#endif // WIDGET_H
second.h
#ifndef SECOND_H
#define SECOND_H
#include <QWidget>
namespace Ui {
class Second;
}
class Second : public QWidget
{
Q_OBJECT
public slots:
void jump_slot(); //接收跳转信号的槽函数
public:
explicit Second(QWidget *parent = nullptr);
~Second();
private:
Ui::Second *ui;
};
#endif // SECOND_H
2) 源文件
widget.cpp
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
s1 = new Second; //给另一个界面实例化空间
//将当前界面的信号,与s1界面的槽函数进行连接
connect(this,&Widget::jump, s1, &Second::jump_slot);
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_loginBtn_clicked()
{
emit jump();
this->hide(); //将当前界面隐藏
}
second.cpp
#include "second.h"
#include "ui_second.h"
Second::Second(QWidget *parent) :
QWidget(parent),
ui(new Ui::Second)
{
ui->setupUi(this);
}
Second::~Second()
{
delete ui;
}
//接收跳转信号对应的槽函数
void Second::jump_slot()
{
this->show(); //将自己界面进行展示
}
3) 主程序
#include "widget.h"
#include"second.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
//Second s; //定义第二个界面
//连接w的信号与s的槽
//QObject::connect(&w, &Widget::jump, &s, &Second::jump_slot);
return a.exec();
}
二、对话框
2.1 消息对话框(QMessageBox)
1> 该类提供的消息对话框,用于提高用户的交互性,可以提供问题对话框、信息对话框、警告对话框、错误对话框。。。
2> 实现该对话框的方式有两种:基于属性版本、静态成员函数版本
3> 基于属性版本实现消息对话框:公共该类实例化对象,调用exec函数进入执行态,该函数返回值时用户点击的按钮
QMessageBox::QMessageBox( //构造函数函数名
QMessageBox::Icon icon, //图标
const QString &title, //对话框标题
const QString &text, //对话框提示文本内容
QMessageBox::StandardButtons buttons = NoButton, //对话框提供的按钮,如果有多个按钮,则使用位或隔开
QWidget *parent = nullptr) //父组件
参数1介绍,对话框提供的图标,该类中的枚举值
Constant
Value
Description
QMessageBox::NoIcon
0
the message box does not have any icon.//不提供任何图标
QMessageBox::Question
4
an icon indicating that the message is asking a question.//提供一个问号图标
QMessageBox::Information
1
an icon indicating that the message is nothing out of the ordinary.//提供一个i符号图标
QMessageBox::Warning
2
an icon indicating that the message is a warning, but can be dealt with.//提供一个感叹号图标
QMessageBox::Critical
3
an icon indicating that the message represents a critical problem. //提供一个叉号图标
参数4介绍,对话框上提供的标准按钮,时类中的枚举值,如果有多个按钮,中间有位或隔开
Constant
Value
Description
QMessageBox::Ok
0x00000400
An "OK" button defined with the AcceptRole. //提供一个ok按钮
QMessageBox::Open
0x00002000
An "Open" button defined with the AcceptRole. //提供一个open按钮
QMessageBox::Save
0x00000800
A "Save" button defined with the AcceptRole. //提供一个保存按钮
QMessageBox::Cancel
0x00400000
A "Cancel" button defined with the RejectRole. //提供一个取消按钮
QMessageBox::Close
0x00200000
A "Close" button defined with the RejectRole. //提供一个关闭按钮
QMessageBox::Discard
0x00800000
A "Discard" or "Don't Save" button, depending on the platform, defined with the DestructiveRole.//不保存
举个例子:
QMessageBox msgBox; //实例化对象
msgBox.setText("The document has been modified.");
msgBox.setInformativeText("Do you want to save your changes?");
msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
msgBox.setDefaultButton(QMessageBox::Save);
int ret = msgBox.exec(); //展示对话框
//判断用户点击的结果
switch (ret) {
case QMessageBox::Save:
// Save was clicked
break;
case QMessageBox::Discard:
// Don't Save was clicked
break;
case QMessageBox::Cancel:
// Cancel was clicked
break;
default:
// should never be reached
break;
}
4> 基于静态成员函数版本:无需实例化对象,但是只能设置有限的信息
[static] QMessageBox::StandardButton //函数返回值类型,是用户点击的标准按钮,该函数是静态成员函数
QMessageBox::warning( //函数名
QWidget *parent, //父组件
const QString &title, //对话框标题
const QString &text, //对话框文本内容
QMessageBox::StandardButtons buttons = Ok, //提供的标准按钮,多个按钮用位或隔开
QMessageBox::StandardButton defaultButton = NoButton) //默认选中的按钮
举个例子:
int ret = QMessageBox::warning(this, tr("My Application"),
tr("The document has been modified.\n"
"Do you want to save your changes?"),
QMessageBox::Save | QMessageBox::Discard
| QMessageBox::Cancel,
QMessageBox::Save);
其余的静态成员函数
QMessageBox::StandardButton
critical(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons = Ok, QMessageBox::StandardButton defaultButton = NoButton)
QMessageBox::StandardButton
information(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons = Ok, QMessageBox::StandardButton defaultButton = NoButton)
QMessageBox::StandardButton
question(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons = StandardButtons(Yes | No), QMessageBox::StandardButton defaultButton = NoButton)
5> 案例
1) 头文件
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include<QMessageBox> //消息对话框类
#include<QDebug>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
private slots:
void on_quesBtn_clicked();
void on_warnBtn_clicked();
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
2) 源文件
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
}
Widget::~Widget()
{
delete ui;
}
//问题按钮对应的槽函数
void Widget::on_quesBtn_clicked()
{
//1、调用构造函数实例化对象
QMessageBox box(QMessageBox::Question, //图标
"问题", //对话框标题
"晚上约不?", //对话框文本内容
QMessageBox::Yes | QMessageBox::No, //提供的按钮
this); //父组件
box.setDetailedText("有上好的飞天茅台"); //提供详细文本内容
box.setDefaultButton(QMessageBox::No); //将no设置成默认按钮
box.setButtonText(QMessageBox::Yes, "好的");
box.setButtonText(QMessageBox::No, "没空");
//2、调用exec函数运行对话框
int ret = box.exec();
//3、对结果进行判断
if(ret == QMessageBox::Yes)
{
qDebug()<<"木的问题,老地方见";
}else if(ret == QMessageBox::No)
{
qDebug()<<"下次一定";
}
}
//警告按钮对应的槽函数
void Widget::on_warnBtn_clicked()
{
//直接调用静态成员函数完成对话框的实现
int ret = QMessageBox::warning(this, //父组件
"警告", //对话框标题
"放学等着,别走", //对话框文本内容
QMessageBox::Yes|QMessageBox::No, //对话题提供的按钮
QMessageBox::No); //默认选中的按钮
//对用户选中的按钮进行判断
if(ret == QMessageBox::Yes)
{
qDebug()<<"行,荤的还是素的,文的还是武的任你挑";
}else if(ret == QMessageBox::No)
{
qDebug()<<"你永远是我大哥";
}
}