添加动作 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 #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 #include "mainwindow.h" #include "ui_mainwindow.h" #include <QMessageBox> #include <QToolBar> MainWindow::MainWindow (QWidget *parent) : QMainWindow (parent) , ui (new Ui::MainWindow) { ui->setupUi (this ); setWindowTitle (tr ("Main Window" )); openAction = new QAction (QIcon (":images/doc-open" ),tr ("&Open..." ),this ); 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#中在项目属性中添加图片类似,建立图片与程序之间的连接。步骤:
文件->新建->AT->QT Resources File
我们在下方点击Add Prefix添加路径名称,也就是下面的前缀
点击Add Files 添加图片文件,目前支持.png 其他格式需要通过安装插件来实现,添加完成后,可以给图片一个别名。因为项目与图片之间存在引用关系,如果定义一个别名,在后面应用中如果修改项目名称,我们依旧可以正确的引用图片。 最下面的语言则是为了适配国际化做的选项。填入语言将会新建一个相应语言的文件夹,系统识别后自动切换到相应路径
之后我们将原有文件中路径修改为:/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中模态对话框是通过
实现,非模态则是和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 () { 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 () { 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::MainWindow (QWidget *parent) : QMainWindow (parent) , ui (new Ui::MainWindow) { ui->setupUi (this ); setWindowTitle (tr ("Main Window" )); openAction = new QAction (QIcon (":images/doc-test" ),tr ("&Open..." ),this ); openAction->setShortcuts (QKeySequence::Open); openAction->setStatusTip (tr ("Open and existing file" )); 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 (); } #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[]) { 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 #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[]) { QApplication app (argc,argv) ; 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); }