【QT】4_1_1_Qt窗口介绍(QMainWindow、QDialog、QMessageBox都继承自QWidget)

作者:永恒0852永恒0852发布时间:2017-11-14 20:55
1.WHAT
            什么是窗口:在生活中随处可见的也有很多窗口,比如房子的窗户,在建筑学上是指墙或屋顶上建造的洞口(事实上窗和户的本意分别指窗和门,在现代汉语中窗户则单指窗。),用以使光线或空气进入室内,实现室内和室外的信息实现交互。计算机也存在很多窗户,指系统中一种新的操作环境。把计算机的显示屏幕划分成许多的框,即为窗口。每个窗口负责显示和处理某一类信息。用户可随意在任一窗口上工作,并在各窗口间交换信息。

        1)生活中可以看到的有哪些窗口?
            ①窗户:站在窗口远望。
            ②(售票处、挂号室等)墙上开的窗形的口,有活扇可以开关:指直接为群众生活服务的。
        2)生活中看不到的有哪些窗口?
            ①比喻渠道:途径:工厂开设门市部,可以成为了解市场信息的窗口。
            ②比喻反映或展示精神上、物质上各种现象或状况的地方:眼睛是心灵的窗口。
        3)我们QT中有哪些窗口?
            ①QMainWindow 类提供一个有菜单条、锚接窗口(例如工具条)和一个状态条的主应用程序窗口。
            ②QWidget 类是所有用户界面对象的基类。
            ③QDialog 类是对话框窗口的基类。对话框窗口是主要用于短期任务以及和用户进行简要通讯的顶级窗口。
            ④在哪里选择窗口,我们在新建项目时,选择桌面Qt应用,操作如下图,在类信息选择的位置提供了,3种可以选择的窗口的基类,具体选哪一种按实际需要选择。(GIF动画,如果不能播放,请点击打开图片)

 1.gif


2.HOW
        1)QMainWindow:QMainWindow是一个为用户提供主窗口程序的类,包含一个菜单栏(menu bar)、多个工具栏(tool bars)、多个锚接部件(dock widgets)、一个状态栏(status bar)及一个中心部件(central widget),是许多应用程序的基础,主窗口通常提供一个大的中央窗口部件,以及周围菜单,工具条,和一个状态栏。QMainWindow窗口经常被继承,使得封装中央部件,菜单,工具条,状态栏等都变得很容易,当用户点击它的时候,相应的槽就会被调用。
                如文本编辑器,图片编辑器等。

3.png

 2.png

            ①菜单栏
                一个主窗口最多只有一个菜单栏。位于主窗口顶部、主窗口标题栏下面。项目创建类型如下(无ui):

4.png

                a)创建菜单栏,通过QMainWindow类的menubar()函数获取主窗口菜单栏指针:
QMenuBar *   menuBar() const
                b)新建菜单,调用QMenu的成员函数addMenu来添加菜单
QAction* addMenu(QMenu * menu)
QMenu* addMenu(const QString & title)
QMenu* addMenu(const QIcon & icon, const QString & title)
                c)创建菜单项,调用QMenu的成员函数addAction来添加菜单项
QAction* activeAction() const
QAction* addAction(const QString & text)
QAction* addAction(const QIcon & icon, const QString & text)
QAction* addAction(const QString & text, const QObject * receiver,const char * member, const QKeySequence & shortcut = 0)
QAction* addAction(const QIcon & icon, const QString & text,const QObject * receiver, const char * member,const QKeySequence & shortcut = 0)
                d)Qt 并没有专门的菜单项类,只是使用一个QAction类,抽象出公共的动作。当我们把QAction对象添加到菜单,就显示成一个菜单项,添加到工具栏,就显示成一个工具按钮。用户可以通过点击菜单项、点击工具栏按钮、点击快捷键来激活这个动作。

            ②工具栏:主窗口的工具栏上可以有多个工具条,通常采用一个菜单对应一个工具条的的方式,也可根据需要进行工具条的划分。
                a)直接调用QMainWindow类的addToolBar()函数获取主窗口的工具条对象,每增加一个工具条都需要调用一次该函数。
                b)插入属于工具条的动作,即在工具条上添加操作。通过QToolBar类的addAction函数添加。
                c)工具条是一个可移动的窗口,它的停靠区域由QToolBar的allowAreas决定,包括:
                    Qt::LeftToolBarArea          停靠在左侧
                    Qt::RightToolBarArea        停靠在右侧
                    Qt::TopToolBarArea           停靠在顶部
                    Qt::BottomToolBarArea     停靠在底部
                    Qt::AllToolBarAreas           以上四个位置都可停靠
