Qt第六章 多窗口编程

2023-11-12

一、QMessageBox 消息对话框(掌握)

QMessageBox继承自QDialog,是一个Qt内置的用来展示信息或询问用户一个问题的模态对话框。

预设了四种类型:

像那些已经写好的窗口,这些现成的东西都会有一些特性,就是他们的对象都不需要new或者说他们就不需要拿到对象,他们为了方便我们使用会用一个静态成员函数就可以把弹窗显示出来。上面的四种类型想要显示就需要用对应的静态成员函数

四种弹窗的参数和返回值基本一致:

参数1:父窗口

参数2:标题文字

参数3:展示信息内容

返回值:用户点击的按钮,默认情况下只有question类型的弹窗有必要接收返回值

只要是预设的对话框他们想要拿数据他一定是通过返回值拿数据 静态成员函数的返回值

不是Q开头的大概路是枚举

我们这个对话框只有只有yes和no所以只有要判断返回值是yes还是no可以判断用户点击的是什么

示例代码下载链接:百度网盘 请输入提取码

提取码:hqyj

--来自百度网盘超级会员V6的分享

dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"

Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);

    group = new QButtonGroup(this);
    group->addButton(ui->btnInfomation,1);
    group->addButton(ui->btnWarning,2);
    group->addButton(ui->btnCritical,3);
    group->addButton(ui->btnQuestion,4);
    group->addButton(ui->btnCustom,5);

    connect(group,SIGNAL(buttonClicked(int)),
            this,SLOT(btnsClickedSlot(int)));
}

Dialog::~Dialog()
{
    delete group;
    delete ui;
}

void Dialog::custom()
{
    // 创建自定义的QMessageBox对象
    QMessageBox* box = new QMessageBox(this);
    // 设置标题
    box->setWindowTitle("自定义QMessageBox");
    // 准备一个图片对象
    QPixmap pic(":/new/prefix1/new_year.png");
    // 设置图标
    box->setIconPixmap(pic);
    // 设置消息内容
    box->setText("2023年即将到来,你感到快乐吗?");
    // 创建两个按钮对象
    QPushButton* btn1 = new QPushButton("快乐",box);
    QPushButton* btn2 = new QPushButton("不快乐",box);
    // 添加按钮到弹窗的正确位置
    box->addButton(btn1,QMessageBox::YesRole);
    box->addButton(btn2,QMessageBox::NoRole);
    // 展示弹窗
    box->show();
}

void Dialog::btnsClickedSlot(int id)
{
    if(id == 1)
        QMessageBox::information(this,"information","网络已连接!");
    else if(id == 2)
        QMessageBox::warning(this,"warning","网络波动!");
    else if(id == 3)
        QMessageBox::critical(this,"critical","无法检测到网络!");
    else if(id == 4)
    {
        QMessageBox::StandardButton result = QMessageBox::question(this,"question","您是否没插网线?");
        if(result == QMessageBox::Yes)
            qDebug() << "我是无线我插什么网线?";
        else if(result == QMessageBox::No)
            qDebug() << "有线性能一定比无线好。";
    }
    else if(id == 5)
        custom();
}

二、常见的窗口类(掌握)

本次Qt学习到的窗口类之间的继承关系如下图所示。

  • QObject

        所有Qt类的基类,本身并不是窗口类。

  • QWidget

        如果创建时制定parent参数的值,此时QWidget对象会作为制定参数对应的窗口内部的组件;如果创建时不传入parent参数的值,此时QWidget对象会作为一个独立的窗口。

  • QMainWindow

        通常使用此类作为应用程序的主窗口,主窗口包含菜单栏、工具栏、中心组件与状态栏。因为使用相对复杂,所以一直讲课未用。

  • QDialog

        通常作为子窗口存在的对话框窗口,特点是组成简单。比较简单的程序可以使用此类型作为主窗口。

  • QMessageBox

        QDialog的一个派生类,主要用于消息展示和提问。

  • QFileDialog

        QDialog一个派生类,主要用于浏览本地磁盘的文件并选择。

所有的窗口类共有一些属性和函数,例如:

  • windowTitle : QString

所有窗口的标题,可以通过getter和setter进行读写。

void QWidget::setWindowState(Qt::WindowStates windowState)

设置窗口状态,参数值如下:

  • windowFlags : Qt::WindowFlags

窗口标记,支持同时通过setter设定多个标记,多个标记之间使用|分割

常用的标记有:

dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"

Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);
    // 设置窗口
    setWindowTitle("哈哈哈哈哈哈哈哈");
    // 设置窗口状态(全屏)
