一、Qt Widgets 问题交流
1.QPainter旋转角度绘制线条的一点问题
QPainter 旋转角度,等距绘制若干线条,会出现绘制不均匀的情况:
但是在测试 QML Canvas 绘制时,发现效果是正常的,原来是因为 Canvas 默认的 capStyle 不一样,QPainter 设置成 FlatCap 后,绘制效果就正常了。
cpp
void MyPaintedItem::paint(QPainter *painter)
{
QRect rect = boundingRect().toRect();
QPoint center = rect.center();
painter->save();
painter->translate(center.x(), center.y());
painter->setRenderHint(QPainter::Antialiasing, true);
int r = qMin(rect.width(), rect.height()) / 2 - 2;
double line_width = 0.5; // + 1E-7;
QPen pen;
pen.setColor(QColor(127, 0, 0));
pen.setWidthF(line_width);
pen.setJoinStyle(Qt::MiterJoin);
// QML Canvas 默认 flat, QPainter 默认 square
// 如果不使用 flat,多次旋转后可能会不均匀
// pen.setCapStyle(Qt::FlatCap);
for (int i = 0; i < mLineCount; i++)
{
// 如果不使用 save/restore, 多次旋转后可能会不均匀
painter->save();
painter->rotate(mRotation + 360.0 / mLineCount * i);
QPainterPath path;
path.moveTo(0, 0);
path.lineTo(r, 0);
painter->strokePath(path, pen);
painter->restore();
}
painter->restore();
}
二、Qt Quick 问题交流
1.QML Window 设置 WindowStaysOnTopHint 置顶后,窗口标题栏没了
测试环境 Win11 + Qt5.15.2
QML 设置 WindowStaysOnTopHint 置顶后,窗口标题栏没了,但是 QWidget 显示正常
cpp
flags: Qt.Window|Qt.WindowStaysOnTopHint
需要把标题栏和按钮的 Hint 全部加上才能显示:
cpp
flags: Qt.Window|Qt.WindowStaysOnTopHint|Qt.WindowTitleHint|
Qt.WindowSystemMenuHint|Qt.WindowMinMaxButtonsHint|
Qt.WindowCloseButtonHint|Qt.WindowFullscreenButtonHint
也可以参考网友的代码,获取窗口 id 后用 Win32 接口切换置顶状态:
https://blog.csdn.net/qq_34719188/article/details/131689748
三、其他
1.Qt5 QSysInfo 在 Win11 上获取的系统信息为 Win10
因为 Win11 需要从 OSVERSIONINFOEX 结构体的 dwBuildNumber 字段来判断,dwBuildNumber ≥ 22000 时判定为 Win11,而 dwMajorVersion 在 Win10 和 Win11 都是 10。
参考 Qt6.5 代码:
cpp
static inline OSVERSIONINFOEX determineWinOsVersion()
{
OSVERSIONINFOEX result = { sizeof(OSVERSIONINFOEX), 0, 0, 0, 0, {'\0'}, 0, 0, 0, 0, 0};
HMODULE ntdll = GetModuleHandleW(L"ntdll.dll");
if (Q_UNLIKELY(!ntdll))
return result;
typedef NTSTATUS (NTAPI *RtlGetVersionFunction)(LPOSVERSIONINFO);
// RtlGetVersion is documented public API but we must load it dynamically
// because linking to it at load time will not pass the Windows App Certification Kit
// https://msdn.microsoft.com/en-us/library/windows/hardware/ff561910.aspx
RtlGetVersionFunction pRtlGetVersion = reinterpret_cast<RtlGetVersionFunction>(
reinterpret_cast<QFunctionPointer>(GetProcAddress(ntdll, "RtlGetVersion")));
if (Q_UNLIKELY(!pRtlGetVersion))
return result;
// GetVersionEx() has been deprecated in Windows 8.1 and will return
// only Windows 8 from that version on, so use the kernel API function.
pRtlGetVersion(reinterpret_cast<LPOSVERSIONINFO>(&result)); // always returns STATUS_SUCCESS
return result;
}
OSVERSIONINFOEX qWindowsVersionInfo()
{
OSVERSIONINFOEX realResult = determineWinOsVersion();
#ifdef QT_DEBUG
// ... ...
#endif
return realResult;
}
static const char *osVer_helper(QOperatingSystemVersion version = QOperatingSystemVersion::current())
{
Q_UNUSED(version);
const OSVERSIONINFOEX osver = qWindowsVersionInfo();
const bool workstation = osver.wProductType == VER_NT_WORKSTATION;
#define Q_WINVER(major, minor) (major << 8 | minor)
switch (Q_WINVER(osver.dwMajorVersion, osver.dwMinorVersion)) {
case Q_WINVER(10, 0):
if (workstation) {
if (osver.dwBuildNumber >= 22000)
return "11";
return "10";
}
// else: Server
if (osver.dwBuildNumber >= 20348)
return "Server 2022";
if (osver.dwBuildNumber >= 17763)
return "Server 2019";
return "Server 2016";
}
#undef Q_WINVER
// unknown, future version
return nullptr;
}
2.32位程序虚拟地址空间大小
遇到32位程序程序在占用1.5G左右内存溢出崩掉的问题,应该是实际的虚拟地址可用的不足2GB,即使设置了启用大地址接近 4GB 和 1.5 GB 差别也不大,数据量较大的时候还是会溢出。
cpp
QMAKE_LFLAGS_WINDOWS += /LARGEADDRESSAWARE
Windows文档:https://learn.microsoft.com/en-us/windows-hardware/drivers/gettingstarted/virtual-address-spaces