(6)——多窗口编程

news/2024/11/24 12:42:10/

目录

1. QMessageBox 消息对话框**

2. 窗口类继承关系**

3. QMainWindow 主窗口类**

3.1 QMenuBar 菜单栏

3.2 QToolBar 工具栏

3.3  QWidget 中心组件

3.4 QStatusBar 状态栏

4. parent参数**

5. 自定义窗口类**

6. 跨界面参数传递**

6.1 主窗口→子窗口

6.2 子窗口→主窗口

7. 事件函数**


1. QMessageBox 消息对话框**

QMessageBox继承自QDialog,是一种用于通知用户或询问用户一个问题的对话框窗口,这种窗口是模态的,会抢占窗口焦点,必须优先处理。

Qt内置的Dialog的派生类通常使用静态成员函数弹出:

// 参数1:父窗口
// 参数2:标题,相当于windowTitle属性
// 参数3:显示的信息
// 返回值:点击的按键类型StandardButton QMessageBox::四种弹窗类型(QWidget * parent, const QString & title, const QString & text) [static]
dialog.h
#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>
#include <QButtonGroup>
#include <QtWidgets> //包含所有组件和窗口的头文件namespace Ui {
class Dialog;
}class Dialog : public QDialog
{Q_OBJECTpublic:explicit Dialog(QWidget *parent = 0);~Dialog();private:Ui::Dialog *ui;QButtonGroup *group;private slots:void btnsClickedSlot(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);group = new QButtonGroup(this);group->addButton(ui->pushButtonQ,1);group->addButton(ui->pushButtonI,2);group->addButton(ui->pushButtonW,3);group->addButton(ui->pushButtonC,4);connect(group,SIGNAL(buttonClicked(int)),this,SLOT(btnsClickedSlot(int)));}
void Dialog::btnsClickedSlot(int id){if(id == 1){QMessageBox::question(this,"question","你今晚吃饭吗?");}else if(id == 2){QMessageBox::information(this,"information","你今晚要吃饭!");}else if(id == 3){QMessageBox::warning(this,"warning","一顿不吃饿得慌!");}else if(id == 4){QMessageBox::critical(this,"critical","顿顿不吃要完蛋!");
}
}
Dialog::~Dialog()
{delete group;delete ui;
}

 ui:

 运行结果:

在question中加问题

dialog.h

#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>
#include <QButtonGroup>
#include <QtWidgets> //包含所有组件和窗口的头文件
#include <QDebug>namespace Ui {
class Dialog;
}class Dialog : public QDialog
{Q_OBJECTpublic:explicit Dialog(QWidget *parent = 0);~Dialog();private:Ui::Dialog *ui;QButtonGroup *group;private slots:void btnsClickedSlot(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);group = new QButtonGroup(this);group->addButton(ui->pushButtonQ,1);group->addButton(ui->pushButtonI,2);group->addButton(ui->pushButtonW,3);group->addButton(ui->pushButtonC,4);connect(group,SIGNAL(buttonClicked(int)),this,SLOT(btnsClickedSlot(int)));}
void Dialog::btnsClickedSlot(int id){if(id == 1){QMessageBox::StandardButton result = QMessageBox::question(this,"question","你今晚吃饭吗?");if(result == QMessageBox::Yes)qDebug()<<"吃了!";else if(result == QMessageBox::No)qDebug()<<"没吃!";}else if(id == 2){QMessageBox::information(this,"information","你今晚要吃饭!");}else if(id == 3){QMessageBox::warning(this,"warning","一顿不吃饿得慌!");}else if(id == 4){QMessageBox::critical(this,"critical","顿顿不吃要完蛋!");
}
}
Dialog::~Dialog()
{delete group;delete ui;
}

 

 

2. 窗口类继承关系**

窗口类的继承关系如下所示。

QWidget类作为窗口和组件的基类,其内部定义了窗口和组件的基本功能,本节展示一部分作为窗口类的基类所拥有的API:

// 设置窗口状态
// 参数为窗口状态值
void QWidget::setWindowState(Qt::WindowStates windowState)

// 设置窗口标记 
// 参数为窗口标记值,多个值之间可以使用|分割,以实际效果为准 
void setWindowFlags(Qt::WindowFlags type)

dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"Dialog::Dialog(QWidget *parent) :QDialog(parent),ui(new Ui::Dialog)
{ui->setupUi(this);// 设置全屏显示
//    setWindowState(Qt::WindowFullScreen);// 设置欢迎页效果setWindowFlags(Qt::FramelessWindowHint|Qt::WindowStaysOnTopHint);
}Dialog::~Dialog()
{delete ui;
}

