添加动作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
//mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
Q_OBJECT

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

private:
Ui::MainWindow *ui;

void open();
QAction *openAction;
};
#endif // MAINWINDOW_H


//mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMessageBox>
#include <QToolBar>

MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
/*
* tr()函数,用于QT国际化的函数,将字符串中提取出来,用于国际化
* 简要来说放置乱码情况出现
*/
setWindowTitle(tr("Main Window"));

openAction = new QAction(QIcon(":images/doc-open"),tr("&Open..."),this);//tr("&Open") 文本值前面有一个&,意味这这将成为一个快捷键 路径表示":images"从本项目的images开始检索
openAction->setShortcuts(QKeySequence::Open);
openAction->setStatusTip(tr("Open and existing file"));
connect(openAction,&QAction::triggered,this,&MainWindow::open);//串联三个动作

QMenu *file = menuBar()->addMenu(tr("&File"));
file->addAction(openAction);

QToolBar *toolBar = addToolBar(tr("&File"));
toolBar-> addAction(openAction);

statusBar();

}

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

void MainWindow::open(){
QMessageBox::information(this,tr("Information"),tr("Open"));
}

在这里插入图片描述

添加资源文件

上面示例中我们的toolbar没有图片显示,基本与背景融为一体。原因是因为我们没有配置资源文件,程序也就没办法找到那个图片进行引用。
这一步就像c#中在项目属性中添加图片类似,建立图片与程序之间的连接。
步骤:

  1. 文件->新建->AT->QT Resources File
    在这里插入图片描述
  • 我们在下方点击Add Prefix添加路径名称,也就是下面的前缀
    在这里插入图片描述
  • 点击Add Files 添加图片文件,目前支持.png 其他格式需要通过安装插件来实现,添加完成后,可以给图片一个别名。因为项目与图片之间存在引用关系,如果定义一个别名,在后面应用中如果修改项目名称,我们依旧可以正确的引用图片。最下面的语言则是为了适配国际化做的选项。填入语言将会新建一个相应语言的文件夹,系统识别后自动切换到相应路径
    在这里插入图片描述
  1. 之后我们将原有文件中路径修改为:/images/doc-test
    在这里插入图片描述

布局管理器

实现一个slider与spinbox的数据联动

设计的知识点主要是函数指针,在刚开始学习c++的时候会对这个知识点不是很熟悉。
函数指针指向某种特定类型,函数的类型由其参数及返回类型共同决定,与函数名无关,ex:

1
2
3
 int add(int left,int right);//定义函数
int(*pf)(int,int);//未初始化
pf = add;//通过赋值使得函数指针指向某具体函数

(*pf)两端的括号需要加上否则就变成一个int * 整型的函数

布局管理器类似于WPF和winForm中的Grid,StackPanel控件
代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include "mainwindow.h"

#include<QLabel>
#include<QPushButton>
#include <QApplication>
#include <QSpinBox>
#include <QSlider>
#include <QHBoxLayout>

int main(int argc, char *argv[])
{
QApplication a(argc, argv);

QWidget window;
window.setWindowTitle("Enter your age");

QSpinBox *spinBox = new QSpinBox(&window);
QSlider *slider = new QSlider(Qt::Horizontal,&window);
spinBox->setRange(0,130);
slider ->setRange(0,130);

QObject::connect(slider,&QSlider::valueChanged,spinBox,&QSpinBox::setValue);
void(QSpinBox::*spinBoxSignal)(int) = &QSpinBox::valueChanged;
QObject::connect(spinBox,spinBoxSignal,slider,&QSlider::setValue);

QHBoxLayout *layout = new QHBoxLayout;
layout -> addWidget(spinBox);
layout -> addWidget(slider);
window.setLayout(layout);


window.show();
return a.exec();
}

添加对话框

主要的函数为QDialog,通过创建函数,并在函数中创建相应控件即可达到相应的效果。如果之前接触过WPF或Winform这块应该挺好理解的。

博主在这篇课题中提到了模块对话框与非模态对话框,在QT中模态对话框是通过

1
dialog.exec();

实现,非模态则是和C#中一样通过show()实现。但是这会出现一个问题,在C#中可以通过使用showDialog()函数,让窗口一直显示,但是在QT中需要通过将QDialog放置在堆上进行运行。

这是因为,show()函数不会阻塞当前线程,对话框会显示出来,然后函数立即返回,代码继续执行。注意,dialog 是建立在栈上的,show()函数返回,MainWindow::open()函数结束,dialog 超出作用域被析构,因此对话框消失了。知道了原因就好改了,我们将 dialog 改成堆上建立,当然就没有这个问题了:

如果需要指定父窗口,只需要在初始化的时候将父窗口传入即可,当父窗口为NULL的时候,该窗口将会作为一个顶层窗口。
模态有父窗口

1
2
3
4
5
6
7
8
9

void MainWindow::open(){
//QMessageBox::information(this,tr("Information"),tr("Open"));
QDialog dialog(this);
dialog.setWindowTitle(tr("Hello ,dialog!"));
dialog.exec();
}


在这里插入图片描述

非模态窗口

