记录使用 VS2022 开发 Qt5 时的基础配置过程。
1 安装
1.1 安装 VS 2022
下载链接  https://visualstudio.microsoft.com/zh-hans/downloads/
社区版免费,已足够个人开发使用。
根据个人需求选择安装组件即可,后续可通过 Visual Studio Installer 修改组件安装。
1.2 安装 Qt 5.14.2
官方下载链接 https://download.qt.io/archive/qt/5.14/5.14.2/qt-opensource-windows-x86-5.14.2.exe
以上链接目前为止是有效的,无法访问的话需科学上网。
Qt 版本自 5.15 开始不再提供离线安装包,需在线安装或者自己下载源码编译安装,因此 5.14.2 最后一个可以离线安装的版本。
安装过程中需登录 Qt 账号,最少需选择以下组件,其它按需选择即可。
详细安装步骤可参考博客 https://cloud.tencent.com/developer/article/2248312
在 Visual Studio 打开 扩展 → 管理扩展,搜索安装 Qt Visual Studio Tools 即可。
装好扩展后,在菜单栏 扩展 → Qt VS Tools → Options 中关联 Qt。
可点击下方 Autodetect 按钮,将自动关联已安装的 Qt 版本,选择一个默认版本打勾即可。
2 配置
如果只是在 Qt 项目中使用 Qt 编程,并不需要额外配置。这里针对的情况,是在普通 C/C++ 项目中使用 Qt 编程。
2.1 设置属性表
个人喜欢通过属性表进行目录配置,这样可以避免在系统环境变量中添加额外 Qt 目录。这里我的 Qt 安装目录为 C:\ProgramLibs\Qt\。
2.2 拷贝 dll 文件
从 C:\ProgramLibs\Qt\Qt5.14.2\5.14.2\msvc2017_64\bin 找到所需的 dll 文件,拷贝到项目文件夹中。
一般常用的 dll 文件有 Qt5Core Qt5Gui Qt5Widgets 等。具体需要哪些 dll 文件,可通过编译报错信息来确定。
将 C:\ProgramLibs\Qt\Qt5.14.2\5.14.2\msvc2017_64\plugins 中的 platforms 文件夹,直接拷贝到 项目文件夹\x64 中的 Debug 或 Release 中。
缺少这一步可能会引发以下报错。
详情可参考博客 https://blog.csdn.net/qq_42495740/article/details/118992097
3 测试
3.1 简单测试
安装完成后,可直接新建一个 Qt 项目来测试是否安装成功。这里选择新建 Qt Quick Application,一路默认下一步即可,最后直接点击编译运行。
3.2 在非 Qt 工程中使用 Qt
3.2.1 配置步骤
这里展示如何在一个 C++ 空项目中配置 Qt 中的钟表示例(Analog Clock Window Example)。
新建 C++ 空项目 testQt,首先将所需的 dll 文件与已建好的属性表文件拷贝到项目文件夹。
在项目属性管理器中添加现有属性表,选择项目文件夹中已建好的 Qt 属性表文件。
将 platforms 文件夹拷贝到项目第一层目录的 x64 文件夹中的 Debug 或 Release 文件夹中。
在项目中分别建立以下头文件与源文件,代码见 3.2.2。
其中 RasterWindow.h 中存在 QObject 类,需要在项目文件夹中通过 moc 命令生成 moc_RasterWindow.cpp 文件,然后添加到项目的资源文件中。
| 1
 | moc RasterWindow.h -o moc_RasterWindow.cpp
 | 
另外,如果项目中有 .ui 文件,也需要在项目文件夹中通过 uic 命令生成 .h 文件,然后添加到项目中。
3.2.2 源代码
main.cpp
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 
 | #include "AnalogClockWindow.h"#include <QtWidgets/QApplication>
 
 int main(int argc, char *argv[])
 {
 QApplication app(argc, argv);
 AnalogClockWindow* clock = new AnalogClockWindow();
 clock->show();
 return app.exec();
 }
 
 | 
AnalogClockWindow.h
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 
 | #include "RasterWindow.h"#include <QtCore/QTimerEvent>
 #include <QtGui/QPainter>
 #include <QtCore/QTime>
 #include <QtCore/QPoint>
 #include <QtGui/QColor>
 
 class AnalogClockWindow : public RasterWindow
 {
 public:
 AnalogClockWindow();
 protected:
 void timerEvent(QTimerEvent*) override;
 void render(QPainter* p) override;
 private:
 int m_timerId;
 };
 
 
 | 
