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

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

109.1 菜单栏 QMenuBar

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

109.2 工具栏 QToolBar

  • 工具栏 QToolBar 可以有多个

109.3 状态栏QStatusBar

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

109.4 浮动窗口QDockWidget

  • 浮动窗口 可以有多个

109.5 代码示例

  • main.cpp
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
cpp 复制代码
#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_OBJECT

public:
    my_MainWindow(QWidget *parent = nullptr);
    ~my_MainWindow();
};
#endif // MY_MAINWINDOW_H
  • my_mainwindow.cpp
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 包含信号函数和槽函数的类体定义

cpp 复制代码
#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 my_signal();  //自定义一个信号函数
    
public slots:  //表示该权限下是公共的槽函数
    void my_slot();  //自定义一个槽函数
    
private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

112.2 信号和槽的连接方式

  • 基于ui界面上的连接,在ui界面下面的信号与槽区,进行信号与槽的连接,该连接只适用于系统提供的信号和槽

    不需要手动书写信号函数,槽函数,连接函数。

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

    cpp 复制代码
    //按钮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版本,该连接是不友好的连接

    cpp 复制代码
    [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版本,该连接是友好的连接

    cpp 复制代码
    [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表达式

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

    1.全局函数举个例子:

    cpp 复制代码
    void someFunction();
    QPushButton *button = new QPushButton;
    QObject::connect(button, &QPushButton::clicked, someFunction);

    2.lambda表达式

    cpp 复制代码
    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

    头文件

    cpp 复制代码
    #ifndef WIDGET_H
    #define WIDGET_H
    
    #include <QWidget>
    #include<QPushButton>
    #include<QTextToSpeech> //语音播报类
    
    QT_BEGIN_NAMESPACE
    namespace Ui { class Widget; }
    QT_END_NAMESPACE
    
    class 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

    源文件

    cpp 复制代码
    #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即可,其函数参数和连接函数一致。

小作业

使用手动连接,将登录框中的取消按钮使用qt4版本的连接到自定义的槽函数中,
在自定义的槽函数中调用关闭函数

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

我写的

login.h

cpp 复制代码
#ifndef LOGIN_H
#define LOGIN_H

#include <QWidget>
#include <QPushButton>
#include <QDebug>
#include <QString>

QT_BEGIN_NAMESPACE
namespace Ui { class Login; }
QT_END_NAMESPACE

class Login : public QWidget
{
    Q_OBJECT

public:
    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

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

    //  设置窗口左上角的企鹅和QQ
    this->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

cpp 复制代码
#include "login.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Login w;
    w.show();
    return a.exec();
}

效果图

相关推荐
I_Am_Me_8 分钟前
【JavaEE进阶】 JavaScript
开发语言·javascript·ecmascript
暮色_年华9 分钟前
Modern Effective C++item 9:优先考虑别名声明而非typedef
c++
重生之我是数学王子18 分钟前
QT基础 编码问题 定时器 事件 绘图事件 keyPressEvent QT5.12.3环境 C++实现
开发语言·c++·qt
Ai 编码助手19 分钟前
使用php和Xunsearch提升音乐网站的歌曲搜索效果
开发语言·php
学习前端的小z23 分钟前
【前端】深入理解 JavaScript 逻辑运算符的优先级与短路求值机制
开发语言·前端·javascript
神仙别闹31 分钟前
基于C#和Sql Server 2008实现的(WinForm)订单生成系统
开发语言·c#
XINGTECODE32 分钟前
海盗王集成网关和商城服务端功能golang版
开发语言·后端·golang
我们的五年41 分钟前
【Linux课程学习】:进程程序替换,execl,execv,execlp,execvp,execve,execle,execvpe函数
linux·c++·学习
zwjapple1 小时前
typescript里面正则的使用
开发语言·javascript·正则表达式
小五Five1 小时前
TypeScript项目中Axios的封装
开发语言·前端·javascript