Qt 5.14.2 + VS2022 配置

记录使用 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

1.3 安装 Qt Visual Studio Tools

在 Visual Studio 打开 扩展管理扩展,搜索安装 Qt Visual Studio Tools 即可。

装好扩展后,在菜单栏 扩展Qt VS ToolsOptions 中关联 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 文件,可通过编译报错信息来确定。

2.3 拷贝 qplatform 文件夹

C:\ProgramLibs\Qt\Qt5.14.2\5.14.2\msvc2017_64\plugins 中的 platforms 文件夹,直接拷贝到 项目文件夹\x64 中的 DebugRelease 中。

缺少这一步可能会引发以下报错。

详情可参考博客 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 文件夹中的 DebugRelease 文件夹中。

在项目中分别建立以下头文件与源文件,代码见 3.2.2。

其中 RasterWindow.h 中存在 QObject 类,需要在项目文件夹中通过 moc 命令生成 moc_RasterWindow.cpp 文件,然后添加到项目的资源文件中。

1
moc RasterWindow.h -o moc_RasterWindow.cpp

另外,如果项目中有 .ui 文件,也需要在项目文件夹中通过 uic 命令生成 .h 文件,然后添加到项目中。

1
uic abc.ui -o ui_abc.h

3.2.2 源代码

main.cpp

1
2
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

1
2
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

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
#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

1
2
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

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
#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);
}