qt-c++多窗口编程

news2024/12/22 18:21:40

1、QMessageBox 消息对话框

QMessageBox继承自QDialog,显示一个模态对话框。用于用户前台信息通知或询问用户问题,并且接收问题答案。

QDialog再Qt源码中,派生类往往都是一些在特定场合下使用的预设好的对话框窗口。这些窗口无需创建对象,直接使用静态成员函数弹窗,使用静态成员函数的返回值作为这个窗口的结果。

QMessageBox类的关键弹窗函数如下:

// 参数1:parent参数
// 参数2:窗口标题
// 参数3:消息内容,窗口展示的信息
// 返回值:用户点击的按钮类型
StandardButton	critical(QWidget * parent, const QString & title, const QString & text)
StandardButton	information(QWidget * parent, const QString & title, const QString & text)
StandardButton	question(QWidget * parent, const QString & title, const QString & text)
StandardButton	warning(QWidget * parent, const QString & title, const QString & text)

dialog.h

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include <QMessageBox>
#include <QButtonGroup>
#include <QDebug>
namespace Ui 
{
class Dialog;
}
class Dialog : public QDialog
{
    Q_OBJECT
public:
    explicit Dialog(QWidget *parent = 0);
    ~Dialog();
private:
    Ui::Dialog *ui;
    QButtonGroup *btp;
private slots:
    void buttonClickedSlot(int);
};
#endif // DIALOG_H

dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"
Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);
    btp = new QButtonGroup(this);//创建按钮组对象
    btp->addButton(ui->pushButtonQ,1);//添加按钮到按钮组
    btp->addButton(ui->pushButtonI,2);
    btp->addButton(ui->pushButtonW,3);
    btp->addButton(ui->pushButtonC,4);
//连接按钮组槽函数
//按钮组信号buttonClicked(int),int是信号id
connect(btp,SIGNAL(buttonClicked(int)),this,SLOT(buttonClickedSlot(int)));
}
Dialog::~Dialog()
{
    delete ui;
    delete btp;
}
//按钮组槽函数
void Dialog::buttonClickedSlot(int id)
{
    if(id == 1)
    {
        // 设置弹窗
        //弹窗返回值用StandardButton 枚举型变量接收
       QMessageBox::StandardButton stdb = QMessageBox::question(this,"question","是否需要关闭?");
   //判断弹窗返回值内容,执行相关命令
       if(stdb == QMessageBox::Yes)
       {
           close();
       }
       else
       {

       }
    }
    else if(id == 2)
    {
        QMessageBox::information(this,"information","已加载完成!");
    }
    else if(id == 3)
    {
        QMessageBox::warning(this,"warning","您的输入有误!");
    }
    else if(id == 4)
    {
        QMessageBox::critical(this,"critical","程序异常,缺少必要文件!");
    }
    else
    {
        qDebug() << "错误处理,没进入对应的模态对话框弹窗" ;
    }
}

2、QWidget类

QWidget类时所有窗口和组件的基类,之前认识此类更多是站在组件的角度,实际上QWidget身为所有窗口的基类,也具有很多窗口的特性,

新建一个项目,使自带窗口继承QWidget:

创建完成后运行时发现,与Dialog的窗口并无太大区别。表面上区别:

QWidget类作为所有窗口的基类,内部也规定了很多窗口的特性。

  • windowTitle : QString

QWidget()set窗口标记

  • windowFlags : Qt::WindowFlags

使用set函数这时多个标记,使用 “|”进行分割。实现无边框、窗口置于最上层。

setWindowFlags(Qt::WindowStaysOnTopHint|Qt::FramelessWindowHint);

void	setWindowFlags(Qt::WindowFlags type)

设置窗口状态

// 参数是窗口的状态
Qt::WindowStates QWidget:: windowState() const

窗口状态:

窗口状态有时可能与窗口标记冲突。

示例代码:

setWindowState(Qt::WindowFullScreen);

3、parent参数

目前对parent参数的理解有以下几点:

  • parent参数表示子组件位于那个窗口给中。
  • parent参数决定了QWidget对象是独立窗口还是内嵌窗口。

实际上parent参数还表示Qt的内存回收机制,如果对象a作为对象b构造函数时的parent参数,表示对象a是对象b的父对象(不是继承关系)。这时一种内存回收的依赖关系,即对象b跟随对象a一并销毁。此时无需手动控制对象b进行销毁过程(手动调用delete)。

如果堆内存对象创建时不传递parent参数,表示对象销毁需要程序员手动销毁(需要手动delete)。

绝大多数情况下,建议堆内存对象传递parent参数。

