//mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include
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
#include
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#中在项目属性中添加图片类似,建立图片与程序之间的连接。
步骤:
Add Prefix
添加路径名称,也就是下面的前缀Add Files
添加图片文件,目前支持.png 其他格式需要通过安装插件来实现,添加完成后,可以给图片一个别名。因为项目与图片之间存在引用关系,如果定义一个别名,在后面应用中如果修改项目名称,我们依旧可以正确的引用图片。最下面的语言则是为了适配国际化做的选项。填入语言将会新建一个相应语言的文件夹,系统识别后自动切换到相应路径实现一个slider与spinbox的数据联动
设计的知识点主要是函数指针,在刚开始学习c++的时候会对这个知识点不是很熟悉。
函数指针指向某种特定类型,函数的类型由其参数及返回类型共同决定,与函数名无关,ex:
int add(int left,int right);//定义函数
int(*pf)(int,int);//未初始化
pf = add;//通过赋值使得函数指针指向某具体函数
(*pf)两端的括号需要加上否则就变成一个int * 整型的函数
布局管理器类似于WPF和winForm中的Grid,StackPanel控件
代码:
#include "mainwindow.h"
#include
#include
#include
#include
#include
#include
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中模态对话框是通过
dialog.exec();
实现,非模态则是和C#中一样通过show()实现。但是这会出现一个问题,在C#中可以通过使用showDialog()函数,让窗口一直显示,但是在QT中需要通过将QDialog
放置在堆上进行运行。
这是因为,show()函数不会阻塞当前线程,对话框会显示出来,然后函数立即返回,代码继续执行。注意,dialog 是建立在栈上的,show()函数返回,MainWindow::open()函数结束,dialog 超出作用域被析构,因此对话框消失了。知道了原因就好改了,我们将 dialog 改成堆上建立,当然就没有这个问题了:
如果需要指定父窗口,只需要在初始化的时候将父窗口传入即可,当父窗口为NULL的时候,该窗口将会作为一个顶层窗口。
模态有父窗口
void MainWindow::open(){
//QMessageBox::information(this,tr("Information"),tr("Open"));
QDialog dialog(this);
dialog.setWindowTitle(tr("Hello ,dialog!"));
dialog.exec();
}
非模态窗口
void MainWindow::open(){
QDialog *dialog = new QDialog;
dialog->setAttribute(Qt::WA_DeleteOnClose);
dialog->setWindowTitle("Hello Dialog!");
dialog->show();
}
QT的内置对话框大致分为以下几类:
QMeaageBox消息提示,会含有下面几个重载:
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#的人可能会很快和我们经常使用的
这个函数联系在一起,只不过C#中的定义会比QT中要轻松许多,但是他们的效果是差不多的
下面是QT中的代码部分:
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#的流文件模式类似,读写,读,写集中类别。
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<toPlainText();
file.close();
}else{
QMessageBox::warning(this,tr("Path"),tr("You did not select any file"));
}
}
之后我们需要在主窗口界面创建打开动作与保存动作,并使用连接器连接起来,之后创建一个文本编辑器QT里面叫做TextEdit
Winform或是WPF中叫做TextBox
,这里有个参数SetCentralWidgrt
可以将窗口放到父窗口的中心位置。 如果刚接触C++的人照着写可能会出错,因为没有在头文件中定义saveFile和TextEdit的指针,还需要再头文件中加入这两个参数才可以。
关于OPenFile函数,解释引用博主的材料
在openFile()函数中,我们使用QFileDialog::getOpenFileName()来获取需要打开的文件的路径。这个函数具有一个长长的签名:
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,每个选项可以使用 | 运算组合起来。
# mainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include
#include
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
#include
#include
#include
#include
#include
#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#类似,只是写的形式会出现区别。通过调用事件绑定操作。
#event.h
#ifndef EVENT_H
#define EVENT_H
#endif // EVENT_H
#include
class EventLabel:public QLabel{
protected:
void mouseMoveEvent(QMouseEvent *ev) ;
void mousePressEvent(QMouseEvent *ev) ;
void mouseReleaseEvent(QMouseEvent *ev) ;
};
#main.cpp
#include "mainwindow.h"
#include
#include
#include
#include
#include
#include
#include
#include "newspaper.h"
#include "event.h"
#include "reader.h"
#include
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("Move: (%1,%2)
")
.arg(QString::number(ev->x()),QString::number(ev->y())));
}
void EventLabel::mousePressEvent(QMouseEvent *ev){
this->setText(QString("Press: (%1,%2)
")
.arg(QString::number(ev->x()),QString::number(ev->y())));
}
void EventLabel::mouseReleaseEvent(QMouseEvent *ev){
QString msg;
msg.sprintf("Relase: (%d,%d)
",ev->x(),ev->y());
this->setText(msg);
}