嵌入式养成计划-43----QT QMainWindow中常用类的使用--ui界面文件--资源文件的添加--信号与槽

本文主要是介绍嵌入式养成计划-43----QT QMainWindow中常用类的使用--ui界面文件--资源文件的添加--信号与槽,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一百零九、QMainWindow中常用类的使用

109.1 菜单栏 QMenuBar

  • 菜单栏 QMenuBar 最多只能有一个

109.2 工具栏 QToolBar

  • 工具栏 QToolBar 可以有多个

109.3 状态栏QStatusBar

  • 状态栏 QStatusBar 最多只能有一个

109.4 浮动窗口QDockWidget

  • 浮动窗口 可以有多个

109.5 代码示例

  • main.cpp
#include "my_mainwindow.h"
#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);my_MainWindow w;w.show();return a.exec();
}
  • my_mainwindow.h
#ifndef MY_MAINWINDOW_H
#define MY_MAINWINDOW_H#include <QMainWindow>
#include <QMenuBar>     //  菜单栏的类
#include <QToolBar>
#include <QPushButton>
#include <QStatusBar>
#include <QLabel>
#include <QDockWidget>  //  浮动窗口类   铆接部件
#include <QTextEdit>    //  文本编辑类class my_MainWindow : public QMainWindow
{Q_OBJECTpublic:my_MainWindow(QWidget *parent = nullptr);~my_MainWindow();
};
#endif // MY_MAINWINDOW_H
  • my_mainwindow.cpp
#include "my_mainwindow.h"my_MainWindow::my_MainWindow(QWidget *parent): QMainWindow(parent)
{// 调整窗口大小this->resize(600,400);// 创建菜单栏    QMenuBar    最多只能有一个QMenuBar *mbar = menuBar();// 把菜单栏放到当前窗口中this->setMenuBar(mbar);// 往菜单栏中增加菜单QMenu *file = mbar->addMenu("文件");// mbar->setStyleSheet("background-color:black");QMenu *edit = mbar->addMenu("编辑");// 往 "文件" 菜单中增加菜单项file->addAction("新建");// 增加分隔符file->addSeparator();// 往菜单中增加菜单项file->addAction("打开");// 创建工具栏 QToolBar 可以有多个QToolBar *tbar = new QToolBar(this);// 把工具栏放到窗口中this->addToolBar(Qt::LeftToolBarArea,tbar);// 后期设置  只允许停靠范围  左边 或 右边  可以继续或tbar->setAllowedAreas(Qt::LeftToolBarArea | Qt::RightToolBarArea);// 设置不允许浮动tbar->setFloatable(false);// 往工具栏中增加工具项   文本tbar->addAction("锤子");// 往工具栏中增加工具项   按钮QPushButton *btn = new QPushButton("榔头",this);tbar->addWidget(btn);// 创建状态栏 QStatusBar 最多只能有一个QStatusBar *sbar = statusBar();// 把状态栏放到窗口中this->setStatusBar(sbar);// 在状态栏中增加标签QLabel *lab = new QLabel("标签",this);// 往状态栏中增加标签组件// 默认在左边
//    sbar->addWidget(lab);// 默认在右边sbar->addPermanentWidget(lab);// 创建浮动窗口 QDockWidget 可以有多个QDockWidget *dock = new QDockWidget("浮动窗口",this);// 把浮动窗口放到窗口中this->addDockWidget(Qt::TopDockWidgetArea, dock);// 设置浮动窗口的停靠范围dock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);// 中心部件 最多只能有一个QTextEdit *text = new QTextEdit(this);// 将中心部件放到窗口中this->setCentralWidget(text);}my_MainWindow::~my_MainWindow()
{
}
  • 运行结果
    在这里插入图片描述

一百一十、ui界面文件

  • ui界面文件在项目工程文件的Forms文件夹下,
  • 可以通过ui指针访问到ui界面上的所有组件(控件)。
  • 创建时需要选中 ui 的界面

ui 操作界面
在这里插入图片描述

一百一十一、资源文件的添加

  • 添加资源文件后,需要用到文件就可以不再用绝对路径了
  • 方便把整个项目打包,这样别人打开
  1. 把资源文件放入到该项目工程文件中,选中项目中任意一个文件,右击,在explorer中显示,将资源文件复制到该项目下。
  2. 添加资源文件
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  3. 选中文件夹中的所有文件
    在这里插入图片描述
  4. 最后 Ctrl+B 或者左下角的锤子,构建一下

一百一十二、信号与槽

  1. 信号和槽是qt引以为傲的核心机制之一,可以实现多个组件之间的相互通信
  2. 信号:信号函数,定义在类体的signals权限下,信号函数不是一个完整的函数,只有声明,没有定义。
  3. 槽:槽函数,定义在类体的slots权限下,槽函数是一个完整的函数,既有声明,又有定义,也可以当成普通函数调用。
  4. 任何组件都有系统提供的默认信号函数和槽函数。

112.1 包含信号函数和槽函数的类体定义

#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECT //有关信号和槽的宏public:Widget(QWidget *parent = nullptr);~Widget();signals:     //表示该权限下都是信号函数void my_signal();  //自定义一个信号函数public slots:  //表示该权限下是公共的槽函数void my_slot();  //自定义一个槽函数private:Ui::Widget *ui;
};
#endif // WIDGET_H