//使用setAllowedAreas()函数指定停靠区域:
setAllowedAreas(Qt::LeftToolBarArea | Qt::RightToolBarArea)
//使用setMoveable()函数设定工具栏的可移动性:
setMoveable(false)//工具条不可移动, 只能停靠在初始化的位置上
            ③状态栏:派生自QWidget类,使用方法与QWidget类似,QStatusBar类常用成员函数:
//添加小部件
void addWidget(QWidget * widget, int stretch = 0)
//插入小部件
int insertWidget(int index, QWidget * widget, int stretch = 0)
//删除小部件
void removeWidget(QWidget * widget)
            ④完整案例
                a)视图如下(事件处理:可以根据实际项目制作):(GIF动画,如果不能播放,请点击打开图片)
5.gif
                b)代码

                      4_1_1.pro:

QT += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = WindowTest
TEMPLATE = app

DEFINES += QT_DEPRECATED_WARNINGS

SOURCES += \
main.cpp \
mainwindow.cpp

HEADERS += \
mainwindow.h

                     mainwindow.h:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

class MainWindow : public QMainWindow
{
Q_OBJECT

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

};

#endif // MAINWINDOW_H

                     main.cpp:

#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();

return a.exec();
}

                     mainwindow.cpp:

#include "mainwindow.h"

#include <QMenuBar> //菜单栏 menuBar();
#include <QMenu> //菜单栏
#include <QAction> //创建菜单栏单项
#include <QToolBar> //工具栏
#include <QStatusBar> //状态栏
#include <QDockWidget> //浮动窗口

#include <QPushButton> //控件
#include <QLabel> //控件
#include <QTextEdit> //控件
#include <QDebug> //调试输出
#define cout qDebug()

MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
this->resize(800,600);

//菜单操作---------------------------------------------------------------------
QMenuBar *myMenuBar = menuBar(); //获取主窗口菜单栏指针

QMenu *pFileMenu = myMenuBar->addMenu("文件"); //添加菜单【菜单】
QAction *pNewAciton = pFileMenu->addAction("新建"); //添加单项【菜单->新建】
connect(pNewAciton, &QAction::triggered, //信号处理【菜单->新建->事件处理】
[=]()
{
cout<< "菜单->新建->事件处理";
}
);
pFileMenu->addSeparator(); //添加分割线【菜单->新建->下方分割线】

QAction *pOpenAction = pFileMenu->addAction("打开"); //添加单项【菜单->打开】
connect(pOpenAction,&QAction::triggered,
[=]()
{
cout<<"菜单->打开->事件处理";
}
);
pFileMenu->addSeparator(); //添加分割线【菜单->打开->下方分割线】

QAction *pSave = pFileMenu->addAction("保存"); //添加单项【菜单->保存】
connect(pSave,&QAction::triggered,
[=]()
{
cout<<"菜单->保存->事件处理";
}
);

QMenu *pEditMenu = myMenuBar->addMenu("编辑"); //添加菜单【菜单】
QMenu *pViewMenu = myMenuBar->addMenu("视图"); //添加菜单【菜单】

//工具栏---------------------------------------------------------------------
QToolBar *toolBar = addToolBar("toolBar"); //添加工具栏

//工具栏添加快捷键
toolBar->addAction(pNewAciton); //新建添加到工具栏中
toolBar->addAction(pOpenAction); //打开添加到工具栏中
toolBar->addAction(pSave); //保存添加到工具栏中

//把一个按钮添加到工具栏
QPushButton *b = new QPushButton;
b->setText("其他功能");
toolBar->addWidget(b); //添加一个自定义的小控件(按钮)

connect(b, &QPushButton::clicked, //自定义控件按钮的处理函数
[=]()
{
qDebug() <<"工具栏->其他功能->事件处理其他功能响应!";
}
);


//状态栏---------------------------------------------------------------------
QStatusBar *sBar = statusBar();
QLabel *label = new QLabel(this); //创建一个标签并指定父对象
label->setText("状态栏1->这里可以输出,当前需要通知用户的信息!");
sBar->addWidget(label); //把标签添加到状态栏


sBar->addWidget(new QLabel("状态栏2", this)); //addWidget 从左往右添加
sBar->addPermanentWidget(new QLabel("状态栏3", this)); //addPermanentWidget 从右往左添加