这样做也有缺点,缺点内存占用,主窗口存在时,子窗口内存不会被释放掉。

dialog.h

#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include <QDebug>
namespace Ui
{
class Dialog;
}
class Dialog : public QDialog
{
    Q_OBJECT
public:
    explicit Dialog(QWidget *parent = 0);
    ~Dialog();
private:
    Ui::Dialog *ui;
private slots:
    void buttonClickedSlot();
    void buttonThisClickedSlot();
};
#endif // DIALOG_H

dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"
Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);
    connect(ui->pushButton,SIGNAL(clicked()),
            this,SLOT(buttonClickedSlot()));
    connect(ui->pushButtonThis,SIGNAL(clicked()),
            this,SLOT(buttonThisClickedSlot()));
}
Dialog::~Dialog()
{
    qDebug() << "析构函数";
    delete ui;
}
//不传递参数,只有最后一个窗口关闭时才会调用析构函数
void Dialog::buttonClickedSlot()
{
    Dialog *dlg = new Dialog;
    dlg->show();
}
//传递参数,创建出来的窗口都是当前窗口的子窗口,父窗口关闭,子窗口都会关闭。
void Dialog::buttonThisClickedSlot()
{
    Dialog *dlg = new Dialog(this);
    dlg->show();
}

不传参的方式:只能一个个关闭,且只析构一次,会存在内存泄漏

传参方式:关闭父窗口,会关闭所有子窗口,且关闭每窗口都会被析构

4、堆栈窗口(QStackedWidget)

通常作为独立窗口的内嵌窗口(组件),与QListWidget进行联动。

dialog.cpp

#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    //手动添加选项(追加)
    ui->listWidget->addItem("第四页");
    ui->listWidget->addItem("第五页");

    // 连接信号槽,点击相应选项,发送相应序号,指定相应页码。
    connect(ui->listWidget,SIGNAL(currentRowChanged(int)),
            ui->stackedWidget,SLOT(setCurrentIndex(int)));
}
Widget::~Widget()
{
    delete ui;
}

5、QMainWindow主窗口类

QMainWindow是最适合作为主窗口的类型,因为包含多个组成部分。

5.1 QMenuBar菜单栏

菜单栏的构建可以通过Designer,也可以通过C++代码实现,不要混用。

代码实现菜单栏构建(不能与Designer混用),

1)向菜单栏中添加一级菜单

// 参数为菜单的文字
// 返回值是添加的菜单对象
QMenu * QMenuBar:: addMenu(const QString & title)

2)向菜单中添加动作

// 参数为动作的文字
// 返回值是添加的动作对象
QAction * QMenu:: addAction(const QString & text)

3)向菜单中添加菜单

// 参数为菜单显示的文字
// 返回值为添加的菜单对象
QMenu * QMenu:: addMenu(const QString & title)

例子:

qMainWindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    QMenu * menuFile = ui->menuBar->addMenu("文件");
    QMenu * menuEdit = ui->menuBar->addMenu("编辑");
    QMenu * menuHelp = ui->menuBar->addMenu("帮助");
    // 向一级菜单中添加动作
    QAction * actionNew = menuFile->addAction("新建");
    QAction * actionOpen = menuFile->addAction("打开");
    QAction * actionClose = menuFile->addAction("关闭");
    // 向一级菜单中添加二级菜单
    QMenu * menuRecent = menuFile->addMenu("最近访问的文件");
    // 向二级菜单中添加动作
    QAction * actionCpp = menuRecent->addAction("hello.cpp");
    QAction * actionH = menuRecent->addAction("hello.h");
}
MainWindow::~MainWindow()
{
    delete ui;
}

菜单信号

为了使QAction点击后有触发效果,需要使用对应的信号连接槽函数。信号函数如下:

//将带有文本的新段落追加到文本编辑的末尾。
void QTextEdit::​append(const QString & text)

示例:

QMainWindow.h

QMainWindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    //连接槽函数
    connect(ui->actionNew,SIGNAL(triggered()),
            this,SLOT(actionNewTriggeredSlot()));
    connect(ui->actionHello_cpp,SIGNAL(triggered()),
            this,SLOT(actionCppTriggeredSlot()));
}
MainWindow::~MainWindow()
{
    delete ui;
}
void MainWindow::actionNewTriggeredSlot()
{

    ui->textBrowser->append("新创建了一个文件");
}
void MainWindow::actionCppTriggeredSlot()
{
    ui->textBrowser->append("打开了hello.cpp");
}

5.2 QToolBar 工具栏

