【Qwt 7.0 系列】交互功能详解 —— 平移、缩放、坐标轴交互与数据拾取

【Qwt 7.0 系列】交互功能详解 ------ 平移、缩放、坐标轴交互与数据拾取

本文是 Qwt 7.0 系列介绍和教程,如果你正在寻找一个高性能、协议友好、同时支持 2D 和 3D 绘图的 Qt 数据可视化库,那么这篇文章就是为你准备的。

系列总述文章:Qwt 7.0 ------ 基于 Qt 的高性能 2D/3D 绘图库

概述 | 高性能曲线绘制 | 常用图表类型 | 高级科学图表 | 多坐标轴与布局 | 交互功能 | 3D 数据可视化 | 坐标轴与刻度 | 控件与辅助元素 | 总体架构解析 | matplotlib 风格绘图

项目地址:GitHub | Gitee | 在线文档

引言

交互是数据可视化的关键环节。一张静态的图表只能展示数据的一个切面,而通过平移、缩放、拾取等交互操作,用户才能在数据海洋中自由探索,发现隐藏的规律。

原版 Qwt 6.2 已经提供了平移和缩放功能,但随着使用场景的复杂化,它暴露出一些明显的不足:平移过程基于位图缓存导致体验不够流畅,缩放器绑定坐标轴数量有限,坐标轴无法直接操作,数据拾取需要开发者自己实现等。

Qwt 7.0 对交互功能进行了全面重构和增强,带来了一系列令人瞩目的新特性:

  • 实时平移QwtPlotPanner 基于 QwtPicker 状态机重构,平移过程中绘图实时刷新
  • 整体画布缩放QwtPlotCanvasZoomer 无需指定坐标轴,自动处理全部四轴
  • 坐标轴内置交互:鼠标直接拖动、滚轮缩放坐标轴(7.0.5+ 新增)
  • 数据拾取QwtPlotSeriesDataPicker 提供 Y 值拾取和最近点拾取(7.0.6+ 新增)

本文将逐一详解这些功能。


一、平移工具

1.1 缓存平移的痛点

原版 Qwt 6 的 QwtPlotPanner 采用基于缓存的平移机制:平移过程中显示的是一张缓存的位图,而非实时更新的绘图内容。这带来两个问题:

  • 平移时看到的不是真实数据,视觉上有"拖动残影"的感觉
  • 无法在平移过程中看到数据的实时变化

虽然缓存机制减少了重绘开销,但对视觉体验很不友好。

1.2 实时平移:QwtPlotPanner(7.0 新增)

Qwt 7.0 对 QwtPlotPanner 进行了完全重构,新的实现基于 QwtPicker 状态机机制,实现了实时平移------平移过程中绘图内容实时更新:

新的 QwtPlotPanner 提供了完整的坐标轴支持:

  • 线性坐标轴(Linear Scale)
  • 对数坐标轴(Logarithmic Scale)
  • 日期时间坐标轴(DateTime Scale)
  • 多坐标轴

基本用法非常简单:

cpp 复制代码
#include "qwt_plot_panner.h"
#include "qwt_plot.h"
#include "qwt_plot_curve.h"

// 创建绘图和曲线
QwtPlot* plot = new QwtPlot;
QwtPlotCurve* curve = new QwtPlotCurve("Sine Wave");
curve->attach(plot);

// 创建实时平移器
QwtPlotPanner* panner = new QwtPlotPanner(plot->canvas());
// 配置鼠标按钮(默认中键平移)
panner->setMouseButton(Qt::MiddleButton);
// 也可以用左键平移
// panner->setMouseButton(Qt::LeftButton);

// 启用平移器
panner->setEnabled(true);

你还可以限制平移方向,只允许水平或垂直方向移动:

cpp 复制代码
// 默认:水平 + 垂直
panner->setOrientations(Qt::Horizontal | Qt::Vertical);
// 仅水平
// panner->setOrientations(Qt::Horizontal);
// 仅垂直
// panner->setOrientations(Qt::Vertical);

注意:QwtPlotPanner 不需要绑定坐标轴,因为它针对整个画布操作,移动画布时所有坐标轴都会同步移动。

1.3 缓存平移:QwtPlotCachePanner(原 QwtPlotPanner)

如果你仍然想使用原来的缓存式平移,Qwt 7.0 保留了它,只是换了名字。以下是重要的类名变更:

原名称(Qwt 6) 新名称(Qwt 7.0) 说明
QwtPanner QwtCachePanner 基类更名
QwtPlotPanner(旧) QwtPlotCachePanner 绘图缓存平移器更名
QwtPolarPanner QwtPolarCachePanner 极坐标缓存平移器更名
QwtPlotPanner(新) --- 全新重构,基于 QwtPicker

简单来说:Qwt 6 的 QwtPlotPanner 在 Qwt 7.0 中变成了 QwtPlotCachePanner,而 QwtPlotPanner 这个名字被新的实时平移器"夺走"了。接口保持不变,原有代码基本无需修改即可使用 QwtPlotCachePanner


二、缩放工具

2.1 缩放器的两个选择

在 Qwt 6 中,QwtPlotZoomer 需要指定两个坐标轴来进行缩放。如果你的绘图有四个坐标轴(上下左右都显示数据),就需要创建两个缩放器:

cpp 复制代码
// Qwt 6 传统用法 - 需要两个缩放器来覆盖四个坐标轴
QwtPlotZoomer* zoomer1 = new QwtPlotZoomer(QwtAxis::XBottom, QwtAxis::YLeft, canvas);
QwtPlotZoomer* zoomer2 = new QwtPlotZoomer(QwtAxis::XTop, QwtAxis::YRight, canvas);

这既繁琐又容易遗漏。Qwt 7.0 提供了两个缩放器,分工明确:

特性 QwtPlotAxisZoomer QwtPlotCanvasZoomer
坐标轴绑定 需要指定 X 和 Y 轴 自动处理所有四个坐标轴
使用场景 特定坐标轴缩放 整体画布缩放
寄生绘图支持 需手动绑定 自动支持所有寄生绘图

2.2 QwtPlotAxisZoomer(原 QwtPlotZoomer)

QwtPlotAxisZoomer 就是原来的 QwtPlotZoomer,重命名以区分新的画布缩放器。它绑定两个特定的坐标轴:

cpp 复制代码
#include "qwt_plot_axis_zoomer.h"

// 创建针对特定坐标轴的缩放器
QwtPlotAxisZoomer* axisZoomer = new QwtPlotAxisZoomer(
    QwtAxis::XBottom,  // X 轴
    QwtAxis::YLeft,    // Y 轴
    plot->canvas(),    // 画布
    true               // 自动重绘
);

// 或者使用默认坐标轴(XBottom + YLeft)
QwtPlotAxisZoomer* defaultZoomer = new QwtPlotAxisZoomer(plot->canvas());

2.3 QwtPlotCanvasZoomer(7.0 新增)

QwtPlotCanvasZoomer 是 Qwt 7.0 新增的缩放器,无需指定坐标轴,自动对整个画布进行缩放。这对多坐标轴和寄生绘图场景特别友好:

cpp 复制代码
#include "qwt_plot_canvas_zoomer.h"

// 创建整体画布缩放器,自动处理所有坐标轴
QwtPlotCanvasZoomer* canvasZoomer = new QwtPlotCanvasZoomer(plot->canvas());

一行代码搞定,简洁明了。

2.4 默认按键绑定

两个缩放器的按键绑定完全一致:

鼠标操作:

操作 默认按钮 功能描述
缩放选择 左键拖拽 选择矩形区域进行缩放
回到基准 右键点击 缩放到基准视图(完全缩小)
后退一级 中键点击 后退一级缩放
前进一级 中键+Shift 点击 前进一级缩放

键盘操作:

操作 默认按键 功能描述
前进一级 + 前进一级缩放
后退一级 - 后退一级缩放
回到基准 Escape 回到基准视图

2.5 自定义按键

如果默认按键不满足需求,可以自定义:

cpp 复制代码
// 配置键盘快捷键
zoomer->setKeyPattern(QwtEventPattern::KeyRedo, Qt::Key_Plus, Qt::ShiftModifier);   // 前进
zoomer->setKeyPattern(QwtEventPattern::KeyUndo, Qt::Key_Minus, Qt::ShiftModifier);  // 后退
zoomer->setKeyPattern(QwtEventPattern::KeyHome, Qt::Key_Escape);                     // 重置

// 配置鼠标模式:中键重置,右键回退
zoomer->setMousePattern(QwtEventPattern::MouseSelect2, Qt::MiddleButton);
zoomer->setMousePattern(QwtEventPattern::MouseSelect3, Qt::RightButton);