//    setWindowState(Qt::WindowFullScreen);
    // 设置窗口标记     关闭缺省的标题窗口栏      创建无边框窗口
    setWindowFlags(Qt::WindowStaysOnTopHint|Qt::FramelessWindowHint);
}

Dialog::~Dialog()
{
    delete ui;
}

 

三、QMainWindow 主窗口

QMainWindow非常适合作为程序的主窗口因为程序的各种功能可以设置到菜单栏和工具栏中,同时状态栏可以显示当前软件的信息。

QMainWindow主要由四部分组成:

这四个部分的初始化设置可以通过Designer完成,也可以在C++代码中完成

QMenuBar中的每个菜单对应类型是QMenuQMenu中可以放置各种触发效果,每个触发效果的类型是QAction

 

你加了这个新建以后它叫做QAction 每个触发效果的类型是 QAction

新建变成了二级菜单 只有最终能点击触发效果的才会变成QAction  

QAction的配置在Designer中通过专属的面板完成:

在上面的面板中找到要编辑的QAction对象,双击即可配置参数。

QAction有以下信号函数:

可以使用拖拽的方式把QAction编程工具栏中的按钮,最好给QAction提前设置好图标。

关于状态栏QStatusBar有两个常用的槽函数:

void QStatusBar::clearMessage() [slot]

清空状态栏信息显示

void QStatusBar::showMessage(const QString & message, 
                             int timeout = 0) [slot]

设置状态栏信息显示

参数1:显示的文字信息

参数2:显示的时长,单位毫秒,0表示持续显示

示例代码下载链接:https://pan.baidu.com/s/15DZlTkMDviC6J5_p0NTL4A 

提取码:hqyj

--来自百度网盘超级会员V6的分享

mainwindow.cpp

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

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // 肉眼可见的对象都归ui指针管理
    connect(ui->actionNew,SIGNAL(triggered()),
            this,SLOT(triggeredSlot()));

    connect(ui->pushButtonShow,SIGNAL(clicked()),
            this,SLOT(btnShowClickedSlot()));
    connect(ui->pushButtonClear,SIGNAL(clicked()),
            this,SLOT(btnClearClickedSlot()));
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::triggeredSlot()
{
    QMessageBox::information(this,"提示","已新建文件!!!!!!");
}

void MainWindow::btnShowClickedSlot()
{
    ui->statusBar->showMessage("哈哈哈哈哈哈哈",5000);
}

void MainWindow::btnClearClickedSlot()
{
    ui->statusBar->clearMessage();
}

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QMessageBox>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private:
    Ui::MainWindow *ui;

private slots:
//    与void triggered()信号连接
    void triggeredSlot();

    // 两个按钮点击的槽函数
    void btnShowClickedSlot();
    void btnClearClickedSlot();
};

#endif // MAINWINDOW_H

四、内存管理

Qt的内存管理机制与C++不同,几乎所有的Qt类的构造函数都有一个名为parent的参数,此参数表示设置当前对象的父对象父对象不仅仅表示子组件与父窗口之间的显示关系,更表示在内存回收上的依赖关系。

建议尽量给对象传入parent参数,以便于保持Qt的内存回收机制;如果不传入parent参数则需要留意内存回收的时机。

堆内存对象尽量传parent

示例代码下载链接:https://pan.baidu.com/s/1Ed7T4CzPSC6DJJXH-hfOCg 

提取码:hqyj

--来自百度网盘超级会员V6的分享

dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"

Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);

    connect(ui->pushButtonYes,SIGNAL(clicked()),
            this,SLOT(btnYesClickedSlot()));
    connect(ui->pushButtonNo,SIGNAL(clicked()),
            this,SLOT(btnNoClickedSlot()));
}

Dialog::~Dialog()
{
    delete ui;
    qDebug() << "析构函数";
}

void Dialog::btnYesClickedSlot()
{
    // 创建一个子窗口对象并展示,使用parent参数
    Dialog* d = new Dialog(this);
    d->show();
}

void Dialog::btnNoClickedSlot()
{
    // 创建一个子窗口对象并展示,不使用parent参数
    Dialog* d = new Dialog;
    d->show();
}

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 btnYesClickedSlot();
    void btnNoClickedSlot();
};

#endif // DIALOG_H

传入parent参数打开的窗口 后面的会依赖前面的哪一个如果前面的窗口关闭后面的也会关闭

不传入parent参数每个窗口都是独立的没有依赖关系  但是回收时需要手动回收 堆内存对象手动delete 栈内存对象无所谓  主要是针对堆内存  