工具栏按钮往往使用菜单栏中QAciton对象。但是需要给他设置图标。

// 添加一个已有的QAction(通常是设置图标)对象到工具栏
void QToolBar:: addAction(QAction * action)

5.3 QStatusBar 状态栏

可以使用槽函数进行信息展示:

// 在状态栏展示信息
// 参数1:展示的信息内容
// 参数2:信息展示的时间(单位毫秒),默认值0表示持续显示
void QStatusBar:: showMessage(const QString & message, int timeout = 0)[slot]

// 清空显示
void QStatusBar:: clearMessage()

显示5秒自动消失

通过QLabel控件,添加状态栏信息

状态栏显示拉伸比(拉伸因子):默认为0,按最小显示不拉伸

6、新建自定义窗口类

在一个项目中新创建一个Qt的窗口界面类,操作步骤如下:

  1. 在Qt Creator中选中项目名称,鼠标右键,点击“添加新文件”。
  2. 在弹出的窗口中,按照下图进行操作:

  1. 在弹出的窗口中选择界面模板后,点击“下一步”。

  1. 在弹出的窗口中,输入类名(注意帕斯卡/大驼峰),然后点击“下一步”。

  1. 在项目管理界面点击完成,可以看到新的窗口类文件已经创建完成,并添加到项目中了。

dialog.cpp

7、对象传值

7.1 父对象->子对象

此处指的是Qt的parent参数的依赖关系,并非继承关系。

【需求】,转动主窗口中的球,子窗口的球跟着转。

这种情况下最佳的解决方案1、信号槽传参 2、C++的成员函数传参。

7.2 子对象→父对象

【需求】:转动子窗口中的球,父窗口中的球跟着转。

这种情况最佳的解决方案是信号槽传参。子对象发射带参数的信号函数,父对象使用带参数的槽函数接收。

dialog.cpp

mydialog

8、事件机制

事件是Qt的一种底层机制,经过层层传递,程序员可以在 传递的层级中检测或者处理这些事件。

本次学习主要是在窗口类中实现事件函数,检测到事件的传递,从而利用事件的触发机制,实现一些特定的效果。事件函数众多。包括但不限于。

以下所示:

// 绘制事件
void QWidget::paintEvent(QPaintEvent * event) [virtual protected] 

// 大小改变事件
void QWidget::resizeEvent(QResizeEvent * event) [virtual protected] 

// 鼠标按压事件
void QWidget::mousePressEvent(QMouseEvent * event) [virtual protected]
// 鼠标释放事件
void QWidget::mouseReleaseEvent(QMouseEvent * event) [virtual protected]
// 鼠标双击事件
void QWidget::mouseDoubleClickEvent(QMouseEvent * event) [virtual protected]
// 鼠标移动事件
void QWidget::mouseMoveEvent(QMouseEvent * event) [virtual protected]

// 移动事件
void QWidget::moveEvent(QMoveEvent * event) [virtual protected]

// 按键按压事件
void QWidget::keyPressEvent(QKeyEvent * event) [virtual protected]
// 按键释放事件
void QWidget::keyReleaseEvent(QKeyEvent * event) [virtual protected]

// 获取焦点事件
void QWidget::focusInEvent(QFocusEvent * event) [virtual protected]
// 失去焦点事件
void QWidget::focusOutEvent(QFocusEvent * event) [virtual protected]

// 关闭事件
void QWidget::closeEvent(QCloseEvent * event) [virtual protected]

// 鼠标进入事件
void QWidget::enterEvent(QEvent * event) [virtual protected]
// 鼠标离开事件
void QWidget::leaveEvent(QEvent * event) [virtual protected]

事件函数的基础使用只需要在对应的类中覆盖基类的事件函数即可。事件函数的参数就是包含了当前事件数据的对象。

// 绘制图片
// 参数1:横轴坐标
// 参数2:纵轴坐标
// 参数3:绘制宽度
// 参数4:绘制高度
// 参数5:绘制内容
void QPainter:: drawPixmap(int x, int y, int width, int height, const QPixmap & pixmap)

【需求】:按下键盘A、S、D、W控制进度条加或者减