QWidget类本身作为所有窗口和组件的基类,QWidget既可以作为窗口对象进行创建,又可以作为组件对象进行创建。

QWidget的构造函数的parent参数传递了一个窗口对象时,此时QWidget会成为这个窗口对象内部的组件。如果不传递此参数,QWidget对象会成为一个独立窗口。

3. QMainWindow 主窗口类**

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

3.1 QMenuBar 菜单栏

菜单栏的组成部分如下所示。

QAction支持信号槽的连接,其信号函数如下。

除了在Designer中添加菜单栏和配置QAction的内容,也可以在C++代码中添加。

3.2 QToolBar 工具栏

当使用Action编辑器设置了QAction的图标后,可以直接拖拽到QToolBar变为工具栏按钮。

工具栏所有的操作也都可以在C++代码中找到对应API。

3.3  QWidget 中心组件

见本章第2节中QWidget作为组件使用时的说明。

3.4 QStatusBar 状态栏

状态栏主要用于显示软件的相关辅助信息,可以使用预设的样式(比较简单),也可以自定义样式。本次以预设的样式为例进行讲解。

主要的函数如下所示。

// 显示信息
// 参数1:信息内容
// 参数2:显示时长,单位毫秒,如果为0(默认值)表示持续显示
void QStatusBar::showMessage(const QString & message, int timeout = 0) [slot]
// 清空信息
void QStatusBar::clearMessage() [slot]

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>namespace Ui {
class MainWindow;
}class MainWindow : public QMainWindow
{Q_OBJECTpublic:explicit MainWindow(QWidget *parent = 0);~MainWindow();private:Ui::MainWindow *ui;private slots:// QAction点击后触发的槽函数void triggeredSlot();
};#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{ui->setupUi(this);// 连接信号槽connect(ui->actionOpen,SIGNAL(triggered()),this,SLOT(triggeredSlot()));// 设置状态栏内容ui->statusBar->showMessage("哈哈哈哈",3000);
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::triggeredSlot()
{// 设置一点显示效果ui->plainTextEdit->setPlainText("这是随便设置的内容");
}

ui界面:

 运行结果:

 

4. parent参数**

几乎所有的Qt类的构造函数都有一个parent参数,实际上parent参数是Qt的一种内存管理策略。parent参数会作为新创建对象的父对象存在,当父对象销毁时,会一并销毁子对象。

建议在绝大多数情况下,传递parent参数,防止内存泄漏。

dialog.h

#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>
#include <QDebug>namespace Ui {
class Dialog;
}class Dialog : public QDialog
{Q_OBJECTpublic:explicit Dialog(QWidget *parent = 0);~Dialog();private:Ui::Dialog *ui;private slots://两个按钮点击的槽函数void btn1ClickedSlot();void btn2ClickedSlot();
};#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_1,SIGNAL(clicked()),this,SLOT(btn1ClickedSlot()));connect(ui->pushButton_2,SIGNAL(clicked()),this,SLOT(btn2ClickedSlot()));
}Dialog::~Dialog()
{qDebug()<<"析构函数";delete ui;
}void Dialog::btn1ClickedSlot()
{Dialog* d = new Dialog(this);d->show();
}void Dialog::btn2ClickedSlot()
{Dialog* d = new Dialog;d->show();
}
 

 

 哪个最后关,哪个调出析构函数

 

5. 自定义窗口类**

截止到当前,Qt项目中从来没有完整地创建过一个自定义的窗口类,要么使用的是项目创建后自带的窗口类,要么使用Qt内置的窗口类QMessageBox。

在项目中创建一个Qt的自定义窗口类的操作步骤如下所示。

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

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

3. 在弹出的窗口中选择窗口的模板样式后,点击“下一步”。

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

5. 在项目管理界面点击“完成”。

dialog.h

#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>
// 头文件
#include "mydialog.h"namespace Ui {
class Dialog;
}class Dialog : public QDialog
{Q_OBJECTpublic:explicit Dialog(QWidget *parent = 0);~Dialog();private:Ui::Dialog *ui;private slots:void btnClickedSlot(); // 单击按钮的槽函数
};#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(btnClickedSlot()));
}void Dialog::btnClickedSlot()
{// 创建并启动MyDialog窗口MyDialog* md = new MyDialog(this);md->show();// 屏蔽按钮ui->pushButton->setEnabled(false);
}Dialog::~Dialog()
{delete ui;
}

6. 跨界面参数传递**

6.1 主窗口→子窗口

这种情况可以使用子窗口的构造函数/成员函数传参。

【例子】转动主窗口的QDial,使子窗口的QDial跟着一起转动。

dialog.h