112.2 信号和槽的连接方式

  • 基于ui界面上的连接,在ui界面下面的信号与槽区,进行信号与槽的连接,该连接只适用于系统提供的信号和槽
    不需要手动书写信号函数,槽函数,连接函数。
    在这里插入图片描述

  • 基于ui界面上的连接,在组件上,右击–>转到槽,选中要发射的信号,需要程序员在槽函数中写逻辑代码,但也不需要写连接函数。
    在这里插入图片描述

    //按钮2对应的槽函数
    void Widget::on_Btn2_clicked()
    {//让按钮1变色//ui->Btn1->setStyleSheet("background-color:red");static int num = 0;if(num%3 == 0){ui->Btn1->setStyleSheet("background-color:red");}else if (num%3 == 1){ui->Btn1->setStyleSheet("background-color:green");}else if (num%3 == 2){ui->Btn1->setStyleSheet("background-color:blue");}++num;
    }
    
  • 手动连接信号和槽函数,基于qt4版本,该连接是不友好的连接

    [static] QMetaObject::Connection  //返回值类型  是一个静态成员函数,实现信号和槽的连接QObject::connect(            //函数名const QObject *sender,       //信号的发送者,是一个组件的指针const char *signal,          //发送具体的信号(信号函数),使用const char* ,而函数名使用函数指针来接收,需要用SIGNAL()转换const QObject *receiver,     //信号的接受者,是一个组件的指针const char *method, )       //对信号处理的槽,使用const char* ,而函数名使用函数指针来接收,需要用SLOT()转换举个例子:QLabel *label = new QLabel;QScrollBar *scrollBar = new QScrollBar;QObject::connect(scrollBar, SIGNAL(valueChanged(int)),label,  SLOT(setNum(int)));
    
  • 手动连接信号和槽函数,基于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);
    
  • 手动连接信号和功能函数,只要组件发射了信号,就自动调用功能函数的内容。
    功能函数可以是 全局函数,也可以是 lambda表达式

    [static] QMetaObject::Connection  //函数返回值类型QObject::connect(      //函数名const QObject *sender,  //信号的发送者PointerToMemberFunction signal,  //信号函数Functor functor)   //功能函数
    

    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");
    });
    