void Dialog::keyPressEvent(QKeyEvent *event)
{
    if(event->key() == Qt::Key_A)
    {
        int value = ui->progressBar->value();
        ui->progressBar->setValue(--value);
    }
    else if(event->key() == Qt::Key_D)
    {
        int value = ui->progressBar->value();
        ui->progressBar->setValue(++value);
    }
    else if(event->key() == Qt::Key_W)
    {
        ui->progressBar->setValue(100);
    }
    else if(event->key() == Qt::Key_S)
    {
        ui->progressBar->setValue(0);
    }
    else
    {

    }

事件函数的基础使用只需要在对应的类中覆盖基类的事件函数即可。事件函数的参数就是包含了当前事件数据的对象。

【问题】事件函数与信号槽的区别?

  • 事件由具体对象进行处理
  • 信号由具体对象主动产生
  • 改写事件处理函数可能导致程序行为发生改变
  • 信号是否存在对应的槽函数不会改变程序行为

6-多窗口编程

  1. QMessageBox 消息对话框

QMessageBox继承自QDialog,显示一个模态对话框。用于用户前台信息通知或询问用户问题,并且接收问题答案。

QDialog再Qt源码中,派生类往往都是一些在特定场合下使用的预设好的对话框窗口。这些窗口无需创建对象,直接使用静态成员函数弹窗,使用静态成员函数的返回值作为这个窗口的结果。

QMessageBox类的关键弹窗函数如下:

// 参数1:parent参数
// 参数2:窗口标题
// 参数3:消息内容,窗口展示的信息
// 返回值:用户点击的按钮类型
StandardButton	critical(QWidget * parent, const QString & title, const QString & text)
StandardButton	information(QWidget * parent, const QString & title, const QString & text)
StandardButton	question(QWidget * parent, const QString & title, const QString & text)
StandardButton	warning(QWidget * parent, const QString & title, const QString & text)

dialog.h

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include <QMessageBox>
#include <QButtonGroup>
#include <QDebug>
namespace Ui 
{
class Dialog;
}
class Dialog : public QDialog
{
    Q_OBJECT
public:
    explicit Dialog(QWidget *parent = 0);
    ~Dialog();
private:
    Ui::Dialog *ui;
    QButtonGroup *btp;
private slots:
    void buttonClickedSlot(int);
};
#endif // DIALOG_H

dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"
Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);
    btp = new QButtonGroup(this);//创建按钮组对象
    btp->addButton(ui->pushButtonQ,1);//添加按钮到按钮组
    btp->addButton(ui->pushButtonI,2);
    btp->addButton(ui->pushButtonW,3);
    btp->addButton(ui->pushButtonC,4);
//连接按钮组槽函数
//按钮组信号buttonClicked(int),int是信号id
connect(btp,SIGNAL(buttonClicked(int)),this,SLOT(buttonClickedSlot(int)));
}
Dialog::~Dialog()
{
    delete ui;
    delete btp;
}
//按钮组槽函数
void Dialog::buttonClickedSlot(int id)
{
    if(id == 1)
    {
        // 设置弹窗
        //弹窗返回值用StandardButton 枚举型变量接收
       QMessageBox::StandardButton stdb = QMessageBox::question(this,"question","是否需要关闭?");
   //判断弹窗返回值内容,执行相关命令
       if(stdb == QMessageBox::Yes)
       {
           close();
       }
       else
       {

       }
    }
    else if(id == 2)
    {
        QMessageBox::information(this,"information","已加载完成!");
    }
    else if(id == 3)
    {
        QMessageBox::warning(this,"warning","您的输入有误!");
    }
    else if(id == 4)
    {
        QMessageBox::critical(this,"critical","程序异常,缺少必要文件!");
    }
    else
    {
        qDebug() << "错误处理,没进入对应的模态对话框弹窗" ;
    }
}

2、QWidget类

QWidget类时所有窗口和组件的基类,之前认识此类更多是站在组件的角度,实际上QWidget身为所有窗口的基类,也具有很多窗口的特性,

新建一个项目,使自带窗口继承QWidget:

创建完成后运行时发现,与Dialog的窗口并无太大区别。表面上区别:

QWidget类作为所有窗口的基类,内部也规定了很多窗口的特性。

  • windowTitle : QString

QWidget()set窗口标记

  • windowFlags : Qt::WindowFlags

使用set函数这时多个标记,使用 “|”进行分割。实现无边框、窗口置于最上层。

setWindowFlags(Qt::WindowStaysOnTopHint|Qt::FramelessWindowHint);

void	setWindowFlags(Qt::WindowFlags type)

设置窗口状态

// 参数是窗口的状态
Qt::WindowStates QWidget:: windowState() const

窗口状态:

窗口状态有时可能与窗口标记冲突。

示例代码:

setWindowState(Qt::WindowFullScreen);

3、parent参数

目前对parent参数的理解有以下几点:

  • parent参数表示子组件位于那个窗口给中。
  • parent参数决定了QWidget对象是独立窗口还是内嵌窗口。

