首先我们先来看三大白板:
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类。