112.3 定义语音播报

  • 在工程文件中增加这个 :texttospeech
    在这里插入图片描述
    头文件
    #ifndef WIDGET_H
    #define WIDGET_H#include <QWidget>
    #include<QPushButton>
    #include<QTextToSpeech> //语音播报类QT_BEGIN_NAMESPACE
    namespace Ui { class Widget; }
    QT_END_NAMESPACEclass Widget : public QWidget
    {Q_OBJECT //有关信号和槽的宏
    public:Widget(QWidget *parent = nullptr);~Widget();
    signals:     //表示该权限下都是信号函数void my_signal();  //自定义一个信号函数
    public slots:  //表示该权限下是公共的槽函数void my_slot();  //自定义一个槽函数void Btn4_slot();  //btn4对应的槽函数声明
    private slots:void on_Btn2_clicked(); //系统定义的槽函数声明
    private:Ui::Widget *ui;QPushButton *btn3;//定义一个语音播报者QTextToSpeech *speecher;
    };
    #endif // WIDGET_H
    
    源文件
    #include "widget.h"
    #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
    {ui->setupUi(this);//给语音播报者实例一个空间speecher = new QTextToSpeech(this);//实例化一个按钮btn3 = new QPushButton("按钮3",this);btn3->move(ui->Btn2->x(), ui->Btn2->y()+ui->Btn2->height()+10);btn3->resize(ui->Btn2->width(),ui->Btn2->height());//手动连接信号和系统槽,基于qt4版本  是不友好的连接//函数原型:[static] QMetaObject::Connection QObject::connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type = Qt::AutoConnection)//参数1:是一个组件的指针 信号的发送者//参数2:信号函数,需要宏函数转换//参数3:是一个组件的指针 信号的接受者//参数4:槽函数,需要宏函数转换//connect(btn3, SIGNAL(clicked()), this, SLOT(close()));//手动连接信号和系统槽,基于qt4版本  是不友好的连接this->connect(btn3, SIGNAL(clicked()), this,SLOT(my_slot()));//手动连接信号和自定义槽,基于qt5版本  是友好的连接//函数原型:[static] QMetaObject::Connection QObject::connect(const QObject *sender, PointerToMemberFunction signal, const QObject *receiver, PointerToMemberFunction method, Qt::ConnectionType type = Qt::AutoConnection)//参数1:是一个组件的指针 信号的发送者connect(ui->Btn4, &QPushButton::clicked, this, &Widget::Btn4_slot);
    }
    Widget::~Widget()
    {delete ui;
    }
    //自定义槽函数的实现
    void Widget::my_slot()
    {this->close();
    }
    //按钮4对应的槽函数实现    #include<QTextToSpeech> //语音播报类
    void Widget::Btn4_slot()
    {//this->close();static int num = 0;if(num%3 == 0){speecher->say("咳咳咳");}else if (num%3 == 1){speecher->say(ui->Btn2->text());}else if (num%3 == 2){speecher->say(this->btn3->text());}++num;
    }
    //按钮2对应的槽函数
    void Widget::on_Btn2_clicked()
    {//让按钮1变色//ui->Btn1->setStyleSheet("background-color:red");static int num = 0;if(num%3 == 0){ui->Btn1->setStyleSheet("background-color:red");}else if (num%3 == 1){ui->Btn1->setStyleSheet("background-color:green");}else if (num%3 == 2){ui->Btn1->setStyleSheet("background-color:blue");}++num;
    }
    

112.4 自定义信号

  1. 自定义信号,写在类体的signals权限下,无返回值类型,只有声明,没有定义
  2. 自定义信号,需要用emit关键字触发,一旦被触发,就会执行与该信号连接的槽函数

112.5 信号与槽的断开连接

  • 断开信号与槽的连接,只需要讲上述的连接函数改成disconnect即可,其函数参数和连接函数一致。
    在这里插入图片描述

112.6 信号与槽总结

  • 一个信号可以连接多个槽函数
  • 一个槽可以连接多个信号
  • 信号和槽函数的参数类型必须保持一致
  • 信号的参数个数要>=槽函数的参数个数
  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
  1. 当信号函数的参数大于槽函数的参数时
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
  1. 当信号函数的参数小于槽函数的参数时
connect(信号发送者, SIGNAL(signalFun(int)),信号接收者, SLOT(slotFun(int, char)));	//False
connect(信号发送者, SIGNAL(signalFun(int)),信号接收者, SLOT(slotFun(int, char=0)));	//Ok

126.7 使用信号与槽实现两个界面的跳转

  1. 创建第二个窗口界面文件
  2. 在第一个窗口的文件中定义一个信号函数
  3. 在新建的窗口的文件中定一个槽函数
  4. 在主函数中将第一个窗口的信号函数和第二个窗口的槽函数连接
  • 创建第二个窗口文件 在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

代码

  • login.h
