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

如何在Qt C++中实现类似Blender的叠加式小部件

如何在Qt C++中实现类似Blender的叠加式小部件

嘿,我完全懂你想要的效果——就像Blender里那种悬浮在视图上方、不占用场景显示空间的工具栏对吧?其实在Qt里实现这个并不复杂,我给你分享两种靠谱的方案,你可以根据需求选:


方案一:直接将工具栏作为QGraphicsView的子控件(推荐)

这种方式能让工具栏固定在视图的某个位置,完全叠加在场景视图上方,不会影响场景的显示和操作,最贴近Blender的效果。

具体步骤和代码示例:

  1. 自定义你的QGraphicsView子类,在构造函数里创建工具栏并设置初始位置:
#include <QGraphicsView>
#include <QToolBar>
#include <QResizeEvent>

class MyGraphicsView : public QGraphicsView
{
    Q_OBJECT
public:
    MyGraphicsView(QWidget *parent = nullptr) : QGraphicsView(parent)
    {
        // 创建工具栏并添加操作按钮
        QToolBar* overlayToolBar = new QToolBar(this);
        overlayToolBar->addAction("自由画笔");
        overlayToolBar->addAction("矩形工具");
        overlayToolBar->addAction("圆形工具");

        // 给工具栏设置半透明样式,更贴近Blender的风格
        overlayToolBar->setStyleSheet(R"(
            QToolBar {
                background-color: rgba(40, 40, 40, 0.8);
                border-radius: 4px;
                padding: 4px;
            }
            QToolButton {
                color: white;
                border: none;
                padding: 6px;
            }
            QToolButton:hover {
                background-color: rgba(60, 60, 60, 0.9);
                border-radius: 3px;
            }
        )");

        // 设置初始位置:左上角偏移20像素
        overlayToolBar->move(20, 20);

        // 禁止工具栏浮动和移动,固定在当前位置
        overlayToolBar->setFloatable(false);
        overlayToolBar->setMovable(false);

        // 确保工具栏在视图的viewport上方(避免被场景遮挡)
        overlayToolBar->raise();
    }

protected:
    // 重写resizeEvent,窗口大小变化时保持工具栏位置不变
    void resizeEvent(QResizeEvent *event) override
    {
        QGraphicsView::resizeEvent(event);
        // 找到我们创建的工具栏(如果保存指针的话更高效,这里用findChild示例)
        QToolBar* toolBar = findChild<QToolBar*>();
        if (toolBar) {
            toolBar->move(20, 20);
        }
    }
};

为什么推荐这个方案?

  • 工具栏完全独立于场景,不会随场景的缩放、平移而移动或变形
  • 不占用场景的显示空间,用户操作场景时不会被工具栏挤压视图
  • 样式自定义自由度高,很容易调出Blender那种深色半透明的质感

方案二:用QGraphicsProxyWidget嵌入场景(适合需要随场景联动的情况)

如果你希望工具栏能跟着场景一起缩放、平移(比如某些特殊绘图场景),可以把工具栏包装成QGraphicsProxyWidget加入到QGraphicsScene中:

// 在你的场景初始化代码里
QToolBar* toolBar = new QToolBar();
toolBar->addAction("画笔");
toolBar->addAction("矩形");

QGraphicsProxyWidget* proxyWidget = scene->addWidget(toolBar);
// 设置初始位置:对应视图左上角偏移20像素(这里要注意坐标转换)
proxyWidget->setPos(mapToScene(20, 20));
// 禁止代理部件随场景缩放而变形
proxyWidget->setFlag(QGraphicsItem::ItemIgnoresTransformations, true);

不过这个方案的缺点是,工具栏会成为场景的一部分,如果你不需要和场景联动,还是方案一更合适。


最后提个小技巧:如果工具栏遮挡了场景的操作区域,你可以给工具栏设置setAttribute(Qt::WA_TransparentForMouseEvents, true),但这样工具栏就接收不到点击事件了,所以只适合纯展示的叠加部件。

备注:内容来源于stack exchange,提问作者bbdd

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.13 16:18:04