//核心控件---------------------------------------------------------------------
QTextEdit *textEdit = new QTextEdit(this);
setCentralWidget(textEdit);
textEdit->setText("我是主要的输入区域!");

//浮动窗口---------------------------------------------------------------------
QDockWidget *dock = new QDockWidget(this);
addDockWidget(Qt::RightDockWidgetArea, dock);

//给浮动窗口添加控件
QTextEdit *textEdit1 = new QTextEdit(this);
dock->setWidget(textEdit1);
textEdit1->setText("我是浮动的输入区域!");
}

MainWindow::~MainWindow()
{

}

                    源代码压缩(解压后不能有中文路径):4_1_1_QMainWindow窗口演示.zip

            ⑤总结

                a)在使用菜单栏,工具栏,状态栏,核心窗口时,需要包含特定的头文件再能进行操作。
                b)如果是菜单栏中的单项,如果把这个单项加入到工具栏,那么点击这个按钮触发的事件和点击菜单本身的处理是同一个函数处理。(只是把菜单的按钮创建了一个快捷方式,放到了工具栏而已)

        2)QWidget对话框(QDialog,QMainWindow都继承自QWidget)
            ①QWidet类是所有用户界面对象的基类,窗口部件是用户界面的一个基本单元,它从窗口系统接收鼠标,键盘和其他消息,并在屏幕上绘制自己。一个窗口部件可以被他的父窗口或者是其他窗口挡住一部分。
            ②对话框是 GUI 程序中不可或缺的组成部分。很多不能或者不适合放入主窗口的功能组件都必须放在对话框中设置。对话框通常会是一个顶层窗口,出现在程序最上层,用于实现短期任务或者简洁的用户交互。

        3)QDialog标准对话框
            所谓标准对话框,是 Qt 内置的一系列对话框,用于简化开发。事实上,有很多对话框都是通用的,比如打开文件、设置颜色、打印设置等。这些对话框在所有程序中几乎相同,因此没有必要在每一个程序中都自己实现这么一个对话框。
            ①模态和非模态对话框
                a)模态对话框,就是会阻塞同一应用程序中其它窗口的输入。
                模态对话框很常见,比如“打开文件”功能。你可以尝试一下记事本的打开文件,当打开文件对话框出现时,我们是不能对除此对话框之外的窗口部分进行操作的。
                b)与此相反的是非模态对话框,例如查找对话框,我们可以在显示着查找对话框的同时,继续对记事本的内容进行编辑。(GIF动画,如果不能播放,请点击打开图片)

 6.gif

                c)新建一个项目类型如下,在ui上面拖放两个按钮:

 7.png

                d)完整的代码如下:

                    4_1_2.pro

QT += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = 4_1_2
TEMPLATE = app

DEFINES += QT_DEPRECATED_WARNINGS

SOURCES += \
main.cpp \
widget.cpp

HEADERS += \
widget.h

FORMS += \
widget.ui

                    widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
Q_OBJECT

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

private slots:
void on_pushButton_clicked();
void on_pushButton_2_clicked();

private:
Ui::Widget *ui;
};

#endif // WIDGET_H

                    main.cpp

#include "widget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.setWindowTitle("主要窗口");
w.show();

return a.exec();
}

                    widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include<QDialog>
#include <QDebug>

Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
this->resize(300,200);
}

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

//模态窗口
void Widget::on_pushButton_clicked()
{
QDialog dlg;
dlg.resize(200,100);
dlg.setWindowTitle("模态窗口");
dlg.exec();
qDebug()<<"模态阻塞,关闭窗口后会输出!";
}

