Linux 学习记录47(QT篇)
一、将资源文件加载到项目
1. 将资源文件放到项目下
2. 添加到项目
二、信号与槽机制
1. 信号与槽机制概念
信号与槽机制,是qt的核心机制,能够完成多个组件之间的互相通信,即一个组件发射信号,其他组件用于相应该信号,并做出相应处理工作
2. 信号与槽概念
- 信号:信号就是信号函数,可以是组件自身提供,也可以是用户自己定义,自定义时,需要在类体的signals权限下进行定义,并且该函数是一个不完整的函数,只有声明,没有定义
- 槽:是槽函数,可以由组件自身提供,也可以是用户自己定义,定义时,需要在类体的slots权限下进行声明,类外进行定义,该函数是一个完整的函数,既有声明,也有定义。并且槽函数可以像普通函数一样被调用,但是普通函数不能像槽函数一样连接信号
- 信号函数与槽函数,都是没有返回值的函数,可以有参数
- 包含信用与槽的类体的定义格式
(1. 定义格式
class Widget : public QWidget
{
Q_OBJECT //有关信号与槽的元对象,会将信号与槽的非标准C++代码,转变成标准的C++代码
signals:
void my_signal(); //此时自定义了一个无参无返回值的信号函数
public slots:
void my_slot(); //自定义的槽函数
public:
Widget(QWidget *parent = nullptr);
~Widget();
private:
Ui::Widget *ui;
};
3. 信号与槽的连接
(1. 使用UI界面
在ui界面下面的信号与槽区,进行相关的信号与槽绑定工作,该方式不常用,只能连接系统提供的信号与槽函数
在ui界面,对组件右键转到槽,选中信号函数,槽函数逻辑由用户自己书写
(2. 使用代码实现
使用qt4版本的连接函数连接信号与槽,该版本的连接是不友好的连接,当给定的信号和槽函数不存在,也不会报错
[static] QMetaObject::Connection //函数返回值,是一个信号与槽的连接,该函数是一个静态成员函数
QObject::connect( //函数名
const QObject *sender, //信号的发送者
const char *signal, //要发射的信号,将信号函数名需要进行转换后,才能当做该函数进行使用,SIGNAL(函数名)
const QObject *receiver, //信号接收者
const char *method) //接收信号要处理的槽函数,也需要进行转换,SLOT(函数名)
注意:需要使用SIGNAL() and SLOT()将信号函数和槽函数,由函数指针类型,转换为const char*类型后才能使用
举个例子:
QLabel *label = new QLabel;
QScrollBar *scrollBar = new QScrollBar;
QObject::connect(scrollBar, SIGNAL(valueChanged(int)),
label, SLOT(setNum(int)));
信号与槽的连接
[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);
C++11后的连接方式
[static] QMetaObject::Connection //函数返回值类型,是一个静态成员函数
QObject::connect( //函数名
const QObject *sender, //信号的发射者
PointerToMemberFunction signal, //要发射信号的地址
Functor functor) //信号发射后的处理函数
举个例子:
void someFunction();
QPushButton *button = new QPushButton;
QObject::connect(button, &QPushButton::clicked, someFunction);
载举个C++11后的例子:
QByteArray page = ...;
QTcpSocket *socket = new QTcpSocket;
socket->connectToHost("qt-project.org", 80);
QObject::connect(socket, &QTcpSocket::connected, [=] () {
socket->write("GET " + page + "\r\n");
});
(3. 断开连接
就是将上面的连接函数改成disconnect即可,参数不变
//断货按钮2的相关连接
disconnect(ui->btn2, SIGNAL(clicked()), this, SLOT(my_slot()));
//断开按钮3的相关连接
disconnect(btn3, &QPushButton::clicked, this, &Widget::btn3_slot);
4. 自定义的信号的定义以及发射
1. 自定义信号定义在类体的signal权限下
2. 信号函数,只有声明没有定义
3. 信号函数,返回值为void,参数可有可无
4. 在程序需要的地方,使用关键字emit 发射自定义的信号,例如:emit my_signal();
5. 将自定义的信号与槽函数进行连接,槽函数可以是系统提供的也可以是自定义的
class login : public QMainWindow
{
Q_OBJECT
signals:
void main_jump();//自定义信号函数
private slots:
public:
login(QWidget *parent = nullptr);
~login();
private:
Ui::login *ui;
};
5. 信号函数与槽函数的总结
- 一个信号函数可以对应多个槽函数
- 多个信号函数,可以对应一个槽函数
- 一般要求信号函数的参数个数和类型必须跟槽函数的参数和类型保持一致
- 当信号函数的参数大于槽函数参数个数时,也可以,也就是说槽函数可以不接受信号函数的参数,但是不能乱接收信号函数的参数
- 当信号函数的参数小于槽函数的参数时,那么要求槽函数的参数,右侧的参数要有默认参数,否则报错
- 信号函数,也可以连接信号函数,能够做到,当一个信号被发射后,另一个信号也被发射
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
6. 使用信号与槽实现多个界面的跳转
(1. 创建两个界面文件
在编辑器的项目处,邮件,add new
(2. 创建一个新的界面
(3. 两个界面的头文件
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
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_jumpBtn_clicked();
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
/***********************************第二个界面的头文件*******************/
#ifndef SECOND_H
#define SECOND_H
#include <QWidget>
namespace Ui {
class Second;
}
class Second : public QWidget
{
Q_OBJECT
public:
explicit Second(QWidget *parent = nullptr);
~Second();
public slots:
void jump_slot(); //定义有关处理跳转信号的槽函数
private:
Ui::Second *ui;
};
#endif // SECOND_H
(2. 两个界面.cpp文件
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//信号函数也可以连接信号函数
//connect(ui->jumpBtn, &QPushButton::clicked, this, &Widget::jump);
}
Widget::~Widget()
{
delete ui;
}
跳转按钮对应的槽 函数
void Widget::on_jumpBtn_clicked()
{
//发射跳转信号
emit jump();
//关闭当前 界面
this->hide();
}
/*************************************第二个文件的源文件****************/
#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(); //将当前界面进行展示
}
(4. main.cpp
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
login w;
main_page m;
sign_up s;
w.show();
/*main.cpp作为第三方连接两个页面*/
QObject::connect(&w,&login::main_jump,&m,&main_page::jump_slot);
return a.exec();
}
练习
1. main_page.cpp
#include "main_page.h"
#include "ui_main_page.h"
main_page::main_page(QWidget *parent) :
QWidget(parent),
ui(new Ui::main_page)
{
ui->setupUi(this);
//设置固定尺寸
this->setFixedSize(600,360);
this->setWindowTitle("Qt window");//当前界面尺寸
//设置窗口图标
this->setWindowIcon(QIcon(":/new/prefix1/Qt_w.png"));//设置窗口图标
this->setStyleSheet("background-color:#F5F5F5;");//设置窗口背景颜色
// 创建一个QLabel用于显示动态图
QLabel label;
// 创建一个QMovie对象,并加载动态图文件
QMovie movie("path_to_your_animated_gif.gif");
}
//处理跳转信号函数对应的槽函数
void main_page::jump_slot(void)
{
this->show(); //将当前界面进行展示
}
main_page::~main_page()
{
delete ui;
}
2. main.cpp
#include "login.h"
#include "main_page.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
login w;
main_page m;
w.show();
QObject::connect(&w,&login::jump,&m,&main_page::jump_slot);
return a.exec();
}
3. main_page.h
#ifndef MAIN_PAGE_H
#define MAIN_PAGE_H
#include <QWidget>
#include <QGridLayout>
#include <QString>
#include <QPushButton>
#include <QDebug>
#include <QLabel>
#include <QIcon>
#include <QMovie>
#include <QLineEdit>
#include <QFont>
namespace Ui {
class main_page;
}
class main_page : public QWidget
{
Q_OBJECT
public slots:
void jump_slot(void); //定义有关处理跳转信号的槽函数
public:
explicit main_page(QWidget *parent = nullptr);
~main_page();
private:
Ui::main_page *ui;
};
#endif // MAIN_PAGE_H
4. login.cpp
#include "login.h"
#include "ui_login.h"
QString UID_set = "321142827";
QString pswd_set = "zd332526";
login::login(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::login)
{
ui->setupUi(this);
QFont font;//字体设置
/***********************窗口设置***********************/
//设置固定尺寸
this->setFixedSize(600,360);
this->setWindowTitle("Qt window");//当前界面尺寸
//设置窗口图标
this->setWindowIcon(QIcon(":/new/prefix1/Qt_w.png"));//设置窗口图标
this->setStyleSheet("background-color:#F5F5F5;");//设置窗口背景颜色
/*// 创建一个QLabel用于显示动态图
QLabel* label = new QLabel (this);
// 创建一个QMovie对象,并加载动态图文件
QMovie* movie = new QMovie ("C:\\Users\\Hao\\Desktop\\buf\\bule2.gif");
// 将QMovie与QLabel关联
label->setMovie(movie);
// 开始播放动态图
movie->start();
// 调整标签大小以适应动态图
label->adjustSize();*/
QLabel *theme1 = new QLabel(this);//设置窗口上半主题
theme1->resize(600,180);//设置窗口上半主题空间
theme1->setPixmap(QPixmap(":/new/prefix1/Qt.jpg"));//设置窗口上半主题样式
QLabel *lab2 = new QLabel(this);//UID图标
lab2->resize(40,40);
lab2->move(205,205);
lab2->setPixmap(QPixmap(":/new/prefix1/UID.png"));
lab2->setScaledContents(true);
QLabel *lab3 = new QLabel(this);//Pass word图标
lab3->resize(40,40);
lab3->move(205,245);
lab3->setPixmap(QPixmap(":/new/prefix1/lock.png"));
lab3->setScaledContents(true);
/***********************按钮设置***********************/
int Button_size[2]={80,40};//登录/取消按键设置
int Button_move_L[2]={200,290};//登录按键坐标
int Button_move_C[2]={320,290};//取消按键坐标
log_on = new QPushButton(QIcon(":/new/prefix1/UID.png"),"登录", this);
cancel = new QPushButton(QIcon(":/new/prefix1/cancel.png"),"取消", this);
log_on->resize(Button_size[0],Button_size[1]);
log_on->move(Button_move_L[0],Button_move_L[1]);
log_on->setStyleSheet("border:none;border-radius:10px;background-color:#3CB371;color:#fff");
cancel->resize(Button_size[0],Button_size[1]);
cancel->move(Button_move_C[0],Button_move_C[1]);
cancel->setStyleSheet("border:none;border-radius:10px;background-color:#3CB371;color:#fff");
connect(log_on,&QPushButton::clicked,this,&login::login_signals);
connect(cancel,&QPushButton::clicked,this,&login::cancel_signals);
/***********************编辑器设置***********************/
font.setPointSize(12);
font.setFamily("宋体");
int line_len = 150;//行编辑器长度
int line_width = 30;//行编辑器长度
int UID_move[2]={250,210};//行编辑器坐标
int Pswd_move[2]={250,250};//行编辑器坐标
int prompt_move[2]={205,190};//行编辑器坐标
/*配置UID编辑器*/
UID = new QLineEdit(this);
UID->resize(line_len,line_width);//重新设置大小
UID->move(UID_move[0],UID_move[1]);//移动
UID->setStyleSheet("border:none;border-radius:10px;background-color:#696969;color:#fff;opacity: 0.3;");// 设置样式表
UID->setPlaceholderText("UID");//设置占位文本
UID->setFont(font);
/*配置密码编辑器*/
pswd = new QLineEdit(this);
pswd->resize(line_len,line_width);//重新设置大小
pswd->move(Pswd_move[0],Pswd_move[1]);//移动
pswd->setStyleSheet("border:none;border-radius:10px;background-color:#696969;color:#fff;opacity: 0.5;");// 设置样式表
pswd->setPlaceholderText("Pass word");//设置占位文本
pswd->setEchoMode(QLineEdit::Password);//设置密文模式
pswd->setFont(font);
pswd->setWindowOpacity(0.5);
font.setPointSize(10);
font.setFamily("黑体");
prompt = new QLineEdit(this);
prompt->resize(200,15);//重新设置大小
prompt->move(prompt_move[0],prompt_move[1]);//移动
prompt->setStyleSheet("border:none;border-radius:10px;color:#FF0000");// 设置样式表
prompt->setPlaceholderText("请输入登录信息");//设置占位文本
prompt->setFont(font);
prompt->setAlignment(Qt::AlignCenter);
prompt->setEnabled(false);
}
void login::login_signals(void)
{
QString UID_line;
QString pswd_line;
UID_line = UID->text();
pswd_line = pswd->text();
if(UID_line==UID_set && pswd_line==pswd_set)
{//登陆成功
emit jump();//发送跳转信号
this->close();//关闭当前界面
}else
{//账号/密码错误
prompt->setPlaceholderText("UID/pswd错误");//设置占位文本
}
}
void login::cancel_signals(void)
{
/*文本内容*/
UID->clear();
pswd->clear();
}
login::~login()
{
delete ui;
}
5. login.h
#ifndef LOGIN_H
#define LOGIN_H
#include <QMainWindow>
#include <QGridLayout>
#include <QString>
#include <QPushButton>
#include <QDebug>
#include <QLabel>
#include <QIcon>
#include <QMovie>
#include <QLineEdit>
#include <QFont>
QT_BEGIN_NAMESPACE
namespace Ui { class login; }
QT_END_NAMESPACE
class login : public QMainWindow
{
Q_OBJECT
signals:
void jump(); //自定义跳转函数
private slots:
void login_signals(void);
void cancel_signals(void);
public:
login(QWidget *parent = nullptr);
~login();
private:
Ui::login *ui;
QPushButton *log_on;//登录按键
QPushButton *cancel;//取消按键
QLineEdit *UID;
QLineEdit *pswd;
QLineEdit *prompt;
};
#endif // LOGIN_H