#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>
// 头文件
#include "mydialog.h"namespace Ui {
class Dialog;
}class Dialog : public QDialog
{Q_OBJECTpublic:explicit Dialog(QWidget *parent = 0);~Dialog();private:Ui::Dialog *ui;MyDialog* md;private slots:void btnClickedSlot(); // 单击按钮的槽函数void valueChangedSlot(int); // QDial数值变化的槽函数
};#endif // DIALOG_H

dialoh.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窗口// 参数1:当前主窗口的QDial数值md = new MyDialog(ui->dial->value(),this);// 建立QDial的信号槽connect(ui->dial,SIGNAL(valueChanged(int)),this,SLOT(valueChangedSlot(int)));md->show();// 屏蔽按钮ui->pushButton->setEnabled(false);
}void Dialog::valueChangedSlot(int value)
{// 给子窗口设定参数值md->setDialValue(value);
}Dialog::~Dialog()
{delete ui;
}

mydialog.h

#ifndef MYDIALOG_H
#define MYDIALOG_H#include <QDialog>namespace Ui {
class MyDialog;
}class MyDialog : public QDialog
{Q_OBJECTpublic:// 增加参数位explicit MyDialog(int,QWidget *parent = 0);~MyDialog();// 增加成员函数void setDialValue(int);private:Ui::MyDialog *ui;
};#endif // MYDIALOG_H

mydialog.cpp

#include "mydialog.h"
#include "ui_mydialog.h"MyDialog::MyDialog(int value,QWidget *parent) :QDialog(parent),ui(new Ui::MyDialog)
{ui->setupUi(this);// 设置QDial的初始值ui->dial->setValue(value);
}MyDialog::~MyDialog()
{delete ui;
}void MyDialog::setDialValue(int value)
{// 设置QDial的变化值ui->dial->setValue(value);
}

6.2 子窗口→主窗口

这种情况可以使用信号槽传参,子窗口发射带参数自定义信号给主窗口的槽函数接收。

【例子】转动子窗口的QDial,使主窗口的QDial跟着一起转动。

dialog.h

#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>
// 头文件
#include "mydialog.h"namespace Ui {
class Dialog;
}class Dialog : public QDialog
{Q_OBJECTpublic:explicit Dialog(QWidget *parent = 0);~Dialog();private:Ui::Dialog *ui;private slots:void btnClickedSlot(); // 单击按钮的槽函数// 与子窗口中的自定义信号连接void valueSlot(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);// 连接信号槽connect(ui->pushButton,SIGNAL(clicked()),this,SLOT(btnClickedSlot()));
}void Dialog::btnClickedSlot()
{// 创建并启动MyDialog窗口MyDialog* md = new MyDialog(this);// 建立两个窗口对象之间的信号槽connect(md,SIGNAL(valueSignal(int)),this,SLOT(valueSlot(int)));md->show();// 屏蔽按钮ui->pushButton->setEnabled(false);
}void Dialog::valueSlot(int value)
{// 更新到组件上ui->dial->setValue(value);
}Dialog::~Dialog()
{delete ui;
}

mydialog.h

#ifndef MYDIALOG_H
#define MYDIALOG_H#include <QDialog>namespace Ui {
class MyDialog;
}class MyDialog : public QDialog
{Q_OBJECTpublic:explicit MyDialog(QWidget *parent = 0);~MyDialog();private:Ui::MyDialog *ui;private slots:// QDial转动的槽函数void valueChangedSlot(int);signals:// 带参数的自定义信号void valueSignal(int);};#endif // MYDIALOG_H

mydialog.cpp

#include "mydialog.h"
#include "ui_mydialog.h"MyDialog::MyDialog(QWidget *parent) :QDialog(parent),ui(new Ui::MyDialog)
{ui->setupUi(this);connect(ui->dial,SIGNAL(valueChanged(int)),this,SLOT(valueChangedSlot(int)));
}MyDialog::~MyDialog()
{delete ui;
}void MyDialog::valueChangedSlot(int value)
{// 发送到主窗口!emit valueSignal(value);
}

7. 事件函数**

事件函数的使用依托于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]

QPaintDevice类表示可绘制设备,其派生类均可以被QPainter类绘制。

dialog.h

#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>
#include <QDebug>
#include <QPixmap> // 图片类
#include <QPainter> // 画家类namespace Ui {
class Dialog;
}class Dialog : public QDialog
{Q_OBJECTpublic:explicit Dialog(QWidget *parent = 0);~Dialog();protected:// 声明事件函数void paintEvent(QPaintEvent * event);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;
}// 定义事件函数
void Dialog::paintEvent(QPaintEvent *)
{// 输出窗口宽高qDebug() << this->width() << this->height();// 创建画家类对象QPainter painter(this);QPixmap pic(":/new/prefix1/ikun.jpg");// 绘制图片函数// void QPainter::drawPixmap(int x, int y, int width, int height, const QPixmap & pixmap)// 参数1:横坐标// 参数2:纵坐标// 参数3:宽度// 参数4:高度// 参数5:图片内容painter.drawPixmap(0,0,width(),height(),pic);
}

