Qt6开发入门-环境配置与入门 安装 在线安装包可以去官网找,也可以这里下载:https://mirrors.nju.edu.cn/qt/official_releases/online_installers/ ,但提前需要在Qt官网注册账户。下载需要换源,命令如下:
1 qt-online-installer-windows-x64-4.9.0.exe --mirror https://mirror.nju.edu.cn/qt
安装时选择“个人使用”、“自定义安装”。建议选择安装目前最高版本的Qt6下的MSVC 2022 64-bit和MinGW 13.1.0 64-bit套件,选中Sources、全部Additional Libraries和Qt Debug Information Files。Build Tools中选择Qt对应的MinGW版本、Qt Installer Framework、CMake、Ninja和全部OpenSSL Toolkit。Qt Creator中建议选中Qt Creator、CDB Debugger Support、Debugging Tools for Windows、Debug Symbols和Plugin Development。大约总共需要30GB空间。
为Visual Studio 2022安装扩展“Qt Visual Studio Tools”,重启并选择“扩展”->“Qt VS Tools”->“Options”,在“Qt”->“Versions”中找qmake.exe。新建项目“Qt Widgets Application”,即可开始开发。要注意项目中的“符合模式”选项必须开启,否则编译不通过。Qt Designer在VS2022中的内嵌模式支持非常不好,有时能打开有时打不开,可删掉Qt Designer选项自己新建一个编辑器。
也可以使用Qt Creator新建项目,用Qt Creator打开项目时选择CMakeLists.txt,然后编译即可。编辑UI界面可用Qt Creator打开.ui文件,其编译后对应的文件在build目录对应编译模式文件夹下的\xxx_autogen\include\ui_mainwindow.h。
Qt也可部署在Linux上,但若缺少桌面系统,会缺少几个必要的链接库,缺啥补啥即可。
Windows上Qt打包可尝试windeployqt。
入门 程序结构 主程序文件main.cpp内容为:
1 2 3 4 5 6 7 8 #include "mainwindow.h" #include <QApplication> int main (int argc,char *argv[]) { QApplication a (argc,argv) ; MainWindow w; w.show (); return a.exec (); };
窗口源程序mainwindow.cpp:
1 2 3 4 5 6 7 8 #include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow (QWidget *parent):QMainWindow (parent),ui (new Ui::MainWindow){ ui->setupUi (this ); }; MainWindow::~MainWindow (){ delete ui; };
窗口类定义头文件mainwindow.h:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #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; }; #endif
例如拖拽一个Push Button,右键“转到槽…”可编写内容。也可直接设计器下方Signals and Slots Editor窗口中添加一条,发送者选择pushButton,信号选择clicked,接收者选择MainWindows,槽选择close。
在ui_mainwindow.h中:
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 #ifndef UI_MAINWINDOW_H #define UI_MAINWINDOW_H #include <QtCore/QVariant> #include <QtWidgets/QApplication> #include <QtWidgets/QLabel> #include <QtWidgets/QMainWindow> #include <QtWidgets/QMenuBar> #include <QtWidgets/QPushButton> #include <QtWidgets/QStatusBar> #include <QtWidgets/QWidget> QT_BEGIN_NAMESPACE class Ui_MainWindow { public : QWidget *centralwidget; QLabel *label; QPushButton *pushButton; QMenuBar *menubar; QStatusBar *statusbar; void setupUi (QMainWindow *MainWindow) { if (MainWindow->objectName ().isEmpty ()) MainWindow->setObjectName ("MainWindow" ); MainWindow->resize (800 ,600 ); centralwidget=new QWidget (MainWindow); centralwidget->setObjectName ("centralwidget" ); label=new QLabel (centralwidget); label->setObjectName ("label" ); label->setGeometry (QRect (130 ,140 ,411 ,181 )); QFont font; font.setPointSize (20 ); label->setFont (font); pushButton=new QPushButton (centralwidget); pushButton->setObjectName ("pushButton" ); pushButton->setGeometry (QRect (360 ,340 ,92 ,28 )); MainWindow->setCentralWidget (centralwidget); menubar=new QMenuBar (MainWindow); menubar->setObjectName ("menubar" ); menubar->setGeometry (QRect (0 ,0 ,800 ,47 )); menubar->setFont (font); MainWindow->setMenuBar (menubar); statusbar=new QStatusBar (MainWindow); statusbar->setObjectName ("statusbar" ); MainWindow->setStatusBar (statusbar); retranslateUi (MainWindow); QObject::connect (pushButton,&QPushButton::clicked,MainWindow,qOverload<>(&QMainWindow::close)); QMetaObject::connectSlotsByName (MainWindow); }; void retranslateUi (QMainWindow *MainWindow) { MainWindow->setWindowTitle (QCoreApplication::translate ("MainWindow" ,"MainWindow" ,nullptr )); label->setText (QCoreApplication::translate ("MainWindow" ,"TextLabel" ,nullptr )); pushButton->setText (QCoreApplication::translate ("MainWindow" ,"PushButton" ,nullptr )); }; }; namespace Ui{ class MainWindow :public Ui_MainWindow{}; }; QT_END_NAMESPACE #endif
Ui::MainWindow ui可访问窗口界面上所有组件,例如:
1 2 3 4 5 6 MainWindow::MainWindow (QWidget *parent):QMainWindow (parent),ui (new Ui::MainWindow) { ui->setupUi (this ); ui->label->setText ("Qt6" ); ui->pushButton->setText ("关闭" ); return ; };
在项目管理器中的子项目上右键添加新文件,类型选择Qt类的Qt Resource File,选择要添加到的子项目。添加一个资源前需要先添加一个前缀,例如icon等,在每个前缀下面添加文件,例如可在项目目录下新建一个images目录,下面放所有图片。
例如可以将若干Check Box放入一个Group Box中,在右侧对象查看器中能够看到层次。Qt Creator上方有几个小按钮:编辑控件、编辑信号/槽、编辑伙伴、编辑Tab顺序,此外控件中还有各种Layout和Spacer可尝试。例如在编辑伙伴视图中,点击某个Label并拖拽到某Line Edit控件上,形成伙伴关系,再例如将Label的text属性设为“姓名(&N)”,此时“&”将不显示,意为快捷键为Alt+N,按下后焦点将转向其伙伴控件,即Line Edit控件。
信号与槽初探 信号是在特定情况下被发射的通知,槽是对信号进行相应的函数。信号与槽的管理用QObject::connect实现,QObject是大部分Qt类的基类,一般可忽略。一个信号可连接多个槽,槽函数按照建立连接时的顺序依次运行。信号和槽函数带有参数时,要指明各参数类型,不用指明参数名称。多个信号可连接同一个槽函数,一个信号也可连接到另一个信号,信号与槽的参数个数和类型要一致。使用信号与槽的类中,必须在类的定义中插入宏Q_OBJECT。某参数不用时可用Q_UNUSED宏标记。
1 QObject::connect (sender,SIGNAL (signal ()),receiver,SLOT (slot ()));
一种常用的使用示例:
1 connect (ui->spinNum,SIGNAL (valueChanged (int )),this ,SLOT (addFun (int )));
例如拖入一个Check Box,右键转到槽选择clicked(bool)信号,在mainwindow.cpp中自动出现以下函数,并自行添加内容:
1 2 3 4 5 6 void MainWindow::on_checkBox_3_clicked (bool checked) { QFont font=ui->checkBox_3->font (); font.setUnderline (checked); ui->checkBox_3->setFont (font); return ; };
翻看ui_mainwindow.h中的setupUi函数,出现以下内容,表示搜索MainWindow界面所有组件,将名称匹配的信号和槽关联起来。
1 QMetaObject::connectSlotsByName (MainWindow);
相当于:
1 connect (chkBoxUnder,SIGNAL (clicked (bool )),this ,SLOT (on_chkBoxUnder_clicked (bool )));
其中,槽函数命名格式为:
1 void on_<对象名>_<信号名>(<信号参数>);
将几个Radio Button放入同一个Group Box等容器中,自动改为互斥的。此时要为所有Radio Button连接到一个槽函数上,选择在mainwindow.h的MainWindow类的private slots部分手动添加下面定义,其中以do开头的槽函数一般认为时自定义槽函数。
1 void do_setFontColor (void ) ;
在函数名上右键重构,选择在mainwindow.cpp中添加定义,并添加具体代码:
1 2 3 4 5 6 7 8 9 void MainWindow::do_setFontColor (void ) { QPalette plet=ui->label->palette (); if (ui->radioButton->isChecked ()) plet.setColor (QPalette::Text,Qt::blue); else plet.setColor (QPalette::Text,Qt::red); ui->label->setPalette (plet); return ; };
然后得自己关联:
1 2 3 4 5 6 7 MainWindow::MainWindow (QWidget *parent):QMainWindow (parent),ui (new Ui::MainWindow){ ui->setupUi (this ); QObject::connect (ui->radioButton,SIGNAL (clicked ()),this ,SLOT (do_setFontColor ())); QObject::connect (ui->radioButton_2,SIGNAL (clicked ()),this ,SLOT (do_setFontColor ())); return ; };
为了给可执行文件添加图标,将图标.ico文件放在项目根目录下,新建xxx.rc文件,记事本打开添加文本:
1 IDI_ICON1 ICON "文件名.ico"
然后在CMakeLists.txt中添加:
1 2 3 4 5 qt_add_executable(qttest2 WIN32 MACOSX_BUNDLE ... xxx.rc )
Qt对标准C++语言进行了扩展,引入了元对象系统MOS,所有从QObject继承的类都可利用MOS提供的功能。MOS支持属性、信号与槽、动态类型等特性。构建项目时,项目中头文件先被MOS预编译,可视化设计的窗口UI文件被用户界面编译器UIC转为一个C++源程序文件,.qrc资源文件会被资源编译器RCC转换为C++程序文件。用MOS、UIC、RCC编译各原始文件的过程称为预编译过程,生成标准C++语言的程序文件,被标准C++编译器编译和连接,生成可执行文件。
CMake文件 CMakeLists.txt内容如下,一般不需要自行修改,只有用到Qt某些附加模块时需要改动qt_add_executable和target_link_libraries。
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 cmake_minimum_required (VERSION 3.19 ) project (qttest2 VERSION 0.1 LANGUAGES CXX) find_package (Qt6 6.5 REQUIRED COMPONENTS Core Widgets) qt_standard_project_setup() qt_add_executable(qttest2 WIN32 MACOSX_BUNDLE main.cpp mainwindow.cpp mainwindow.h mainwindow.ui res.qrc logo.rc ) target_link_libraries (qttest2 PRIVATE Qt::Core Qt::Widgets ) include (GNUInstallDirs)install (TARGETS qttest2 BUNDLE DESTINATION . RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ) qt_generate_deploy_app_script( TARGET qttest2 OUTPUT_SCRIPT deploy_script NO_UNSUPPORTED_PLATFORM_ERROR ) install (SCRIPT ${deploy_script} )