实际上parent参数还表示Qt的内存回收机制,如果对象a作为对象b构造函数时的parent参数,表示对象a是对象b的父对象(不是继承关系)。这时一种内存回收的依赖关系,即对象b跟随对象a一并销毁。此时无需手动控制对象b进行销毁过程(手动调用delete)。

如果堆内存对象创建时不传递parent参数,表示对象销毁需要程序员手动销毁(需要手动delete)。

绝大多数情况下,建议堆内存对象传递parent参数。

这样做也有缺点,缺点内存占用,主窗口存在时,子窗口内存不会被释放掉。

dialog.h

#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include <QDebug>
namespace Ui
{
class Dialog;
}
class Dialog : public QDialog
{
    Q_OBJECT
public:
    explicit Dialog(QWidget *parent = 0);
    ~Dialog();
private:
    Ui::Dialog *ui;
private slots:
    void buttonClickedSlot();
    void buttonThisClickedSlot();
};
#endif // DIALOG_H

dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"
Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);
    connect(ui->pushButton,SIGNAL(clicked()),
            this,SLOT(buttonClickedSlot()));
    connect(ui->pushButtonThis,SIGNAL(clicked()),
            this,SLOT(buttonThisClickedSlot()));
}
Dialog::~Dialog()
{
    qDebug() << "析构函数";
    delete ui;
}
//不传递参数,只有最后一个窗口关闭时才会调用析构函数
void Dialog::buttonClickedSlot()
{
    Dialog *dlg = new Dialog;
    dlg->show();
}
//传递参数,创建出来的窗口都是当前窗口的子窗口,父窗口关闭,子窗口都会关闭。
void Dialog::buttonThisClickedSlot()
{
    Dialog *dlg = new Dialog(this);
    dlg->show();
}

不传参的方式:只能一个个关闭,且只析构一次,会存在内存泄漏

传参方式:关闭父窗口,会关闭所有子窗口,且关闭每窗口都会被析构

4、堆栈窗口(QStackedWidget)

通常作为独立窗口的内嵌窗口(组件),与QListWidget进行联动。

dialog.cpp

#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    //手动添加选项(追加)
    ui->listWidget->addItem("第四页");
    ui->listWidget->addItem("第五页");

    // 连接信号槽,点击相应选项,发送相应序号,指定相应页码。
    connect(ui->listWidget,SIGNAL(currentRowChanged(int)),
            ui->stackedWidget,SLOT(setCurrentIndex(int)));
}
Widget::~Widget()
{
    delete ui;
}

5、QMainWindow主窗口类

QMainWindow是最适合作为主窗口的类型,因为包含多个组成部分。

5.1 QMenuBar菜单栏

菜单栏的构建可以通过Designer,也可以通过C++代码实现,不要混用。

代码实现菜单栏构建(不能与Designer混用),

1)向菜单栏中添加一级菜单

// 参数为菜单的文字
// 返回值是添加的菜单对象
QMenu * QMenuBar:: addMenu(const QString & title)

2)向菜单中添加动作

// 参数为动作的文字
// 返回值是添加的动作对象
QAction * QMenu:: addAction(const QString & text)

3)向菜单中添加菜单

// 参数为菜单显示的文字
// 返回值为添加的菜单对象
QMenu * QMenu:: addMenu(const QString & title)

例子:

qMainWindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    QMenu * menuFile = ui->menuBar->addMenu("文件");
    QMenu * menuEdit = ui->menuBar->addMenu("编辑");
    QMenu * menuHelp = ui->menuBar->addMenu("帮助");
    // 向一级菜单中添加动作
    QAction * actionNew = menuFile->addAction("新建");
    QAction * actionOpen = menuFile->addAction("打开");
    QAction * actionClose = menuFile->addAction("关闭");
    // 向一级菜单中添加二级菜单
    QMenu * menuRecent = menuFile->addMenu("最近访问的文件");
    // 向二级菜单中添加动作
    QAction * actionCpp = menuRecent->addAction("hello.cpp");
    QAction * actionH = menuRecent->addAction("hello.h");
}
MainWindow::~MainWindow()
{
    delete ui;
}

菜单信号

为了使QAction点击后有触发效果,需要使用对应的信号连接槽函数。信号函数如下:

//将带有文本的新段落追加到文本编辑的末尾。
void QTextEdit::​append(const QString & text)

示例:

QMainWindow.h

QMainWindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    //连接槽函数
    connect(ui->actionNew,SIGNAL(triggered()),
            this,SLOT(actionNewTriggeredSlot()));
    connect(ui->actionHello_cpp,SIGNAL(triggered()),
            this,SLOT(actionCppTriggeredSlot()));
}
MainWindow::~MainWindow()
{
    delete ui;
}
void MainWindow::actionNewTriggeredSlot()
{

    ui->textBrowser->append("新创建了一个文件");
}
void MainWindow::actionCppTriggeredSlot()
{
    ui->textBrowser->append("打开了hello.cpp");
}

5.2 QToolBar 工具栏

工具栏按钮往往使用菜单栏中QAciton对象。但是需要给他设置图标。

// 添加一个已有的QAction(通常是设置图标)对象到工具栏
void QToolBar:: addAction(QAction * action)

5.3 QStatusBar 状态栏

可以使用槽函数进行信息展示:

// 在状态栏展示信息
// 参数1:展示的信息内容
// 参数2:信息展示的时间(单位毫秒),默认值0表示持续显示
void QStatusBar:: showMessage(const QString & message, int timeout = 0)[slot]

// 清空显示
void QStatusBar:: clearMessage()

显示5秒自动消失

通过QLabel控件,添加状态栏信息

状态栏显示拉伸比(拉伸因子):默认为0,按最小显示不拉伸

6、新建自定义窗口类

在一个项目中新创建一个Qt的窗口界面类,操作步骤如下:

  1. 在Qt Creator中选中项目名称,鼠标右键,点击“添加新文件”。
  2. 在弹出的窗口中,按照下图进行操作:

  1. 在弹出的窗口中选择界面模板后,点击“下一步”。

  1. 在弹出的窗口中,输入类名(注意帕斯卡/大驼峰),然后点击“下一步”。

  1. 在项目管理界面点击完成,可以看到新的窗口类文件已经创建完成,并添加到项目中了。

dialog.cpp

7、对象传值

7.1 父对象->子对象

此处指的是Qt的parent参数的依赖关系,并非继承关系。

【需求】,转动主窗口中的球,子窗口的球跟着转。

这种情况下最佳的解决方案1、信号槽传参 2、C++的成员函数传参。

7.2 子对象→父对象

【需求】:转动子窗口中的球,父窗口中的球跟着转。

这种情况最佳的解决方案是信号槽传参。子对象发射带参数的信号函数,父对象使用带参数的槽函数接收。

dialog.cpp

mydialog

8、事件机制

事件是Qt的一种底层机制,经过层层传递,程序员可以在 传递的层级中检测或者处理这些事件。

本次学习主要是在窗口类中实现事件函数,检测到事件的传递,从而利用事件的触发机制,实现一些特定的效果。事件函数众多。包括但不限于。

以下所示:

// 绘制事件
void QWidget::paintEvent(QPaintEvent * event) [virtual protected] 

// 大小改变事件
void QWidget::resizeEvent(QResizeEvent * event) [virtual protected] 

// 鼠标按压事件
void QWidget::mousePressEvent(QMouseEvent * event) [virtual protected]
// 鼠标释放事件
void QWidget::mouseReleaseEvent(QMouseEvent * event) [virtual protected]
// 鼠标双击事件
void QWidget::mouseDoubleClickEvent(QMouseEvent * event) [virtual protected]
// 鼠标移动事件
void QWidget::mouseMoveEvent(QMouseEvent * event) [virtual protected]

// 移动事件
void QWidget::moveEvent(QMoveEvent * event) [virtual protected]

// 按键按压事件
void QWidget::keyPressEvent(QKeyEvent * event) [virtual protected]
// 按键释放事件
void QWidget::keyReleaseEvent(QKeyEvent * event) [virtual protected]

// 获取焦点事件
void QWidget::focusInEvent(QFocusEvent * event) [virtual protected]
// 失去焦点事件
void QWidget::focusOutEvent(QFocusEvent * event) [virtual protected]

// 关闭事件
void QWidget::closeEvent(QCloseEvent * event) [virtual protected]

// 鼠标进入事件
void QWidget::enterEvent(QEvent * event) [virtual protected]
// 鼠标离开事件
void QWidget::leaveEvent(QEvent * event) [virtual protected]

事件函数的基础使用只需要在对应的类中覆盖基类的事件函数即可。事件函数的参数就是包含了当前事件数据的对象。

// 绘制图片
// 参数1:横轴坐标
// 参数2:纵轴坐标
// 参数3:绘制宽度
// 参数4:绘制高度
// 参数5:绘制内容
void QPainter:: drawPixmap(int x, int y, int width, int height, const QPixmap & pixmap)

【需求】:按下键盘A、S、D、W控制进度条加或者减