#ifndef LOGIN_H
#define LOGIN_H
#include <QWidget>QT_BEGIN_NAMESPACE
namespace Ui { class login; }
QT_END_NAMESPACE
class login : public QWidget
{Q_OBJECT
public:login(QWidget *parent = nullptr);~login();
//	第一个界面文件中的信号
signals:void jump_to_second_signal();
//	第一个界面中用于接收点击事件的槽函数
private slots:void on_denglu_clicked();
private:Ui::login *ui;
};
#endif // LOGIN_H
  • second.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 on_pushButton_clicked();void jump();
private:Ui::Second *ui;
};
#endif // SECOND_H
  • login.cpp
#include "login.h"
#include "ui_login.h"login::login(QWidget *parent): QWidget(parent), ui(new Ui::login)
{ui->setupUi(this);
}
login::~login()
{delete ui;
}
//	第一界面接收点击事件后,关闭第一界面,发射跳转信号
void login::on_denglu_clicked()
{this->close();emit jump_to_second_signal();
}
  • 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::on_pushButton_clicked()
{this->close();
}
//	接收第一界面传来的信号,打开当前界面(第二界面)
void Second::jump()
{this->show();
}
  • main.cpp
#include "login.h"
#include "second.h"#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);login w;w.show();//	创建第二界面对象Second s;//	连接第一界面文件中的信号函数和第二界面文件中的槽函数QObject::connect(&w, &login::jump_to_second_signal, &s,&Second::jump);return a.exec();
}

小作业

使用手动连接,将登录框中的取消按钮使用qt4版本的连接到自定义的槽函数中,
在自定义的槽函数中调用关闭函数将登录按钮使用qt5版本的连接到自定义的槽函数中,
在槽函数中判断ui界面上输入的账号是否为"admin",密码是否为"123456",
如果账号密码匹配成功,则输出“登录成功”,并关闭该界面,
如果匹配失败,则输出登录失败,并将密码框中的内容清空

我写的

login.h

#ifndef LOGIN_H
#define LOGIN_H#include <QWidget>
#include <QPushButton>
#include <QDebug>
#include <QString>QT_BEGIN_NAMESPACE
namespace Ui { class Login; }
QT_END_NAMESPACEclass Login : public QWidget
{Q_OBJECTpublic:Login(QWidget *parent = nullptr);~Login();signals:void clicked_cencel_signal();public slots:void close_window_slot();private:Ui::Login *ui;
};
#endif // LOGIN_H

login.cpp

#include "login.h"
#include "ui_login.h"Login::Login(QWidget *parent): QWidget(parent), ui(new Ui::Login)
{ui->setupUi(this);//  上半部分的图画ui->loginLab->setPixmap(QPixmap(":/pictrue/qq_login.gif"));//  设置上半部分图画为自适应大小ui->loginLab->setScaledContents(true);//  设置窗口左上角的企鹅和QQthis->setWindowTitle("QQ");this->setWindowIcon(QIcon(":/pictrue/qie.png"));//  设置输入框前面的企鹅和密码图片ui->unameLab->setPixmap(QPixmap(":/pictrue/qie.png"));ui->passwdLab->setPixmap(QPixmap(":/pictrue/passwd.jpg"));//  设置密码输入形式ui->passwdEdit->setEchoMode(QLineEdit::Password);//  设置头像ui->touxiang->setPixmap(QPixmap(":/pictrue/touxiang.ico"));//  设置右下角的二维码ui->ewm->setPixmap(QPixmap(":/pictrue/eweima.png"));//  用 QT4 的方式连接自定义的槽函数,用于让 取消按钮 去 关闭窗口connect(ui->cencelBtn, SIGNAL(clicked()), this, SLOT(close_window_slot()));//  用 QT5 的方式 让登录按钮 连接自定义的槽函数connect(ui->loginBtn,&QPushButton::clicked,[&](){if(ui->unameEdit->text() == "admin" && ui->passwdEdit->text() == "123456"){qDebug() << "登录成功";close_window_slot();}else{ui->passwdEdit->clear();}});}Login::~Login()
{delete ui;
}void Login::close_window_slot()
{this->close();
}

main.cpp

#include "login.h"#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);Login w;w.show();return a.exec();
}