//非模态窗口
void Widget::on_pushButton_2_clicked()
{
//QDialog * pDlg = new QDialog(this); //不要指定父对象
QDialog * pDlg = new QDialog;
pDlg->setAttribute(Qt::WA_DeleteOnClose); //对话框关闭时,自动销毁对话框
pDlg->resize(200,100);
pDlg->setWindowTitle("非模态窗口");
pDlg->show();
qDebug()<<"非模态,点击窗口后会输出!";
}

                f )注意事项:

               模态窗口,我们定义一个局部窗口即可,因为后面有了dlg.exec();阻塞了这个函数,窗体只能处理当前窗口的响应,在函数没有结束之前,窗体是存在的,且点击一次只能穿件一个窗口,如下图,当窗体关闭之后才能输出后面的字符串。(相当于时我们一个普通函数中定义了一个死循环,在死循环没有被终止之前,前面的局部变量都是存在的。)
               非模态窗口,我们定义一个局部窗口,如果上模态一样定义,不使用new,而直接创建一个窗口,运行时会发现窗口一闪而过(那是因为这个函数执行结束了,局部变量会被释放),所以必须new一个对象出来,函数执行结束了堆区变量也存在。既然是new出来的对象,那么就涉及到了释放的问题,开始的时候,我们可能会想到给他指定一个父对象,当父对象关闭的时候,子对象也会自动释放,但是问题出来了,非模态的窗口,只要点击了按钮,就会创建一个窗口,如果在父窗口没关闭,而创建了很多个非模态的窗口,虽然弹出的窗口表面上已经关闭,但是堆区的内存还是存在的并没有被释放,所以系统为我们提供了一个函数,当窗口关闭后,自动释放对应堆区的内存“pDlg->setAttribute(Qt::WA_DeleteOnClose);”。

                e)运行结果:(GIF动画,如果不能播放,请点击打开图片)

  8.gif

                    完整的代码:4_1_2_演示模态和非模态.zip

            ②标准对话框

                a)所谓标准对话框,是 Qt 内置的一系列对话框,用于简化开发。事实上,有很多对话框都是通用的,比如打开文件、设置颜色、打印设置等。这些对话框在所有程序中几乎相同,因此没有必要在每一个程序中都自己实现这么一个对话框。
类--------------------------------------------作用
QColorDialog-------------------------------选择颜色
QFileDialog----------------------------------选择文件或者目录
QFontDialog---------------------------------选择字体
QInputDialog--------------------------------允许用户输入一个值,并将其值返回
QMessageBox--------------------------------模态对话框,用于显示信息、询问问题等
QPageSetupDialog---------------------------为打印机提供纸张相关的选项
QPrintDialog----------------------------------打印机配置
QPrintPreviewDialog-------------------------打印预览
QProgressDialog-----------------------------显示操作过程
                b)创建一个基类为QMainWindow(不带界面)的项目,实现的功能是,点击菜单,弹出一个标准的窗口,获取被选中(打开)一个或多个文件的路径。

               4_1_3.pro

QT += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = 4_1_3
TEMPLATE = app
DEFINES += QT_DEPRECATED_WARNINGS
SOURCES += \
main.cpp \
mainwindow.cpp

HEADERS += \
mainwindow.h

               mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
MainWindow(QWidget *parent = 0);
~MainWindow();
};
#endif // MAINWINDOW_H
               main.cpp
#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();

return a.exec();
}

               mainwindow.cpp

#include "mainwindow.h"
#include<QMenuBar> //获取菜单栏状态
#include <QMenu> //创建菜单使用
#include <QAction> //追加菜单子项
#include<QFileDialog> //文件对话框
#include<QString>
#include <QDebug>
#define cout qDebug()

MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
this->resize(400,200); //设置窗口大小

//创建菜单
QMenuBar * pMenuBar = menuBar(); //获取菜单栏状态
QMenu * pOpenMenu = pMenuBar->addMenu("打开"); //【打开】
QAction *pOpenAciton = pOpenMenu->addAction("选择一个文件"); //【打开->选择一个文件】
QAction *pOpensAciton = pOpenMenu->addAction("选择多个文件"); //【打开->选择多个文件】

//处理菜单点击时间
connect(pOpenAciton,&QAction::triggered,
[=]()
{
//选择一个文件
QString path = QFileDialog::getOpenFileName();
cout<<"选择一个文件:"<<path;
}
);

connect(pOpensAciton,&QAction::triggered,
[=]()
{
//选择多个文件
QStringList list = QFileDialog::getOpenFileNames();
cout <<"选择多个文件:"<<list;
}
);

}

MainWindow::~MainWindow()
{

}

                c)运行结果:(GIF动画,如果不能播放,请点击打开图片)               

9.gif

                d)完整的代码:4_1_3_标准对话框延时(打开文件).zip

            ③消息对话框
                a)常用的消息对话框,F1帮助:QMessageBox