加了parent就不用考虑手动回收了

五、自定义窗口类

下面手动创建一个自定义窗口类对象,操作步骤如下:

1. 选中项目名称,鼠标右键,点击“添加新文件”

2. 在弹出的窗口中,按照下图所示进行操作。

3. 在弹出的窗口中,先选择要创建的窗口类型,再点击“下一步”。

4. 在新弹出的窗口中,给类命名后,点击“下一步”。

5. 在项目管理界面,直接点击“完成”。可以看到项目中多了一个窗口类的头文件、源文件和界面文件。

示例代码下载链接:百度网盘 请输入提取码

提取码:hqyj

--来自百度网盘超级会员V6的分享

dialog.h

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
// 引入MyDialog类的头文件
#include "mydialog.h"

namespace Ui {
class Dialog;
}

class Dialog : public QDialog
{
    Q_OBJECT

public:
    explicit Dialog(QWidget *parent = 0);
    ~Dialog();

private:
    Ui::Dialog *ui;

private slots:
    // 点击按钮触发的槽函数
    void btnClickedSlot();
};

#endif // DIALOG_H

mydialog.h

#ifndef MYDIALOG_H
#define MYDIALOG_H

#include <QDialog>

namespace Ui {
class MyDialog;
}

class MyDialog : public QDialog
{
    Q_OBJECT

public:
    explicit MyDialog(QWidget *parent = 0);
    ~MyDialog();

private:
    Ui::MyDialog *ui;
};

#endif // MYDIALOG_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(btnClickedSlot()));
}

void Dialog::btnClickedSlot()
{
    // 创建MyDialog类对象
    MyDialog* md = new MyDialog(this);
    // 展示
    md->show();
}

Dialog::~Dialog()
{
    delete ui;
}

上述功能为点击dialog界面的按钮会打开mydialog窗口

六、参数传递

6.1 成员函数传参

【例子】转动上面代码中的绿色QDial,橙色QDial跟随绿色QDial一起转动。

示例代码下载链接:https://pan.baidu.com/s/1OpgiIiyV6WjQFLhlBsF4pw 

提取码:hqyj

--来自百度网盘超级会员V6的分享

主窗口去主导 然后子窗口跟着动一般使用成员函数 或者构造函数

dialog.h

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
// 引入MyDialog类的头文件
#include "mydialog.h"

namespace Ui {
class Dialog;
}

class Dialog : public QDialog
{
    Q_OBJECT

public:
    explicit Dialog(QWidget *parent = 0);
    ~Dialog();

private:
    Ui::Dialog *ui;
    MyDialog* md = NULL; // 子窗口对象 要写成成员的 局部的拿不到主窗口传的数值

private slots:
    // 点击按钮触发的槽函数
    void btnClickedSlot();
    // 检测绿色QDial转动的槽函数void	valueChanged(int value)
    void valueChangedSlot(int);
};

#endif // DIALOG_H

mydialog.h

#ifndef MYDIALOG_H
#define MYDIALOG_H

#include <QDialog>

namespace Ui {
class MyDialog;
}

class MyDialog : public QDialog
{
    Q_OBJECT

public:
    explicit MyDialog(QWidget *parent = 0,int value = 0);//构造函数传参 要遵循向右原则 第一个//参数赋值 后面的必须赋值 还要注意 声明定义在一个地方赋值就行
//保证两个的起始位置在一个地方, 第二个参数就是创建完盖子窗口时子窗口的初始位置
    ~MyDialog();
    // 公开一个函数可以设置橙色QDial的数值
    void setValue(int);
    //注意上面的成员函数不能写成私有的 因为写的这个函数要给主窗口里面去调用实在类外调用的

private:
    Ui::MyDialog *ui;
};

#endif // MYDIALOG_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(btnClickedSlot()));
    connect(ui->dial,SIGNAL(valueChanged(int)),
            this,SLOT(valueChangedSlot(int)));
}

void Dialog::btnClickedSlot()
{
    //因为主窗口可以拿到子窗口的一个对象 就可以很方便的去调用子窗口里面的任意一个函数
    // 创建MyDialog类对象 要写成成员的不然别的函数调用不了
    md = new MyDialog(this,ui->dial->value());
    // 展示
    md->show();
    // 屏蔽按钮  原因你只能操控一个子窗口多的操作不了
    ui->pushButton->setEnabled(false);
}