AnalogClockWindow.cpp
| 12
 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
 
 | #include "AnalogClockWindow.h"
 AnalogClockWindow::AnalogClockWindow()
 {
 setTitle("Analog Clock");
 resize(200, 200);
 m_timerId = startTimer(1000);
 }
 void AnalogClockWindow::timerEvent(QTimerEvent* event)
 {
 if (event->timerId() == m_timerId)
 renderLater();
 }
 void AnalogClockWindow::render(QPainter* p)
 {
 static const QPoint hourHand[3] = { QPoint(7, 8), QPoint(-7, 8), QPoint(0, -40) };
 static const QPoint minuteHand[3] = { QPoint(7, 8), QPoint(-7, 8), QPoint(0, -70) };
 QColor hourColor(127, 0, 127);
 QColor minuteColor(0, 127, 127, 191);
 p->setRenderHint(QPainter::Antialiasing);
 p->translate(width() / 2, height() / 2);
 int side = qMin(width(), height());
 p->scale(side / 200.0, side / 200.0);
 p->setPen(Qt::NoPen);
 p->setBrush(hourColor);
 QTime time = QTime::currentTime();
 p->save();
 p->rotate(30.0 * ((time.hour() + time.minute() / 60.0)));
 p->drawConvexPolygon(hourHand, 3);
 p->restore();
 p->setPen(hourColor);
 for (int i = 0; i < 12; ++i)
 {
 p->drawLine(88, 0, 96, 0);
 p->rotate(30.0);
 }
 p->setPen(Qt::NoPen);
 p->setBrush(minuteColor);
 p->save();
 p->rotate(6.0 * (time.minute() + time.second() / 60.0));
 p->drawConvexPolygon(minuteHand, 3);
 p->restore();
 p->setPen(minuteColor);
 for (int j = 0; j < 60; ++j)
 {
 if ((j % 5) != 0)
 p->drawLine(92, 0, 96, 0);
 p->rotate(6.0);
 }
 }
 
 | 
RasterWindow.h
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 
 | #include <QtGui/QWindow>#include <QtCore/QEvent>
 #include <QtGui/QPainter>
 #include <QtGui/QResizeEvent>
 #include <QtGui/QBackingStore>
 
 class RasterWindow : public QWindow
 {
 Q_OBJECT
 public:
 explicit RasterWindow(QWindow* parent = 0);
 virtual void render(QPainter* painter);
 public slots:
 void renderLater();
 void renderNow();
 protected:
 bool event(QEvent* event) override;
 void resizeEvent(QResizeEvent* event) override;
 void exposeEvent(QExposeEvent* event) override;
 private:
 QBackingStore* m_backingStore;
 };
 
 
 | 
RasterWindow.cpp
| 12
 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
 
 | #include "RasterWindow.h"
 RasterWindow::RasterWindow(QWindow* parent) : QWindow(parent) , m_backingStore(new QBackingStore(this))
 {
 setGeometry(100, 100, 300, 200);
 }
 void RasterWindow::exposeEvent(QExposeEvent*)
 {
 if (isExposed())
 renderNow();
 }
 void RasterWindow::resizeEvent(QResizeEvent* resizeEvent)
 {
 m_backingStore->resize(resizeEvent->size());
 }
 void RasterWindow::renderNow()
 {
 if (!isExposed())
 return;
 QRect rect(0, 0, width(), height());
 m_backingStore->beginPaint(rect);
 QPaintDevice* device = m_backingStore->paintDevice();
 QPainter painter(device);
 painter.fillRect(0, 0, width(), height(), QGradient::NightFade);
 render(&painter);
 painter.end();
 m_backingStore->endPaint();
 m_backingStore->flush(rect);
 }
 void RasterWindow::render(QPainter* painter)
 {
 painter->drawText(QRectF(0, 0, width(), height()), Qt::AlignCenter, QStringLiteral("QWindow"));
 }
 void RasterWindow::renderLater()
 {
 requestUpdate();
 }
 bool RasterWindow::event(QEvent* event)
 {
 if (event->type() == QEvent::UpdateRequest)
 {
 renderNow();
 return true;
 }
 return QWindow::event(event);
 }
 
 |