You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修改QStackedBarSeries中单个QBarSet的宽度?(马赛克图开发)

解决Qt中马赛克图的柱状条宽度自定义问题

其实你不用急着子类化QAbstractBarSeries,这里有几个更实用的思路,帮你实现马赛克图的需求:

方案一:手动用QGraphicsView绘制(推荐)

马赛克图的核心是精确控制每个矩形的宽高比例,而Qt Charts的QStackedBarSeries天生是为统一宽度的堆叠柱状图设计的,强行改造反而麻烦。直接用QGraphicsScene+QGraphicsView绘制是最灵活的方式,完全不受框架限制:

举个简单的实现框架:

// 模拟马赛克数据:每个类别对应总宽度,以及内部分段的高度占比
QList<QPair<qreal, QList<qreal>>> mosaicData = {
    {20, {0.3, 0.5, 0.2}}, // 第一组宽度20,三段占比30%/50%/20%
    {30, {0.4, 0.6}},      // 第二组宽度30,两段占比40%/60%
    {15, {0.1, 0.3, 0.6}}  // 第三组宽度15,三段占比10%/30%/60%
};

QGraphicsScene* scene = new QGraphicsScene();
qreal currentX = 0;
const qreal totalHeight = 100; // 整体高度,可按需调整

for (const auto& category : mosaicData) {
    qreal barWidth = category.first;
    qreal currentY = 0;
    // 绘制当前组的每个分段
    for (qreal proportion : category.second) {
        qreal segmentHeight = totalHeight * proportion;
        QGraphicsRectItem* rect = scene->addRect(currentX, currentY, barWidth, segmentHeight);
        // 自定义样式:随机颜色、tooltip提示
        rect->setBrush(QColor::fromHsv(qrand()%360, 200, 200));
        rect->setToolTip(QString("宽度:%1,高度占比:%2%").arg(barWidth).arg(proportion*100));
        currentY += segmentHeight;
    }
    currentX += barWidth + 5; // 组之间添加间距
}

QGraphicsView* view = new QGraphicsView(scene);
view->setRenderHint(QPainter::Antialiasing);
view->show();

这种方式不仅能自由控制每个“柱状条”(组)的宽度,连内部分段的高度、颜色、交互都能完全自定义,完美匹配马赛克图的需求。

方案二:基于Qt Charts自定义渲染(复杂但贴合原有框架)

如果一定要用Qt Charts的体系,那确实需要深入修改渲染逻辑,但不一定非要子类化QAbstractBarSeries:

  1. 子类化QStackedBarSeries,重写createRenderer()方法,返回一个自定义的bar渲染器
  2. 自定义渲染器需要继承Qt Charts的私有类QBarRenderer(注意:需要包含Qt Charts的私有头文件,或者自己实现类似的绘制逻辑)
  3. 在自定义渲染器中,根据每个类别的数据调整对应的bar宽度

不过这种方法门槛较高,需要熟悉Qt Charts的内部渲染流程,而且私有类可能在不同Qt版本中有所变化,维护成本高,所以更推荐第一种方案。

总结一下:如果是做马赛克图,手动绘制是更优更简便的起点,完全不需要受限于QStackedBarSeries的默认行为。

内容的提问来源于stack exchange,提问作者XababaX

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 10:11:28