void Dialog::valueChangedSlot(int value)
{
    if(md != NULL)//防止没创建子窗口时就转导致的程序异常 因为你转的话会调用该槽函数 这里面的md没有创建出来  加了该代码就不会走下面的代码
        // 把参数值传递给第二个窗口对象
        md->setValue(value);
}

Dialog::~Dialog()
{
    delete ui;
}

mydialog.cpp

#include "mydialog.h"
#include "ui_mydialog.h"

MyDialog::MyDialog(QWidget *parent,int value) ://因为在声明处赋予初始值了 这里就不用再写了
    QDialog(parent),
    ui(new Ui::MyDialog)
{
    ui->setupUi(this);
    // 初始化QDial的数值
    ui->dial->setValue(value);//构造函数传参
}

MyDialog::~MyDialog()
{
    delete ui;
}

void MyDialog::setValue(int value)
{
    // 设置显示的数值
    ui->dial->setValue(value);
}

6.2 信号槽传参

【例子】转动上面代码中的橙色QDial,绿色QDial跟随橙色QDial一起转动。

就是右边的东西发送到左边来

链接:https://pan.baidu.com/s/1owM93_UPSQpAqQ7NRqZafA 

提取码:hqyj

--来自百度网盘超级会员V6的分享

dialog.h

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
// 引入MyDialog类的头文件
#include "mydialog.h"
#include <QDebug>

namespace Ui {
class Dialog;
}

class Dialog : public QDialog
{
    Q_OBJECT

public:
    explicit Dialog(QWidget *parent = 0);
    ~Dialog();

private:
    Ui::Dialog *ui;
    MyDialog* md = NULL; // 子窗口对象

private slots:
    // 点击按钮触发的槽函数
    void btnClickedSlot();
    // 检测绿色QDial转动的槽函数void	valueChanged(int value)
    void valueChangedSlot(int);
    // 接收子窗口发来的信号的槽函数
    void valueSlot(int);
};

#endif // DIALOG_H

mydialog.h

#ifndef MYDIALOG_H
#define MYDIALOG_H

#include <QDialog>

namespace Ui {
class MyDialog;
}

class MyDialog : public QDialog
{
    Q_OBJECT

public:
    explicit MyDialog(QWidget *parent = 0,int value = 0);
    ~MyDialog();
    // 公开一个函数可以设置橙色QDial的数值
    void setValue(int);

private:
    Ui::MyDialog *ui;

private slots:
    // 接收橙色QDial数值变化的槽函数
    void valueChangedSlot(int);

signals:
    // 发射橙色QDial数值的信号函数(声明完就可以用) 什么时候发射每一次橙色数值变化的时候就发射
    void valueSignal(int);
};

#endif // MYDIALOG_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(btnClickedSlot()));
    connect(ui->dial,SIGNAL(valueChanged(int)),
            this,SLOT(valueChangedSlot(int)));
}

void Dialog::btnClickedSlot()
{
    // 创建MyDialog类对象  为啥后面是ui->dial->value()是因为通过定义是的默认参数value=0 这个就是获得那个默认参数
    md = new MyDialog(this,ui->dial->value());
    // 建立两个窗口间通信的信号槽连接
    connect(md,SIGNAL(valueSignal(int)),
            this,SLOT(valueSlot(int)));

    // 展示
    md->show();
    // 屏蔽按钮
    ui->pushButton->setEnabled(false);
}

void Dialog::valueChangedSlot(int value)
{
    if(md != NULL)
        // 把参数值传递给第二个窗口对象
        md->setValue(value);
}

void Dialog::valueSlot(int value)
{
    // 更新显示
    ui->dial->setValue(value);
}

Dialog::~Dialog()
{
    delete ui;
}

mydialog.cpp

#include "mydialog.h"
#include "ui_mydialog.h"

MyDialog::MyDialog(QWidget *parent,int value) :
    QDialog(parent),
    ui(new Ui::MyDialog)
{
    ui->setupUi(this);
    // 初始化QDial的数值
    ui->dial->setValue(value);
    // 连接QDial数值监听的信号槽  发送出去然后第一个界面来接收
    connect(ui->dial,SIGNAL(valueChanged(int)),
            this,SLOT(valueChangedSlot(int)));
}

MyDialog::~MyDialog()
{
    delete ui;
}

void MyDialog::setValue(int value)
{
    // 设置显示的数值
    ui->dial->setValue(value);
}

void MyDialog::valueChangedSlot(int value)
{
    // 发射自定义信号
    emit valueSignal(value);
}

七、事件机制

7.1 事件机制原理

事件机制是Qt的核心逻辑,事件是程序运行的过程中的某些操作,这些操作会在操作系统与应用程序中逐层传递。