三、坐标轴内置交互动作(7.0.5+ 新增)

3.1 直接操作坐标轴

这是一个非常实用的新特性。在 Qwt 6 及更早版本中,用户无法直接操作坐标轴------所有的平移和缩放都发生在画布上。从 Qwt 7.0.5 开始,你可以用鼠标直接拖动坐标轴来平移,用滚轮在坐标轴上缩放。

这个功能的设计灵感来源于 QCustomPlot 的交互机制。启用后,用户可以在任意坐标轴上:

  • 左键单击选中坐标轴
  • 左键拖动平移坐标轴范围,绘图区域实时更新
  • 滚轮缩放,缩放中心位于鼠标当前位置
  • 右键单击取消选中状态

坐标轴拖动效果:

坐标轴滚轮缩放效果:

3.2 启用与配置

坐标轴交互功能通过 QwtPlotScaleEventDispatcher 类实现事件分发,但用户通常无需直接接触这个类,只需调用 QwtPlot::setEnableScaleBuildinActions 即可:

cpp 复制代码
// Qwt 7 默认启用坐标轴交互
// 如需手动控制:
plot->setEnableScaleBuildinActions(true);   // 启用
// plot->setEnableScaleBuildinActions(false); // 禁用

3.3 单轴自定义

你可以针对特定坐标轴配置不同的交互行为。QwtScaleWidget 使用 BuiltinActions 枚举来定义内置动作:

cpp 复制代码
// 仅让 XBottom 轴支持拖动,不支持滚轮缩放
plot->axisWidget(QwtAxis::XBottom)->setBuildinActions(
    QwtScaleWidget::ActionClickPan);

// 查询当前配置
auto flags = plot->axisWidget(QwtAxis::XBottom)->buildinActions();
// 检查某个动作是否激活
bool canPan = plot->axisWidget(QwtAxis::XBottom)->testBuildinActions(
    QwtScaleWidget::ActionClickPan);

3.4 选中效果自定义

坐标轴被选中时,默认文字和轴线颜色变为蓝色。你可以自定义这个选中颜色,以及选中后轴线粗细的变化:

cpp 复制代码
// 设置选中颜色(默认蓝色)
plot->axisWidget(QwtAxis::XBottom)->setSelectionColor(QColor(255, 100, 0));

// 设置选中后画笔宽度偏移(默认 1,即选中后线条加粗 1 像素)
plot->axisWidget(QwtAxis::XBottom)->setSelectedPenWidthOffset(2);

效果如下图所示,选中坐标轴后轴线变粗、颜色变化:


四、数据拾取:QwtPlotSeriesDataPicker(7.0.6+ 新增)

4.1 为什么需要数据拾取

数据拾取是绘图控件的常见需求:用户移动鼠标时,实时显示当前位置对应的数据值。在 Qwt 6 中,这个功能需要开发者自己实现,涉及坐标转换、数据查找、文本绘制等繁琐工作。

Qwt 7.0.6 开始,Qwt 新增了 QwtPlotSeriesDataPicker 类,开箱即用,支持两种拾取模式、线性插值、多曲线、高性能优化等特性:

核心特性一览:

  • 双模式拾取:Y 值拾取 + 最近点拾取
  • 智能插值:线性插值计算,数据点之间也能精确取值
  • 高性能优化:二分查找 + 窗口搜索算法,支持大数据集
  • 多曲线支持:同时拾取多条曲线的数据
  • 自定义显示:文本样式、特征点绘制、背景均可定制
  • 寄生绘图支持:支持宿主绘图和寄生绘图的数据获取

4.2 基本用法

cpp 复制代码
#include "qwt_plot_series_data_picker.h"

// 创建绘图对象
QwtPlot* plot = new QwtPlot(this);

// 创建数据拾取器,传入 canvas 即可
QwtPlotSeriesDataPicker* picker = new QwtPlotSeriesDataPicker(plot->canvas());

// 设置拾取模式
picker->setPickMode(QwtPlotSeriesDataPicker::PickYValue);

// 启用线性插值
picker->setInterpolationMode(QwtPlotSeriesDataPicker::LinearInterpolation);

// 设置文本显示位置(自动选择)
picker->setTextArea(QwtPlotSeriesDataPicker::TextPlaceAuto);

4.3 Y 值拾取模式