运行结果:

 dialog.h

#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>
#include <QDebug>
#include <QPixmap> // 图片类
#include <QPainter> // 画家类
#include <QKeyEvent> // 键盘事件参数namespace Ui {
class Dialog;
}class Dialog : public QDialog
{Q_OBJECTpublic:explicit Dialog(QWidget *parent = 0);~Dialog();protected:// 声明事件函数void paintEvent(QPaintEvent * event);void keyPressEvent(QKeyEvent * event);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;
}// 定义事件函数
void Dialog::paintEvent(QPaintEvent *)
{// 输出窗口宽高qDebug() << this->width() << this->height();// 创建画家类对象QPainter painter(this);QPixmap pic(":/new/prefix1/ikun.jpg");// 绘制图片函数// void QPainter::drawPixmap(int x, int y, int width, int height, const QPixmap & pixmap)// 参数1:横坐标// 参数2:纵坐标// 参数3:宽度// 参数4:高度// 参数5:图片内容painter.drawPixmap(0,0,width(),height(),pic);
}// 所有的事件函数的参数都包含了当前类型事件的参数信息
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);}
}

运行结果:

 


http://www.ppmy.cn/news/63041.html

相关文章

Linux-Day02

Linux-Day02 课程内容 软件安装 项目部署 1. 软件安装 1.1 软件安装方式 在Linux系统中&#xff0c;安装软件的方式主要有四种&#xff0c;这四种安装方式的特点如下&#xff1a; 安装方式特点二进制发布包安装软件已经针对具体平台编译打包发布&#xff0c;只要解压&am…

NECCS|全国大学生英语竞赛C类|词汇和语法|语法题|时态 非谓语动词 |19:00~20:15|完形填空·词性转化

14:35&#xff5e;14:45 15:45&#xff5e;16:2019:00&#xff5e;20:15 http://t.csdn.cn/XbsUy 目录 &#xff08;一&#xff09;时态 7. 将来进行时 8. 过去将来进行时 9. 现在完成时 10. 过去完成时​编辑 11. 将来完成时 12. 现在完成时 13. 过去完成进行时 &#xff08;…

第三节课 Linux文件权限

目录 文件属性详解 权限修改 文件所有者与属组修改 文件默认权限修改 Linux是多人多任务的操作系统&#xff0c;因此可能常常会有多人使用一台机器&#xff0c; 为了考虑每个人的隐私、方便用户合作&#xff0c;每个文件都有三类用户&#xff0c;权限是基于这三类用户设定的…

北京地铁:充分发挥数据价值,全面提升业财融合能力

4月19日-4月21日&#xff0c;一年一度的用友BIP技术大会圆满召开。来自行业领先企业的CIO/CDO、生态伙伴、开发者、分析师、媒体等共聚北京用友产业园&#xff0c;了解最新技术发展趋势、探讨行业热点话题。会上&#xff0c;北京地铁运营有限公司&#xff08;以下简称“北京地铁…

最近想学PMP,有什么要注意和推荐的吗?

我觉得参加PMP的学习和考试有两点需要把握住&#xff0c;一是心态&#xff0c;二是学习方法&#xff1b; 谈心态的话虽然比较虚&#xff0c;因为这个还是要看个人在生活中对事物发展的应对能力与应对突发情况的处理能力&#xff0c;但是简单的谈谈在备考过程中心态的处理还是很…

​射频PCB 设计​的六大条技巧

即使是最自信的设计人员&#xff0c;对于射频电路也往往望而却步&#xff0c;因为它会带来巨大的设计挑战&#xff0c;并且需要专业的设计和分析工具。这里将为您介绍六条技巧&#xff0c;来帮助您简化任何射频PCB 设计任务和减轻工作压力&#xff01; 1、保持完好、精确的射频…

Vue列表展示【第二篇】

&#x1f331; 1、vue列表展示案例 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>vueDemo02列表展示</title> </head> <body> <div id"xy"><!--原始展示方式…

MagicaCloth2安装教程

您可访问官网查看详情&#xff1b; MagicaSoft Unity Assets – Magica Soft 也可通过我的资源文件获得此插件的详细教程&#xff1a; (19条消息) UnityMagicaCloth2插件中文文档&#xff08;机翻/部分&#xff09;-Unity3D文档类资源-CSDN文库 MagicaCloth2是基于ECS开发的…