上图表示的是从用户操作到操作系统,再到应用程序的传递过程,对于Qt开发的应用程序而言,事件也会在应用程序内部逐层传递,如下所示。

操作系统发送给应用程序的大管家 再发给当前正在获取焦点的子组件 最后把事件给父组件(比如按钮子组件 处理完事情后给最后给窗口 窗口时父组件

7.2 事件函数

本次授课在事件传递的最后一个环节,即父窗口中使用事件函数检测事件传递。

所有事件函数的用法基本相同,常用的事件函数如下:

// 绘制
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]

QPainter是画家类,可以在QPaintDevice的派生类上绘制各种各种的图形,QPaintDevice是QWidget的基类,即QWidget及其所有派生类都可以被QPainter对象进行绘制。

QPainter::QPainter(QPaintDevice * device)

QPainter的构造函数,参数是在哪个对象上作画。

void QPainter::drawPixmap(int x, int y, int width, int height, const QPixmap & pixmap)

绘制QPixmap的内容。

参数1:绘制内容的横坐标,定位点是绘制内容的左上角

参数2:绘制内容的纵坐标,定位点是绘制内容的左上角

参数3:绘制内容的宽度

参数4:绘制内容的高度

参数5:绘制的内容

示例代码下载链接:百度网盘 请输入提取码

提取码:hqyj

--来自百度网盘超级会员V6的分享

dialog.h

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
// 头文件
#include <QDebug>
#include <QPixmap>    //图片类
#include <QPainter> // 画家类
#include <QKeyEvent> // 按键事件类
#include <QMessageBox> //信息弹窗类

namespace Ui {
class Dialog;
}

class Dialog : public QDialog
{
    Q_OBJECT

public:
    explicit Dialog(QWidget *parent = 0);
    ~Dialog();

    // 声明事件函数,为了覆盖事件函数  因为他们是虚函数
protected:
    void paintEvent(QPaintEvent*);//绘制事件
    void keyPressEvent(QKeyEvent*);//键盘按下事件

private:
    Ui::Dialog *ui;
};

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

Dialog::~Dialog()
{
    delete ui;
}

/**
 * @brief Dialog::paintEvent
 * 1. 组件从无到有,从有到无会触发
 * 2. 大小改变会触发,移动不会触发
 */
void Dialog::paintEvent(QPaintEvent *)
{
    qDebug() << width() << "*" << height(); //打印窗口的宽高
    qDebug() << x() << "," << y();           //打印窗口坐标
    QPixmap map(":/new/prefix1/yuandan.jpg");
    QPainter painter(this); // 一个在窗口上绘制的画家对象
    // 开始绘制
    /*
    参数1:绘制内容的横坐标,定位点是绘制内容的左上角
    参数2:绘制内容的纵坐标,定位点是绘制内容的左上角    
    参数3:绘制内容的宽度
    参数4:绘制内容的高度
    参数5:绘制的内容
*/
    painter.drawPixmap(0,0,width(),height(),map);
}

/**
 * @brief Dialog::keyPressEvent
 * @param event 包含当前事件的相关信息,QKeyEvent包含按键编码
 */
void Dialog::keyPressEvent(QKeyEvent * event)
{
    if(Qt::Key_A == event->key()) // 如果是A键
    {
        // 获得进度条当前数值
        int value = ui->progressBar->value();
        if(value == 0)
        {
            QMessageBox::information(this,"提示","拒绝emo");
            return;
        }
        ui->progressBar->setValue(--value);
    }else if(Qt::Key_D == event->key())
    {
        // 获得进度条当前数值
        int value = ui->progressBar->value();
        if(value == 100)
        {
            QMessageBox::information(this,"提示","快乐无边!");
            return;
        }
        ui->progressBar->setValue(++value);
    }
}

7.3 事件过滤器

事件过滤器可以在父组件对象中检测子组件对象传递的事件。

使用事件过滤器需要给监控的子组件注册事件过滤器后,在父组件对象中覆盖下面的函数。

bool QObject::eventFilter(QObject * watched, QEvent * event) [virtual protected]

参数1:被观察的子组件对象

参数2:当前检测的事件对象

返回值:是否拦截事件的传递,建议初学者不要写固定值,此处调用原基类被覆盖的函数返回值。

d9b1f0af01f5c21257cd260c12ec80a0.png

22ebabfe60f6eda2463bb6d7c605d7f3.png

Type QEvent::type() const

返回当前事件的类型

示例代码下载链接:百度网盘 请输入提取码

