首先我们先来看三大白板:
1.widget (小部件): widget主要是在上面放置布局控件
2.dialog (对话框): dialog有exec函数,如果是dialog窗口,后面的窗口是不能选取的
3.mainwindow (主窗口):可以显示菜单,工具栏,状态栏,托盘等功能
tips:
(1.widget和dialog都有show函数,如果通过这个函数显示这两种类型的窗口,则两个窗口都是可选的
(2.mainwindow和widget的主要区别就是能不能直接创建菜单栏等几种行为(注意:widget也可以只是要自己去定义实现,mainwidow是直接就有)
(3.dialog和mainwindow两者之间没有直接关系
一.widget
QWidgt 类是所有用户界面对象的基类。 窗口部件是用户界面的一个基本单元:它从窗 口系统接收鼠标、键盘和其它事件,并且在屏幕上绘制自己。每一个窗口部件都是矩形的, 并且它们按 Z 轴顺序排列。一个窗口部件可以被它的父窗口部件或者它前面的窗口部件盖住 一部分。
二.dialog
QDialog 类是对话框窗口的基类。对话框窗口是主要用于短期任务以及和用户进行简要 通讯的顶级窗口。QDialog 可以是模态对话框也可以是非模态对话框。QDialog 支持扩展性并 且可以提供返回值。它们可以有默认按钮。
例子1:
mydialog.h
#ifndef MYQDIALOG_H #define MYQDIALOG_H #include <QDialog> #include <QPushButton> class myQDialog : public QDialog { Q_OBJECT //申明当前类支持信号与槽机制,QT c++特有语法 public: myQDialog(QWidget *parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags()); private: QPushButton *bt; }; #endif // MYQDIALOG_H
widget.h
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> class Widget : public QWidget { Q_OBJECT public: Widget(QWidget *parent = 0); ~Widget(); }; #endif // WIDGET_H
.cpp
#include "myqdialog.h" myQDialog::myQDialog(QWidget *parent, Qt::WindowFlags f) :QDialog(parent, f) { bt = new QPushButton("登录"); bt->setParent(this); bt->setGeometry(150, 100, 100, 50); connect(bt, SIGNAL(clicked(bool)), this, SLOT(close())); }
.cpp
#include "widget.h" #include <QWidget> #include <QDialog> #include "myqdialog.h" Widget::Widget(QWidget *parent) : QWidget(parent) { // QWidget *w = new QWidget; // w->setFixedSize(300, 200); // w->show(); myQDialog *w = new myQDialog; w->setFixedSize(300, 200); w->exec(); //模态显示: 比show()高级 } Widget::~Widget() { }
必须点击第一个才能显示出第二个
例子2:
widget.h
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include <QPushButton> #include <QTextEdit> #include <QColorDialog> #include <QErrorMessage> #include <QFileDialog> #include <QFontDialog> #include <QInputDialog> #include <QMessageBox> #include <QProgressDialog> class Widget : public QWidget { Q_OBJECT public slots: void get_font(); void get_color(); void get_filepath(); void get_input(); void show_msg(); void show_errmsg(); void show_progress(); public: Widget(QWidget *parent = 0); ~Widget(); private: QPushButton *bt_color; QPushButton *bt_errmsg; QPushButton *bt_file; QPushButton *bt_font; QPushButton *bt_input; QPushButton *bt_msg; QPushButton *bt_progress; QTextEdit *te; }; #endif // WIDGET_H
.cpp
#include "widget.h" #include <QVBoxLayout> #include <QHBoxLayout> #include <QDebug> Widget::Widget(QWidget *parent) : QWidget(parent) { bt_color = new QPushButton("颜色"); bt_errmsg = new QPushButton("错误消息"); bt_file = new QPushButton("文件路径选择"); bt_font = new QPushButton("字体选择"); bt_input = new QPushButton("输入框"); bt_msg = new QPushButton("消息"); bt_progress = new QPushButton("进度"); QVBoxLayout *vbox = new QVBoxLayout; vbox->addWidget(bt_color); vbox->addWidget(bt_errmsg); vbox->addWidget(bt_file); vbox->addWidget(bt_font); vbox->addWidget(bt_input); vbox->addWidget(bt_msg); vbox->addWidget(bt_progress); te = new QTextEdit; QHBoxLayout *hbox = new QHBoxLayout; hbox->addLayout(vbox); hbox->addWidget(te); setLayout(hbox); connect(bt_font, &QPushButton::clicked, this, &Widget::get_font); connect(bt_color, &QPushButton::clicked, this, &Widget::get_color); connect(bt_file, SIGNAL(clicked(bool)), this, SLOT(get_filepath())); connect(bt_input, SIGNAL(clicked(bool)), this, SLOT(get_input())); connect(bt_msg, SIGNAL(clicked(bool)), this, SLOT(show_msg())); connect(bt_errmsg, SIGNAL(clicked(bool)), this, SLOT(show_errmsg())); connect(bt_progress, SIGNAL(clicked(bool)), this, SLOT(show_progress())); } void Widget::show_msg() { QMessageBox msgBox; msgBox.setText("The document has been modified."); msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel); qDebug() << msgBox.exec(); } void Widget::show_errmsg() { QErrorMessage emg; //TODO emg.showMessage("aaaaaaaaaaaaaaaaaaaaaa"); emg.exec(); } void Widget::show_progress() { QProgressDialog progress("正在下载", "取消", 0, 100); progress.setValue(60); progress.exec(); } void Widget::get_input() { QString name = QInputDialog::getText(this, "xxx", "你的名字"); te->append(name); } void Widget::get_filepath() { //QString filepath = QFileDialog::getOpenFileName(); //弹出一个文件选择对话框,并且返回文件路径 QStringList filepaths = QFileDialog::getOpenFileNames(this, "打开文件", "C://Users//ThinkPad T490//Desktop", "Images (*.png *.bmp *.jpg)"); //弹出一个文件选择对话框,并且返回一堆文件路径 for(int i=0; i<filepaths.length(); i++) te->append(filepaths[i]); } void Widget::get_color() { QColor color = QColorDialog::getColor(); //弹出一个颜色对话框,并且返回用户选择的颜色 te->setTextColor(color); } void Widget::get_font() { // QFontDialog *d = new QFontDialog; // d->exec(); bool ok; QFont font = QFontDialog::getFont(&ok); //弹出字体对话框,并且界面消失的时候反馈用户选择的字体 if(ok) { //te->setFont(font); //设置整个文本框的字体 te->setCurrentFont(font); //设置被选中的文字的字体 } } Widget::~Widget() { }
效果:
三.mainwindow
QMainWindow 类提供一个有菜单条、锚接窗口(例如工具条)和一个状态条的主应用程序窗口。主窗口通常用在提供一个大的中央窗口部件(例如文本编辑或者绘制画布)以及周围菜单、工具条和一个状态条。QMainWindow 常常被继承,因为这使得封装中央部件、菜单和工具条以及窗口状态条变得更容易,当用户点击菜单项或者工 具条按钮时,槽会被调用。
例子实现简单的文件编辑器:
.h
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <QTextEdit> #include <QLabel> class MainWindow : public QMainWindow { Q_OBJECT public slots: void new_file(); void open_file(); void save_file(); void saveas_file(); void close_file(); void set_font(); void set_color(); public: MainWindow(QWidget *parent = 0); ~MainWindow(); private: QTextEdit *te; QLabel *lb; }; #endif // MAINWINDOW_H
.cpp
#include "mainwindow.h" #include <QMenu> #include <QMenuBar> #include <QDebug> #include <QToolBar> #include <QToolButton> #include <QStatusBar> #include <QFontDialog> #include <QFileDialog> #include <QFile> #include <QMessageBox> #include <QColorDialog> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { //0. 构造所有的action QAction *new_action = new QAction(QIcon(":/img/new.png"), "新建"); new_action->setShortcut(QKeySequence("Ctrl+N")); connect(new_action, SIGNAL(triggered(bool)), this, SLOT(new_file())); QAction *open_action = new QAction(QIcon(":/img/open.png"), "打开"); open_action->setShortcut(QKeySequence("Ctrl+O")); connect(open_action, SIGNAL(triggered(bool)), this, SLOT(open_file())); //open_action->setEnabled(false); QAction *saveas_action = new QAction(QIcon(":/img/saveas.png"), "另存为"); saveas_action->setShortcut(QKeySequence("Ctrl+Y")); connect(saveas_action, SIGNAL(triggered(bool)), this, SLOT(saveas_file())); QAction *save_action = new QAction(QIcon(":/img/save.png"), "保存"); save_action->setShortcut(QKeySequence("Ctrl+s")); connect(save_action, SIGNAL(triggered(bool)), this, SLOT(save_file())); QAction *close_action = new QAction(QIcon(":/img/close.png"), "保存"); close_action->setShortcut(QKeySequence("Ctrl+X")); connect(close_action, SIGNAL(triggered(bool)), this, SLOT(close_file())); QAction *font_action = new QAction(QIcon(":/img/font.png"), "字体"); font_action->setShortcut(QKeySequence("Ctrl+f")); connect(font_action, SIGNAL(triggered(bool)), this, SLOT(set_font())); QAction *color_action = new QAction(QIcon(":/img/color.png"), "颜色"); color_action->setShortcut(QKeySequence("Ctrl+f")); connect(color_action, SIGNAL(triggered(bool)), this, SLOT(set_color())); //1. 获取菜单栏menuBar(),添加菜单->addMenu,添加选项 QMenu *fileMenu = menuBar()->addMenu("&File"); //&F: 用键盘Alt+f fileMenu->addAction(new_action); fileMenu->addAction(open_action); fileMenu->addAction(save_action); fileMenu->addAction(saveas_action); fileMenu->addAction(close_action); QMenu *editMenu = menuBar()->addMenu("&Edit"); //&E: 用键盘Alt+e editMenu->addAction(font_action); editMenu->addAction(color_action); //2. 工具栏 QToolBar *filetoolbar = addToolBar("file"); //添加一个工具栏,并且放入常用的action filetoolbar->addAction(new_action); filetoolbar->addAction(open_action); filetoolbar->addAction(save_action); filetoolbar->addAction(saveas_action); filetoolbar->addAction(close_action); QToolBar *edittoolbar = addToolBar("edit"); //添加一个工具栏,并且放入常用的action edittoolbar->addAction(font_action); edittoolbar->addAction(color_action); QToolBar *xxxtoolbar = addToolBar("编译"); //添加一个工具栏,并且放入常用的action QToolButton *tb = new QToolButton; tb->setText("编译"); xxxtoolbar->addWidget(tb); // tb->setDisabled(true); // tb->setEnabled(false); //3. 设置中央部件 te = new QTextEdit; te->setMinimumSize(640, 480); this->setCentralWidget(te); te->setDisabled(true); //4. 状态栏 lb = new QLabel; QStatusBar *st = statusBar(); st->addWidget(lb); connect(te, &QTextEdit::textChanged, [&]{ if(!lb->text().contains('*')) lb->setText(lb->text()+'*'); }); } void MainWindow::set_font() { qDebug() << "set font........"; bool ok; QFont font = QFontDialog::getFont(&ok); if(ok) te->setCurrentFont(font); } void MainWindow::set_color() { qDebug() << "set color........"; QColor color = QColorDialog::getColor(); te->setTextColor(color); } void MainWindow::new_file() { qDebug() << "new........"; te->setEnabled(true); if(lb->text().contains('*')) //有文件在编辑中 { close_file(); } else { //清除工作区 te->clear(); lb->clear(); } } void MainWindow::open_file() { qDebug() << "open........"; te->setEnabled(true); //1. 提取文件路径 QString path = QFileDialog::getOpenFileName(); //2. 提取出文件内容 QFile QFile f(path); f.open(QIODevice::ReadOnly); QByteArray buf = f.readAll(); f.close(); //3. 将内容显示在文本编辑框 te->setText(buf); //4. 显示文件路径在状态栏 lb->setText(path); } void MainWindow::save_file() { //1. 提取文件路径 QString str = lb->text(); if(!str.contains('*')) //如果文件未有改动 return; str.chop(1); if(str.isEmpty()) //这是一个新建的文件 { saveas_file(); return; } //2. 提取文本编辑框的内容 QString buf = te->toPlainText(); //3. 将内容写入文件 QFile f(str); f.open(QIODevice::WriteOnly); f.write(buf.toStdString().c_str()); f.close(); //4. 更新状态栏 lb->setText(str); } void MainWindow::saveas_file() { //1. 提取文件路径 QString str = QFileDialog::getSaveFileName(); if(str.isEmpty()) return; //2. 提取文本编辑框的内容 QString buf = te->toPlainText(); //3. 将内容写入文件 QFile f(str); f.open(QIODevice::WriteOnly); f.write(buf.toStdString().c_str()); f.close(); //3. 更新状态栏 lb->setText(str); } void MainWindow::close_file() { qDebug() << "close........"; if(lb->text().contains('*')) //有文件被编辑中 { //1. 弹框提示是否需要保存 QMessageBox msgBox; msgBox.setText("The document has been modified."); msgBox.setInformativeText("Do you want to save your changes?"); msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel); msgBox.setDefaultButton(QMessageBox::Save); int ret = msgBox.exec(); //2. 如果要保存 if(QMessageBox::Save == ret) save_file(); else if(QMessageBox::Cancel == ret) return; } //清除工作区 te->clear(); lb->clear(); } MainWindow::~MainWindow() { }
效果:
用的时候怎么选择?
窗口类型介绍:QMainWindow、QWidget、QDialog三个类都可以用来创建窗口,可以直接使用,也可以继承后使用。
1.如果是主窗口,就使用QMainWindow类;
2.如果是对话框,就使用QDialog类;
3.如果不确定,有可能作为顶层窗口,也有可能嵌入到其他窗口,就使用QWidget类。