void Dialog::keyPressEvent(QKeyEvent *event)
{
    if(event->key() == Qt::Key_A)
    {
        int value = ui->progressBar->value();
        ui->progressBar->setValue(--value);
    }
    else if(event->key() == Qt::Key_D)
    {
        int value = ui->progressBar->value();
        ui->progressBar->setValue(++value);
    }
    else if(event->key() == Qt::Key_W)
    {
        ui->progressBar->setValue(100);
    }
    else if(event->key() == Qt::Key_S)
    {
        ui->progressBar->setValue(0);
    }
    else
    {

    }

事件函数的基础使用只需要在对应的类中覆盖基类的事件函数即可。事件函数的参数就是包含了当前事件数据的对象。

【问题】事件函数与信号槽的区别?

  • 事件由具体对象进行处理
  • 信号由具体对象主动产生
  • 改写事件处理函数可能导致程序行为发生改变
  • 信号是否存在对应的槽函数不会改变程序行为

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1403542.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PaddleDetection学习3——使用Paddle-Lite在 Android 上部署PicoDet模型(fp16)

使用Paddle-Lite在 Android 上运行PicoDet模型&#xff08;fp16&#xff09; 1. 环境准备2. 部署步骤2.1 下载Paddle-Lite-Demo2.2 打开 picodet_detection_demo项目2.2.1 修改build.gradle&#xff0c;配置国内镜像仓库2.2.2 NDK 配置错误问题2.2.3 gradle.properties文件配置…

PaddleOCR实现对表格的提取

1、背景 PaddleOCR: 基于飞桨的OCR工具库&#xff0c;包含总模型仅8.6M的超轻量级中文OCR&#xff0c;单模型支持中英文数字组合识别、竖排文本识别、长文本识别。同时支持多种文本检测、文本识别的训练算法。对pdf/word里的表格中识别出有效信息具有重要意义&#xff0c;比如…

OpenSource - 文件在线预览模块(多格式转 PDF 文件)

文章目录 文件在线预览模块&#xff08;多格式转PDF文件&#xff09;现已支持格式如下界面展示运行方式接口介绍文件上传文件转 PDF文件转图片文件转SVG 参数配置其他说明项目关联关键词文档转换预览技术说明同步转换异步转换 主要技术乱码问题处理帮助文档 前端预览弹出层用法…

uniapp开发小程序如何获取用户地理位置

1、需求说明 需求&#xff1a;点击按钮获取当前微信位置&#xff0c;以及点击拒绝授权后&#xff0c;下次点击还可以拉起授权窗口&#xff1b; 2、言归正传 1、编写代码 模板部分 <template><view><button type"" click"getLocation"&…

hugo的常规使用操作

hugo的常规使用操作&#xff08;不断完善中&#xff09; 找到theme主题中config.toml 一般都会通过theme中复制到自己项目的config.toml中做修改和补充&#xff0c;来完善不同的业务需求 Hugo静态资源载入逻辑 原理 将图片信息放到static中&#xff0c;但是在文章中写的时…

入门教程:使用 Postman 发送 post 请求

Postman 是一个实用的开发工具&#xff0c;它让发送各类 POST 请求成为了可能&#xff0c;包括文本、JSON、XML 以及文件等。开发者利用此工具不仅能够检验API的功能性&#xff0c;还能仿真客户端的请求行为&#xff0c;进而深入了解客户端如何与 API 进行互动。 HTTP 协议中的…

v38.条件结构

1.if-else 2.嵌套if结构 第二个if是嵌套在第一个if里面的&#xff0c;不能独立实现程序。存在依赖关系。 3.else if 不存在依赖关系。 4. printf函数是属于if/else 语句的&#xff0c;加不加大括号&#xff5b;&#xff5d;效果是一样的 5. 也就是说if的管辖范围只能是条件后…

服务器感染了.wis[[Rast@airmail.cc]].wis勒索病毒,如何确保数据文件完整恢复?

导言&#xff1a; 在当今数字化的时代&#xff0c;恶意软件攻击已经变得越来越复杂和狡猾&#xff0c;[[MyFilewaifu.club]].wis [[backupwaifu.club]].wis[[Rastairmail.cc]].wis勒索病毒是其中的一种新威胁。本文91数据恢复将深入介绍[[MyFilewaifu.club]].wis [[backupwaif…

大数据开发之Spark(入门)

第 1 章&#xff1a;Spark概述 1.1 什么是spark 回顾&#xff1a;hadoop主要解决&#xff0c;海量数据的存储和海量数据的分析计算。 spark是一种基于内存的快速、通用、可扩展的大数据分析计算引擎。 1.2 hadoop与spark历史 hadoop的yarn框架比spark框架诞生的晚&#xff…

常见的嵌入式面试问题解答!

1.关键字static的作用是什么&#xff1f;为什么static变量只初始化一次&#xff1f; ​1&#xff09;修饰局部变量&#xff1a;使得变量变成静态变量&#xff0c;存储在静态区&#xff0c;存储在静态区的数据周期和程序相同&#xff0c; 在main函数开始前初始化&#xff0c;在…

【论文代码】基于隐蔽带宽的汽车控制网路鲁棒认证-到达时间间隔通道的Java实现(一)

文章目录 一、USBtin 基类1.1 CANSender 类1.1.1 SimpleSender类 1.2 CANReceiver类1.2.1 SimpleReceiver类 1.3 Noise_node类 二、CANMessageListener 接口2.1 IAT_Monitor2.2 BasicListener2.3 DLC_Monitor 三、IATBitConverter 抽象类3.1 OneBitConverter类3.2 TwoBitConver…

swagger-ui配置错误原因

第一个问题 就是出现了error white page&#xff0c;主要是因为运行类的pom文件里没有添加到common类的地址dependency&#xff0c;导致出现问题&#xff0c;还到处排查 第二个问题 进去就跳出登录页面&#xff0c;可是我没有账户名和密码啊 在弄pom文件的时候不知道什么时候…

【idea】解决IDEA:The file size exceeds configured limit (5.12MB).

报错原因 The file size (5.13MB) exceeds configured limit (5.12MB). Code insight features are not available.(文件大小超出了设定值&#xff0c;IDEA不再对这个文件的进行代码解析了) 与之而来的结果是&#xff1a;IDEA中其他文件对于这个文件的所有引用都会报错&#x…

洛谷 P1126 机器人搬重物

题目描述 机器人移动学会&#xff08;RMI&#xff09;现在正尝试用机器人搬运物品。机器人的形状是一个直径 1.6 米的球。在试验阶段&#xff0c;机器人被用于在一个储藏室中搬运货物。储藏室是一个 NM 的网格&#xff0c;有些格子为不可移动的障碍。机器人的中心总是在格点上…

云原生DevOps基础与实战

一、DevOps基础 1、DevOps简介 DevOps 是一系列做法和工具&#xff0c;可以使 IT 和软件开发团队之间的流程实现自动化。其中&#xff0c;随着敏捷软件开发日趋流行&#xff0c;持续集成 (CI) 和持续交付 (CD) 已经成为该领域一个理想的解决方案。在 CI/CD 工作流中&#xff…

ARM 驱动 1.22

linux内核等待队列wait_queue_head_t 头文件 include <linux/wait.h> 定义并初始化 wait_queue_head_t r_wait; init_waitqueue_head(&cm_dev->r_wait); wait_queue_head_t 表示等待队列头&#xff0c;等待队列wait时&#xff0c;会导致进程或线程被休眠&…

最新版的Tuxera NTFS 2024 支持macOS 12系统

备受期待的Tuxera NTFS 2024 Mac中文版终于上线了&#xff0c;小编第一时间为您带来&#xff01;Tuxera NTFS 2024 中文版是一款非常好用的NTFS读写工具&#xff0c;可以让您完整的读写兼容NTFS格式驱动器&#xff0c;对磁盘进行访问、编辑、存储和传输文件等。同时还包括开源磁…

电脑存储位置不够怎么办

电脑内存不够怎么办&#xff01;&#xff01;&#xff01; 我前段时间经常因为电脑D盘内存不够而苦恼&#xff08;毕竟电脑内存就那么丁点&#xff0c;C盘作为系统盘不能随便下东西的情况下&#xff0c;就只能选择其他盘进 方法一&#xff1a;检查电脑硬盘的分区情况&#xf…

git内部原理

git内部原理 介绍目录结构说明 介绍 项目的本地仓库中&#xff0c;包含一个隐藏的.git目录&#xff0c;其不同的文件产生都源于git的各种不同命令造成&#xff0c;文件目录如下所示&#xff1a; 目录结构说明 上面最核心重要的为object目录&#xff0c;目录最主要有三个对象…

设置代码模板创建sql映射文件、Mybatis主配置文件

目录 1、Sql映射&#xff08;Sql Mapper&#xff09;文件的介绍 2、Mybatis的主配置文件的介绍 3、通过代码模板创建Sql映射文件 4、通过代码模板创建Mybatis主配置文件 1、Sql映射&#xff08;Sql Mapper&#xff09;文件的介绍 <?xml version"1.0" encod…