效果图

在这里插入图片描述

这篇关于嵌入式养成计划-43----QT QMainWindow中常用类的使用--ui界面文件--资源文件的添加--信号与槽的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/297246

相关文章

C++使用栈实现括号匹配的代码详解

《C++使用栈实现括号匹配的代码详解》在编程中,括号匹配是一个常见问题,尤其是在处理数学表达式、编译器解析等任务时,栈是一种非常适合处理此类问题的数据结构,能够精确地管理括号的匹配问题,本文将通过C+... 目录引言问题描述代码讲解代码解析栈的状态表示测试总结引言在编程中,括号匹配是一个常见问题,尤其是在

Java中String字符串使用避坑指南

《Java中String字符串使用避坑指南》Java中的String字符串是我们日常编程中用得最多的类之一,看似简单的String使用,却隐藏着不少“坑”,如果不注意,可能会导致性能问题、意外的错误容... 目录8个避坑点如下:1. 字符串的不可变性:每次修改都创建新对象2. 使用 == 比较字符串,陷阱满

Python使用国内镜像加速pip安装的方法讲解

《Python使用国内镜像加速pip安装的方法讲解》在Python开发中,pip是一个非常重要的工具,用于安装和管理Python的第三方库,然而,在国内使用pip安装依赖时,往往会因为网络问题而导致速... 目录一、pip 工具简介1. 什么是 pip?2. 什么是 -i 参数?二、国内镜像源的选择三、如何

使用C++实现链表元素的反转

《使用C++实现链表元素的反转》反转链表是链表操作中一个经典的问题,也是面试中常见的考题,本文将从思路到实现一步步地讲解如何实现链表的反转,帮助初学者理解这一操作,我们将使用C++代码演示具体实现,同... 目录问题定义思路分析代码实现带头节点的链表代码讲解其他实现方式时间和空间复杂度分析总结问题定义给定

Linux使用nload监控网络流量的方法

《Linux使用nload监控网络流量的方法》Linux中的nload命令是一个用于实时监控网络流量的工具,它提供了传入和传出流量的可视化表示,帮助用户一目了然地了解网络活动,本文给大家介绍了Linu... 目录简介安装示例用法基础用法指定网络接口限制显示特定流量类型指定刷新率设置流量速率的显示单位监控多个

JavaScript中的reduce方法执行过程、使用场景及进阶用法

《JavaScript中的reduce方法执行过程、使用场景及进阶用法》:本文主要介绍JavaScript中的reduce方法执行过程、使用场景及进阶用法的相关资料,reduce是JavaScri... 目录1. 什么是reduce2. reduce语法2.1 语法2.2 参数说明3. reduce执行过程

C#中读取XML文件的四种常用方法

《C#中读取XML文件的四种常用方法》Xml是Internet环境中跨平台的,依赖于内容的技术,是当前处理结构化文档信息的有力工具,下面我们就来看看C#中读取XML文件的方法都有哪些吧... 目录XML简介格式C#读取XML文件方法使用XmlDocument使用XmlTextReader/XmlTextWr

如何使用Java实现请求deepseek

《如何使用Java实现请求deepseek》这篇文章主要为大家详细介绍了如何使用Java实现请求deepseek功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1.deepseek的api创建2.Java实现请求deepseek2.1 pom文件2.2 json转化文件2.2

python使用fastapi实现多语言国际化的操作指南

《python使用fastapi实现多语言国际化的操作指南》本文介绍了使用Python和FastAPI实现多语言国际化的操作指南,包括多语言架构技术栈、翻译管理、前端本地化、语言切换机制以及常见陷阱和... 目录多语言国际化实现指南项目多语言架构技术栈目录结构翻译工作流1. 翻译数据存储2. 翻译生成脚本

C++ Primer 多维数组的使用

《C++Primer多维数组的使用》本文主要介绍了多维数组在C++语言中的定义、初始化、下标引用以及使用范围for语句处理多维数组的方法,具有一定的参考价值,感兴趣的可以了解一下... 目录多维数组多维数组的初始化多维数组的下标引用使用范围for语句处理多维数组指针和多维数组多维数组严格来说,C++语言没