Y 值拾取模式显示当前 X 位置对应所有曲线的 Y 值。当鼠标在画布上移动时,拾取器会画一条垂直辅助线,并在每条曲线上标记对应 Y 值的位置:

cpp 复制代码
// Y 值拾取模式(默认)
picker->setPickMode(QwtPlotSeriesDataPicker::PickYValue);

插值是该模式的亮点。当数据点比较稀疏时,拾取器会通过线性插值计算出当前 X 轴位置对应的 Y 值,而非简单取最近点。插值默认开启,也可以关闭:

cpp 复制代码
// 关闭插值,使用最近的数据点
picker->setInterpolationMode(QwtPlotSeriesDataPicker::NoInterpolation);

4.4 最近点拾取模式

最近点拾取模式计算距离鼠标最接近的数据点并显示。这个模式特别适合频谱图等需要拾取峰值的场景:

cpp 复制代码
// 最近点拾取模式
picker->setPickMode(QwtPlotSeriesDataPicker::PickNearestPoint);

4.5 性能优化:窗口搜索算法

最近点拾取需要计算曲线每个点到鼠标的距离,全曲线遍历会非常耗时。为此,Qwt 7.0 提供了窗口搜索算法:

cpp 复制代码
// 设置搜索窗口大小
void setNearestSearchWindowSize(int windowSize);
int nearestSearchWindowSize() const;

窗口大小支持三种设置方式:

设置值 含义
0 不使用窗口,搜索整个曲线
正数 固定窗口大小(数据点数量)
负数 自适应窗口,取绝对值百分比(如 -5 表示曲线点数的 5%)

默认值为 -5,即曲线点数的 5%。需要注意的是,窗口优化算法默认在曲线点数超过 1000 时才生效,点数较少时直接全量搜索。

此外,窗口优化算法要求曲线数据按 X 坐标升序排列。使用自定义数据源时请确保数据已排序。

4.6 自定义显示文本

通过继承 QwtPlotSeriesDataPicker 并重写 valueString 方法,可以自定义数据点的显示格式:

cpp 复制代码
class CustomDataPicker : public QwtPlotSeriesDataPicker {
public:
    explicit CustomDataPicker(QWidget* canvas) : QwtPlotSeriesDataPicker(canvas) {}

protected:
    QString valueString(const QPointF& value, QwtPlotItem* item,
                        size_t seriesIndex, int order) const override {
        Q_UNUSED(seriesIndex);

        if (pickMode() == PickYValue) {
            QString text;
            if (order != 0) {
                text += "\n";  // 非第一个点需要换行
            }
            text += QString("%1: %2 (X=%3)")
                        .arg(item->title().text())
                        .arg(value.y(), 0, 'f', 3)
                        .arg(value.x(), 0, 'f', 3);
            return text;
        }
        return QString("坐标: (%1, %2)").arg(value.x()).arg(value.y());
    }
};

valueStringorder 参数表示当前是第几个特征点,多条曲线时递增,可根据它是否为 0 决定是否换行。

4.7 特征点与文本样式

拾取到的数据点称为"特征点",会在曲线上标记出来:

cpp 复制代码
// 启用特征点标记
picker->setEnableDrawFeaturePoint(true);
// 设置特征点大小(像素)
picker->setDrawFeaturePointSize(6);

// 自定义文本背景
picker->setTextBackgroundBrush(QBrush(QColor(255, 255, 255, 180)));
// 设置文本对齐方式
picker->setTextAlignment(Qt::AlignLeft | Qt::AlignTop);

4.8 点击信号与数据获取

QwtPlotSeriesDataPicker 提供了点击信号,方便响应用户操作:

cpp 复制代码
// 单击信号
void clicked(QwtPlotSeriesDataPicker* picker, const QPoint& pos);
// 双击信号
void doubleClicked(QwtPlotSeriesDataPicker* picker, const QPoint& pos);

点击信号仅响应鼠标左键。双击时会先触发 clicked() 再触发 doubleClicked(),这是 Qt 的标准行为。

通过 featurePoints() 方法可以获取当前拾取到的数据点信息:

cpp 复制代码
struct FeaturePoint {
    QwtPlotItem* item { nullptr };  // 对应的曲线项
    QPointF feature { 0, 0 };       // 特征点坐标
    size_t index { 0 };             // 在曲线数据中的索引
};

// 获取当前拾取到的特征点列表
QList<FeaturePoint> featurePoints() const;