Static Public Members
void
about(QWidget *parent, const QString &title, const QString &text)
void
aboutQt(QWidget *parent, const QString &title = QString())
StandardButton
critical(QWidget *parent, const QString &title, const QString &text, StandardButtons buttons = Ok, StandardButton defaultButton = NoButton)
StandardButton
information(QWidget *parent, const QString &title, const QString &text, StandardButtons buttons = Ok, StandardButton defaultButton = NoButton)
StandardButton
question(QWidget *parent, const QString &title, const QString &text, StandardButtons buttons = StandardButtons( Yes | No ), StandardButton defaultButton = NoButton)
StandardButton
warning(QWidget *parent, const QString &title, const QString &text, StandardButtons buttons = Ok, StandardButton defaultButton = NoButton)
  • 5 static public members inherited from QWidget
  • 10 static public members inherited from QObject
                b)使用介绍
                    使用是需要包含头文件:#include <QMessageBox>  //消息对话框
                    以:QMessageBox::question(this,"question","Are you ok?",
                                                                      QMessageBox::Ok | QMessageBox::Cancel);
                    为例:
                            第一个参数为父类,一般填充this,这样就能保证QMessageBox不飞出屏幕外;
                            第二个参数为标题,需要填充一个字符串;
                            第三个参数为QMessageBox要显示的内容,需要填充一个字符串;
                            第五个和第六个参数,是QMessageBox自带的两个按钮,Ok和Cancel;
                     如果需要捕获用户点击的按钮,可以接收QMessageBox的返回值,按钮是枚举类型,我们可以使用int来接收,可以以使用auto来接收。
                c)案例,创建一个窗口,点击菜单中的按钮,弹出相应的窗口
                       4_1_4.pro
QT += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = 4_1_4
TEMPLATE = app
DEFINES += QT_DEPRECATED_WARNINGS

SOURCES += \
main.cpp \
mainwindow.cpp

HEADERS += \
mainwindow.h

FORMS += \
mainwindow.ui
                       mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
Q_OBJECT

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

private:
Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H
                       main.cpp
#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();

return a.exec();
}
                       mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMenuBar> //获取菜单状态
#include <QMenu> //菜单
#include <QAction> //子项
#include <QMessageBox> //消息对话框
#include <QDebug> //调试输出
#define cout qDebug()

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

this->resize(400,200);
this->setWindowTitle("消息对话框演示");

QMenuBar *pMenuBer = menuBar(); //获取菜单的指针
QMenu * pMenu = pMenuBer->addMenu("消息"); //【消】
QAction *pAbout = pMenu->addAction("关于"); //【消息->关于】
QAction * pQues = pMenu->addAction("问题"); //【消息->问题】

//菜单点击处理
connect(pAbout,&QAction::triggered,
[=]()
{
//关于对话框
QMessageBox::about(this,"about","关于qt");
}
);
connect(pQues,&QAction::triggered,
[=]()
{
//问题对话框
int p = QMessageBox::question(this,"question","Are you ok?",
QMessageBox::Ok | QMessageBox::Cancel);
if(p == QMessageBox::Ok)
{
cout << "p == QMessageBox::Ok";
}
else if(p == QMessageBox::Cancel)
{
cout <<"p == QMessageBox::Cancel";
}
}
);
}

MainWindow::~MainWindow()
{
delete ui;
}
                       判断用户点击的是哪个按钮,上面代码使用if判断,实际也可以用switch来判断
connect(pQues, &QAction::triggered,
[=]()
{
//问题对话框
int ret = QMessageBox::question(this,
"question", "Are you ok?",
QMessageBox::Ok | QMessageBox::Cancel);

switch(ret)
{
case QMessageBox::Ok:
qDebug() << "i am ok";
break;
case QMessageBox::Cancel:
qDebug() << "i am bad";
break;
default:
break;
}
}
);
                d)运行结果(GIF动画,如果不能播放,请点击打开图片)

 10.gif

                e)完整代码4_1_4_消息对话框测试.zip


3.WHY

            每当用户开始运行一个应用程序时,应用程序就创建并显示一个窗口;当用户操作窗口中的对象时,程序会作出相应反应。用户通过关闭一个窗口来终止一个程序的运行。
            窗口是用户界面中最重要的部分。它是屏幕上与一个应用程序相对应的矩形区域,包括框架和客户区,是用户与产生该窗口的应用程序之间的可视界面。
            程序的数据处理是靠内部代码实现,但部分数据需要用户提供,最原始的方法是弹出一个命令控制台界面让用户输入一个数据,这明显是很不明智的选择,那么我们借助窗口,可以很好的让程序和用户之前建立信息交换渠道。


/*************************************************************
*   温馨提示:
*            为了不影响文章的可读性,本站图片均不自动加水印。
*            除非注明,文章均由"永恒0852"整理发布,欢迎转载。
*            否则转载请注明本文地址:http://www.yongheng0852.com/qt/46.html
**************************************************************/

评论