1
2
3
4
5
6
7
void MainWindow::open(){
QDialog *dialog = new QDialog;
dialog->setAttribute(Qt::WA_DeleteOnClose);
dialog->setWindowTitle("Hello Dialog!");
dialog->show();
}

在这里插入图片描述

QMessageBox

QT的内置对话框大致分为以下几类:

  • QColorDialog:选择颜色;
  • QFileDialog:选择文件或者目录;
  • QFontDialog:选择字体;
  • QInputDialog:允许用户输入一个值,并将其值返回;
  • QMessageBox:模态对话框,用于显示信息、询问问题等;
  • QPageSetupDialog:为打印机提供纸张相关的选项;
  • QPrintDialog:打印机配置;
  • QPrintPreviewDialog:打印预览;
  • QProgressDialog:显示操作过程。

QMeaageBox消息提示,会含有下面几个重载:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
static int question(QWidget *parent, const QString &title,
const QString& text,
int button0, int button1 = 0, int button2 = 0);
static int question(QWidget *parent, const QString &title,
const QString& text,
const QString& button0Text,
const QString& button1Text = QString(),
const QString& button2Text = QString(),
int defaultButtonNumber = 0,
int escapeButtonNumber = -1);
inline static int question(QWidget *parent, const QString &title,
const QString& text,
StandardButton button0, StandardButton button1)
{ return question(parent, title, text, StandardButtons(button0), button1); }

我的QT是5.14.2路径是

E:\Qt\Qt5.14.2\5.14.2\mingw73_64\include\QtWidgets

这个函数如果熟悉C#的人可能会很快和我们经常使用的

Microsoft.VisualBasic.Interaction
在这里插入图片描述

这个函数联系在一起,只不过C#中的定义会比QT中要轻松许多,但是他们的效果是差不多的

下面是QT中的代码部分:

1
2
3
4
5
6
7
8
void MainWindow::open(){
//QMessageBox::information(this,tr("Information"),tr("Open"));
if(QMessageBox::Yes == QMessageBox::question(this,tr("Question"),tr("Are you OK?"),QMessageBox::Yes|QMessageBox::No|QMessageBox::Save,QMessageBox::Yes)){
QMessageBox::information(this,tr("Hmmm..."),tr("I'm glab to hear that!"));
}else{
QMessageBox::information(this,tr("Hmmm..."),tr("I'm sorry!"));
}
}

在这里插入图片描述
在这里插入图片描述

添加文件对话框

看了一段时间的博客之后发现如果之前有Winform或者是WPF的基础的话,对于目前学到的知识很容易掌握,这应该就是触类旁通的意思。
首先贴一下打开和保存的代码,通过定义文件的Mode这一步与C#的流文件模式类似,读写,读,写集中类别。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
void MainWindow::openFile(){
QString path = QFileDialog::getOpenFileName(this,tr("Open File"),".",tr("Text Files(*.txt)"));

if(!path.isEmpty()){
QFile file(path);
if(!file.open(QIODevice::ReadOnly|QIODevice::Text)){
QMessageBox::warning(this,tr("Read File"),tr("Cannot open file:\n%1").arg(path));
return;
}
QTextStream in(&file);
textEdit->setText(in.readAll());
file.close();
}else{
QMessageBox::warning(this,tr("Path"),tr("You did not select any file"));
}
}

void MainWindow::saveFile(){
QString path = QFileDialog::getSaveFileName(this,tr("&Save File"),".",tr("Text Files(*.txt"));
if(!path.isEmpty()){
QFile file(path);
if(!file.open(QIODevice::WriteOnly|QIODevice::Text)){
QMessageBox::warning(this,tr("Write File"),tr("Cannot save file:\n%1").arg(path));
return;
}
QTextStream out(&file);
out<<textEdit->toPlainText();
file.close();
}else{
QMessageBox::warning(this,tr("Path"),tr("You did not select any file"));
}
}

之后我们需要在主窗口界面创建打开动作与保存动作,并使用连接器连接起来,之后创建一个文本编辑器QT里面叫做TextEditWinform或是WPF中叫做TextBox,这里有个参数SetCentralWidgrt可以将窗口放到父窗口的中心位置。 如果刚接触C++的人照着写可能会出错,因为没有在头文件中定义saveFile和TextEdit的指针,还需要再头文件中加入这两个参数才可以。
关于OPenFile函数,解释引用博主的材料

在openFile()函数中,我们使用QFileDialog::getOpenFileName()来获取需要打开的文件的路径。这个函数具有一个长长的签名:

1
2
3
4
5
6
     QString getOpenFileName(QWidget * parent = 0,
const QString & caption = QString(),
const QString & dir = QString(),
const QString & filter = QString(),
QString * selectedFilter = 0,
Options options = 0)

不过注意,它的所有参数都是可选的,因此在一定程度上说,这个函数也是简单的。这六个参数分别>是:

parent:父窗口。我们前面介绍过,Qt 的标准对话框提供静态函数,用于返回一个模态对话框(在一定程度上这就是外观模式的一种体现);
caption:对话框标题;
dir:对话框打开时的默认目录,“.” 代表程序运行目录,“/” 代表当前盘符的根目录(特指 Windows 平台;Linux 平台当然就是根目录),这个参数也可以是平台相关的,比如“C:\”等;
filter:过滤器。我们使用文件对话框可以浏览很多类型的文件,但是,很多时候我们仅希望打开特定类型的文件。比如,文本编辑器希望打开文本文件,图片浏览器希望打开图片文件。过滤器就是用于过滤特定的后缀名。如果我们使用“Image Files(.jpg .png)”,则只能显示后缀名是 jpg 或者 png 的文件。如果需要多个过滤器,使用“;;”分割,比如“JPEG Files(.jpg);;PNG Files(.png)”;
selectedFilter:默认选择的过滤器;
options:对话框的一些参数设定,比如只显示文件夹等等,它的取值是enum QFileDialog::Option,每个选项可以使用 | 运算组合起来。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# mainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QTextEdit>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
Q_OBJECT

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

private:
Ui::MainWindow *ui;

void open();
void openFile();
void saveFile();
QAction *openAction;
QAction *saveAction;
QTextEdit *textEdit;
};
#endif // MAINWINDOW_H

//MainWinodw.cpp
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
/*
* tr()函数,用于QT国际化的函数,将字符串中提取出来,用于国际化
* 简要来说放置乱码情况出现
*/
setWindowTitle(tr("Main Window"));

openAction = new QAction(QIcon(":images/doc-test"),tr("&Open..."),this);//tr("&Open") 文本值前面有一个&,意味这这将成为一个快捷键
openAction->setShortcuts(QKeySequence::Open);
openAction->setStatusTip(tr("Open and existing file"));
//connect(openAction,&QAction::triggered,this,&MainWindow::open);//串联三个动作

saveAction = new QAction(QIcon(":images/doc-test"),tr("&Save..."),this);
saveAction->setShortcuts(QKeySequence::Save);
saveAction->setStatusTip(tr("Save as a new file"));

connect(openAction,&QAction::triggered,this,&MainWindow::openFile);
connect(saveAction,&QAction::triggered,this,&MainWindow::saveFile);


QMenu *file = menuBar()->addMenu(tr("&File"));
file->addAction(openAction);
file->addAction(saveAction);

QToolBar *toolBar = addToolBar(tr("&File"));
toolBar-> addAction(openAction);
toolBar->addAction(saveAction);



textEdit = new QTextEdit(this);
setCentralWidget(textEdit);



statusBar();

}

//main.cpp
#include "mainwindow.h"

#include<QLabel>
#include<QPushButton>
#include <QApplication>
#include <QSpinBox>
#include <QSlider>
#include <QHBoxLayout>
#include "newspaper.h"
#include "reader.h"

int main(int argc, char *argv[])
{
// QCoreApplication app(argc,argv);
// Newspaper newspaper("NewsPaper A");

// Reader reader;

// QObject::connect(&newspaper,&Newspaper::newPaper,&reader,&Reader::receriveNewpaper);
// newspaper.send();
/*
* 控制MainWinodow.cpp中控件显示
*/
QApplication app(argc,argv);

MainWindow mainWindow;
mainWindow.show();
return app.exec();
}

事件

Event,语法和c#类似,只是写的形式会出现区别。通过调用事件绑定操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#event.h
#ifndef EVENT_H
#define EVENT_H

#endif // EVENT_H

#include <QLabel>

class EventLabel:public QLabel{
protected:
void mouseMoveEvent(QMouseEvent *ev) ;
void mousePressEvent(QMouseEvent *ev) ;
void mouseReleaseEvent(QMouseEvent *ev) ;
};
#main.cpp


#include "mainwindow.h"

#include<QLabel>
#include<QPushButton>
#include <QApplication>
#include <QSpinBox>
#include <QSlider>
#include <QHBoxLayout>
#include <QString>
#include "newspaper.h"
#include "event.h"
#include "reader.h"
#include <QMouseEvent>


int main(int argc, char *argv[])
{
// QCoreApplication app(argc,argv);
// Newspaper newspaper("NewsPaper A");

// Reader reader;

// QObject::connect(&newspaper,&Newspaper::newPaper,&reader,&Reader::receriveNewpaper);
// newspaper.send();
/*
* 控制MainWinodow.cpp中控件显示
*/

QApplication app(argc,argv);

// MainWindow mainWindow;
// mainWindow.show();
EventLabel *label = new EventLabel;
label->setWindowTitle("MouseEvent Demo");
label->resize(300,200);
label->show();
return app.exec();
}

void EventLabel::mouseMoveEvent(QMouseEvent *ev){
this->setText(QString("<center><h1>Move: (%1,%2)</h1></center>")
.arg(QString::number(ev->x()),QString::number(ev->y())));

}

void EventLabel::mousePressEvent(QMouseEvent *ev){
this->setText(QString("<center><h1>Press: (%1,%2)</h1></center>")
.arg(QString::number(ev->x()),QString::number(ev->y())));
}

void EventLabel::mouseReleaseEvent(QMouseEvent *ev){
QString msg;
msg.sprintf("<center><h1>Relase: (%d,%d)</h1></center>",ev->x(),ev->y());
this->setText(msg);
}