使用示例:

cpp 复制代码
connect(picker, &QwtPlotSeriesDataPicker::clicked,
        [](QwtPlotSeriesDataPicker* p, const QPoint& pos) {
    Q_UNUSED(pos);
    QList<QwtPlotSeriesDataPicker::FeaturePoint> fps = p->featurePoints();
    for (const auto& fp : fps) {
        if (fp.item) {
            qDebug() << "曲线:" << fp.item->title().text()
                     << "X:" << fp.feature.x()
                     << "Y:" << fp.feature.y()
                     << "索引:" << fp.index;
        }
    }
});

4.9 多子图联动:QwtPlotSeriesDataPickerGroup

在多子图布局中,QwtPlotSeriesDataPickerGroup 可以实现跨图数据联动。当用户点击某个子图时,组内其他 picker 会自动同步到相同的 X 轴比例位置:

cpp 复制代码
#include "qwt_plot_series_data_picker_group.h"

// 创建 Group 并添加多个 picker
QwtPlotSeriesDataPickerGroup* pickerGroup = new QwtPlotSeriesDataPickerGroup(this);
pickerGroup->addPicker(picker1);
pickerGroup->addPicker(picker2);
pickerGroup->addPicker(picker3);

// 连接 Group 的点击信号
connect(pickerGroup, &QwtPlotSeriesDataPickerGroup::clicked,
        this, [this](QwtPlotSeriesDataPicker* picker, const QPoint& pos) {
    Q_UNUSED(pos);
    // 此时所有 picker 已同步,可获取所有子图的数据
    for (auto* p : { picker1, picker2, picker3 }) {
        auto fps = p->featurePoints();
        if (!fps.isEmpty()) {
            qDebug() << "Y value:" << fps.first().feature.y();
        }
    }
});

Group 在发出点击信号之前会先同步所有 picker 的位置,这意味着信号触发时所有 picker 的 featurePoints() 都已更新,非常适合多子图联动检视。


五、Picker 状态机简介

前面多次提到 QwtPlotPanner 基于 QwtPicker 状态机实现,这里简要介绍一下状态机的概念,帮助理解 Qwt 7.0 交互功能的底层机制。

5.1 为什么需要状态机

图形交互中,用户的操作往往是一个有序的事件序列,而非单一动作。比如拖拽操作 = 按下鼠标 → 移动鼠标 → 释放鼠标。如果没有状态机管理,我们需要在事件处理函数中写大量 if-else 分支和状态变量,代码会变得难以维护。

Qwt 的 QwtPicker 使用状态机来管理交互过程,将事件序列的识别具体业务操作分离:

  • 状态机负责识别完整的事件序列(按下→移动→释放)
  • QwtPicker 负责执行具体的绘制、选择等操作

5.2 工作原理

QwtPicker 的事件处理流程如下:

复制代码
事件流: QEvent → QwtPicker → QwtPickerMachine → Commands → QwtPicker方法

状态机将具体的绘图动作抽象为五种命令:

命令 描述
Begin() 开始选择
Append() 添加点
Move() 移动点
Remove() 删除点
End() 结束选择

状态机分析事件后返回命令序列,QwtPicker 依次执行这些命令。以拖拽点选择为例,核心逻辑如下:

cpp 复制代码
QList<QwtPickerMachine::Command> QwtPickerDragPointMachine::transition(
    const QwtEventPattern& eventPattern, const QEvent* event)
{
    QList<QwtPickerMachine::Command> cmdList;

    switch (event->type()) {
        case QEvent::MouseButtonPress:
            if (state() == 0) {           // 初始状态
                cmdList += Begin;          // 开始选择
                cmdList += Append;         // 添加第一个点
                setState(1);               // 进入拖拽状态
            }
            break;
        case QEvent::MouseMove:
            if (state() != 0)              // 在拖拽状态中
                cmdList += Move;           // 持续移动
            break;
        case QEvent::MouseButtonRelease:
            if (state() != 0) {
                cmdList += End;            // 结束选择
                setState(0);               // 回到初始状态
            }
            break;
    }
    return cmdList;
}

状态转换非常清晰:状态 0(初始)→ 按下 → 状态 1(拖拽)→ 释放 → 状态 0。

5.3 常用内置状态机

Qwt 提供了多种预定义状态机,满足不同的交互需求:

状态机 用途 典型场景
QwtPickerTrackerMachine 实时追踪鼠标位置 坐标显示、悬停提示
QwtPickerClickPointMachine 单次点击选择一个点 点选数据点、快速定位
QwtPickerDragPointMachine 拖拽选择点 精确位置选择、实时平移
QwtPickerClickRectMachine 两次点击确定矩形 精确矩形选择
QwtPickerDragRectMachine 拖拽选择矩形 快速缩放、区域选择
QwtPickerDragLineMachine 拖拽选择线段 距离测量、角度测量
QwtPickerPolygonMachine 多次点击创建多边形 复杂区域选择、多边形绘制

理解状态机的工作原理,不仅有助于正确使用 Qwt 的交互组件,还能在需要自定义交互模式时,通过继承 QwtPickerMachine 快速实现。


六、与旧版本的区别总结

下表汇总了 Qwt 7.0 交互功能与 Qwt 6 的核心区别:

功能 Qwt 6 Qwt 7.0
平移 QwtPlotPanner(缓存平移) QwtPlotPanner(实时平移,重构)+ QwtPlotCachePanner(缓存平移)
缩放 QwtPlotZoomer(绑定 2 轴) QwtPlotAxisZoomer(绑定 2 轴)+ QwtPlotCanvasZoomer(整体画布缩放)
坐标轴交互 不支持 7.0.5+ 支持鼠标拖动和滚轮缩放
数据拾取 需自行实现 7.0.6+ 内置 QwtPlotSeriesDataPicker
多子图联动 QwtPlotSeriesDataPickerGroup 支持同步

类名变更速查(重要):

旧名(Qwt 6) 新名(Qwt 7.0) 说明
QwtPanner QwtCachePanner 缓存平移基类更名
QwtPlotPanner QwtPlotCachePanner 缓存平移器更名
QwtPolarPanner QwtPolarCachePanner 极坐标缓存平移器更名
QwtPlotZoomer QwtPlotAxisZoomer 轴缩放器更名

迁移提示:如果你从 Qwt 6 迁移到 7.0,只需将旧的 QwtPlotPanner 替换为 QwtPlotCachePanner,将 QwtPlotZoomer 替换为 QwtPlotAxisZoomer,接口保持不变。或者直接使用新的实时平移 QwtPlotPanner 和整体画布缩放 QwtPlotCanvasZoomer,体验更佳。


总结

Qwt 7.0 的交互功能相比 Qwt 6 有了质的提升:

  1. 实时平移让数据探索更流畅,告别缓存残影
  2. 整体画布缩放简化了多坐标轴场景的配置
  3. 坐标轴内置交互让用户可以直接操作坐标轴,交互更直观
  4. 数据拾取器开箱即用,支持双模式、插值、多子图联动,大幅减少开发工作量
  5. 底层的 Picker 状态机机制让自定义交互也变得清晰可控

类名变更是迁移时最需要注意的地方,但接口保持不变,迁移成本很低。如果你是新项目,直接使用 7.0 的新组件即可获得最佳体验。

系列文章

系列总述:Qwt 7.0 ------ 基于 Qt 的高性能 2D/3D 绘图库


相关链接

相关推荐
sycmancia2 小时前
Qt——进程与线程的概念
qt
郝学胜-神的一滴2 小时前
Qt 高级编程 034:深耕QWidget底层内核—彻底吃透无边框窗口设计核心原理
开发语言·c++·qt·程序人生·软件开发·用户界面
满天星83035773 小时前
【Qt】控件(二) (geometry及与frameGeometry的区别)
开发语言·qt
大气的小蜜蜂3 小时前
基于Python+PyQt5+SQLite的药房管理系统实现:事务一致性与界面解耦全流程解析
python·qt·sqlite
尘中远4 小时前
【Qwt 7.0 系列】总体架构解析 —— 从单体到三库模块化的演进
qt·matplotlib·绘图·qwt·科学绘图
xcyxiner4 小时前
DicomViewer (编译以及优化)8
qt
旖-旎4 小时前
QT界面优化(6)
开发语言·c++·qt
特立独行的猫a4 小时前
为 HarmonyOS/OpenHarmony 构建第三方库的解决方案(转自Qt官方Blog)
qt·华为·harmonyos·三方库·鸿蒙pc
零点零一4 小时前
QT 5升级到 Qt 6 使用 Clazy 检查将 C++ 应用程序移植到 Qt 6
开发语言·c++·qt