提取码:hqyj

--来自百度网盘超级会员V6的分享

dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"

Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);

    // 给第一个输入框注册事件过滤器  installEventFilter安装注册使用
    ui->lineEdit->installEventFilter(this);
}

Dialog::~Dialog()
{
    delete ui;
}
//参数1:被观察的子组件对象
//参数2:当前检测的事件对象

bool Dialog::eventFilter(QObject * watched, QEvent * event)
{
    // 先判断是哪个组件,再判断当前组件的事件类型  FocusIn 获取焦点   event->type()返回当前事件的类型
    if(watched == ui->lineEdit && QEvent::FocusIn == event->type())
    {
        qDebug() << "第一个输入框获取了焦点!";
        //FocusOut 失去焦点              这个事件类型去第一个图片找
    }else if(watched == ui->lineEdit && QEvent::FocusOut == event->type())
    {
        qDebug() << "第一个输入框失去了焦点!";
    }

    // 调用基类覆盖的函数  这个函数有返回值
    return QDialog::eventFilter(watched,event);
}

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

protected:
    // 声明事件过滤器函数 bool QObject::eventFilter(QObject * watched, QEvent * event) [virtual protected]
    bool eventFilter(QObject *, QEvent *);

private:
    Ui::Dialog *ui;
};

#endif // DIALOG_H

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Qt第六章 多窗口编程 的相关文章

  • 在QT中以不同的时间间隔更新GUI [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我想知道如何在QT中以不同的时间间隔更新GUI 最好的是我可以控制时间间隔 我知道 QTimer 可以在同一时间间隔更新 GUI 但我
  • QML 适合所有分辨率的屏幕

    大家好 我的 QML 代码有问题 我犯了一个错误 我给元素设置了一定的大小 现在我在将应用程序放在其他设备上时遇到了问题 我会将我的代码粘贴到有宽度和高度的位置 以便您可以更改它以向我展示如何使用动态调整大小 我需要说我正在使用以下代码从
  • 无法锚定到不是父级或同级 QML QtQuick 的项目

    我正在使用 QML 开发 python 桌面应用程序 我的 QML 文件中有这个 SplitView anchors fill parent orientation Qt Horizontal Rectangle color 272822
  • Qt Creator 中的按钮是否有隐藏属性?

    Qt Creator 属性托盘中是否有按钮的隐藏属性 我想找到一个 但找不到 我需要禁用一些按钮并隐藏一些按钮 我应该使用属性托盘还是在构造函数中进行 稍后在用户事件中 它们将被启用并显示 有些控件在调色板上具有 可见性 属性 有些则没有
  • 如何删除在设计器模式下创建的插槽?

    我已经创建了按钮cancelButton 然后我创建了函数槽on cancelButton clicked 使用上下文菜单项Go to slot 但是 过了一段时间 我删除了这个按钮 不再需要 并尝试删除该函数 但编译器给出错误undefi
  • QMainWindow::showMaximized() 不更新大小

    我正在尝试创建一个QMainWindow封装一个QGraphicsView我把它放进去 我希望它一开始就最大化 所以我这样做 QMainWindow mainWindow new QMainWindow mainWindow gt setW
  • Qt 对象的生命周期

    Qt 对象的生命周期是多少 Such as QTcpSocket socket new QTcpSocket 套接字什么时候会被销毁 我应该使用 delete socket 有什么区别吗 QTcpSocket socket 我找不到有关此的
  • 无法隐藏 QMenu 对象 QMenu::setVisible()?

    我已经建立了一个QMenu MainMenu在我的上面MainWindow在我的应用程序中 大家都习惯了 我有以下QMenu主菜单 文件 编辑 SuperHeavyExpertMenus 设置 帮助 我想隐藏子树SuperHeaverExp
  • QT“找不到 Qt 平台插件“xcb””

    我出于学术原因安装了QT everywhere 5 15开源版 但无法运行程序 首先 我编译了必要的源文件make并安装了QT Creator 然后我选择qmake来运行其中的程序 当我尝试运行示例程序时 遇到以下错误 qt qpa plu
  • 关于 GUI 计时器显示后台线程已用时间的建议?

    Issue 我有一个 PyQt GUI 用户按下按钮即可启动后台线程 workerThread 它是从QThread 我想要一个计时器显示 以QLabel 显示自此以来已经过去了多少时间workerThread开始 我希望这个计时器在wor
  • QT 应用程序运行时错误?

    我已经在 Windows 7 的 Qt5 1 上开发了一个应用程序 现在我想分发它 由于我使用了 MINGW 编译器 因此无法静态构建它 我使用dependency walker找出所有dll并打包 当我在未安装 QT 开发环境的计算机上运
  • 获取小部件的背景颜色 - 真的

    我无法获取小部件的实际背景颜色 在我的特殊情况下 我在使用 QTabWidget 中的小部件时遇到问题 这是在Windows7上 因此 经典的小部件有一些灰色背景 而选项卡内的小部件通常用白色背景绘制 I tried def bgcolor
  • 我的 QSqlQueryModel 不在列表视图中显示数据

    我正在玩 QSqlQueryModel 但我现在完全陷入困境 我一整天都在寻找解决方案 但到目前为止还没有运气 我所做的工作是它从我的 sqlite 数据库中提取数据 但由于某种原因我无法在列表视图中显示它 我的角色名似乎不存在 对于我从数
  • 对齐坐标系

    Let s say I have 2 coordinate systems as it is shown in image attached 如何对齐这个坐标系 我知道我需要将第二个坐标系围绕 X 平移 180 度 然后将其平移到第一个坐标
  • QToolBar 的菜单延迟

    我通过制作 QAction 并向其添加 QMenu 在 QToolBar 上有一个菜单 如何消除单击图标时出现菜单之前的延迟 QToolBar myToolBar new QToolBar this QAction myAction new
  • 如何恢复 QSS 属性的默认系统值?

    如果父级之一将其样式表设置为 Qt QSS 会传播给子级color red 它的所有子级都将应用此样式表 如果你明确设置QLabel color red 那么只有 QLabel 子项会受到关注 如果子项设置自己的值 则可以覆盖子项的样式表c
  • cx_freeze:QODBC 驱动程序未加载

    我的 python 应用程序如下所示 test py from PyQt4 import QtCore from PyQt4 import QtGui from PyQt4 import QtSql import sys import at
  • Qt GUI 编程设计

    我正在尝试创建一个 GUI 应用程序 主窗口 一个QMainWindow 包含 9 个固定大小的标签以及主窗口的大小 我尝试在没有 Qt GUI Designer 的情况下以编程方式制作它 该项目构建时没有错误 但我看不到主窗口上显示的任何
  • qt项目如何设置安装路径

    我正在寻找与 qmake configure prefix 等效的内容 基本上 我想覆盖默认的安装 部署目录 这是如何用命令行 qmake 指定的 我还使用 QtCreator 构建了很多 gui 项目 并且我想知道如何在 QtCreato
  • 仅将非模态 QDialog 窗口放置在我的应用程序顶部,而不是所有应用程序顶部

    我有一个 QDialog 窗口 它应该始终位于我的应用程序顶部 它不是模态的 用户可以随时与对话框和主应用程序进行交互 使用窗口保持在顶部提示在某种程度上实现了这一点 但是 该对话框仍然位于所有其他正在运行的应用程序 例如记事本 chrom

随机推荐

  • Apple 允许您指定在您死后谁可以访问您的账户

    在周一的WWDC 2021活动中 Apple 宣布 从今年秋季的 iOS 15 和 macOS Monterey 操作系统更新开始 将可以指定在您死亡的情况下谁可以访问您的账户 新功能称为数字遗产 它使亲戚或朋友更容易访问已故亲人拥有的数码
  • ZYNQ7000系列 DDR读取正确性

    摘要 使用ZYNQ或者MPSoC的好处是可以通过PL逻辑设计硬件加速器 对功能进行硬件加速 加速器和ARM之间的交互信息一般包含自定义加速指令传递 待计算数据以及计算结果 这三种交互信息 使用ZYNQ或者MPSoC的好处是可以通过PL逻辑设
  • java 档案整理 生成归档章 透明背景图片

    import javax imageio ImageIO import java awt import java awt image BufferedImage import java io File import java io IOEx
  • unity3d鼠标点击,获取世界坐标

    unity中有关于鼠标位置的函数 Input mousePosition 但不得不说 这个函数不到位 可以用一个print函数输出一下这个坐标会发现 只有X Y值在改变 Z值没有发生变化 并且在屏幕的左下角固定为 0 0 0 查看文档后发现
  • 类加载器是否为空

    package com bzu csh 项目名称 Test1 类名称 Test2 类描述 创建人 admin 创建时间 2017年1月7日 下午9 41 36 修改人 admin 修改时间 2017年1月7日 下午9 41 36 修改备注
  • 数据可视化之折线图绘制

    使用python中的matplotlib绘制折线图 环境需求 python 或者anaconda pycharm 和第三方库matplotlib 首次先绘制简单的折线图 其他的参数可以在使用熟练后一点一点的加入 import matplot
  • 计算机网络课程笔记

    学习MOOC华南理工计算机网络课程笔记 第1章 概述 1 1 为什么要学习计算机网络 1 2 互联网发展史 1 3 常用的基本概念 1 4 参考模型 1 5 参考模型相关概念 1 6 本课程的组织 第2章 物理层 2 1 物理层概述 2 2
  • JNI编程—JNI基础

    什么是JNI 怎么使用 JNI Java Native Interface 它是Java平台的一个特性 并不是Android系统特有的 其实主要是定义了一些JNI函数 让开发者可以通过调用这些函数实现Java代码调用C C 的代码 C C
  • python 如何编写一个自己的包

    python 如何编写一个自己的包 先写function 内容 package wadepypk ls init py f1 py f2 py f1 py def show print in pkg f show f2 py def sho
  • unix bsd linux gun   粗略解释

    最早的unix是开放的 很多组织对unix都有修改 期中比较有名的就是伯克利大学的修改版本 叫做bsd 是unix的分支 由于bsd的协议允许你直接使用 修改他的代码 并且可以作为商业用途 所以很多公司的unix都是从bsd衍生过来的 比如
  • mongodb学习笔记一:mongodb安装与介绍

    一 前言 最近开始学习非关系型数据库MongoDB 却在博客园上找不到比较系统的教程 很多资料都要去查阅英文网站 效率比较低下 本人不才 借着自学的机会把心得体会都记录下来 方便感兴趣的童鞋分享讨论 部分资源出自其他博客 旨将零散知识点集中
  • C/C++函数模板template

    1 说明 当函数处理功能相似 函数名相同 但是参数个数或者类型有区别 我们知道实现的方式是依靠函数重载 overload 但是如果仅函数参数或返回数的类型不同 我们想到靠函数模板解决这个问题 不仅节省内存 而且不用复杂声明多个函数 函数模板
  • 为线程池中的每个线程设置UncaughtExceptionHandler

    参考了 java并发编程实战 P134内容 每当线程池需要创建一个线程时 都是通过调用线程工厂方法来完成的 默认的线程工厂方法将创建一个新的 非守护的线程 并且不包好特殊的配置信息 如果你希望在线程运行之前 之后 或者运行中如果发生异常等情
  • Linux 系统 lscpu 命令详解

    文章目录 前言 lscpu 命令详解 命令 1 查看物理 CPU 个数 2 查看每个物理 CPU 核数 3 查看总线程数 4 查看内存信息 5 查看 linux 系统版本 前言 Linux 系统查看系统相关信息方法很多 以下详细介绍 lsc
  • 一颗二叉树代码(图解)

    什么是二叉树 树结构是一种非线性存储结构 存储的是具有一对多关系的数据的集合 而树形结构的一种抽象出来的数据结构往往是二叉树的形式 满足以下两个条件的树就是二叉树 本身是有序树 树中包含的各个节点的度不能超过 2即只能是 0或者1 或者 2
  • 项目时间管理-架构真题(二十四)

    1 霍尔提出了系统方法的三维结构体系 通常称为霍尔三维结构 这就是系统工程方法论的基础 霍尔三维结构以时间堆 堆 知识堆组成的立体结构概括性表示出系统工程在各阶段 各步骤以及所涉及的知识范围 其中时间维是系统的工作进程 对于一个具体的工程项
  • 计算机网络面试八股文攻略(二)—— TCP 与 UDP

    一 基础概念 TCP 与 UDP 是活跃于 运输层 的数据传输协议 TCP 传输控制协议 Transmission Control Protocol 提供面向连接的 可靠的数据传输服务 具体来说就是一种要建立双端连接才能发送数据 能确保传输
  • react拖拽排序、js列表拖拽

    列表拖动排序的解决方案有多种 个人感觉最简单的就是zent 提供的 Sortable 组件了 一 zent Sortable 拖拽排序 推荐 简单明了 zent 官网 https zent contrib gitee io zent zh
  • 1139: 输出最短字符串java

    import java util Scanner public class Main public static void main String args Scanner input new Scanner System in int n
  • Qt第六章 多窗口编程

    一 QMessageBox 消息对话框 掌握 QMessageBox继承自QDialog 是一个Qt内置的用来展示信息或询问用户一个问题的模态对话框 预设了四种类型 像那些已经写好的窗口 这些现成的东西都会有一些特性 就是他们的对象都不需要