gpt4 book ai didi

c++ - 使 QGraphicsProxyWidget 可移动和可选择

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:24:07 28 4
gpt4 key购买 nike

我想放一个 QWidgetQGraphicsView并使用 QGraphicsProxyWidget 使小部件可选和可移动.
(这非常适用于 QGraphicsRectItemQGraphicItem 等)

这是我目前使用的代码:

// Create new QGraphicsScene and assign to graphicsView
scene = new QGraphicsScene(this);
ui->graphicsView->setScene(scene);

// Create widget and add to scene
MyWidget *widget = new MyWidget;
QGraphicsProxyWidget *proxy = scene->addWidget(widget);

// Make selectable
proxy->setFlag(QGraphicsItem::ItemIsSelectable, true);
// Make movable
proxy->setFlag(QGraphicsItem::ItemIsMovable, true);

小部件显示正确,但它既不能移动也不能选择!

任何帮助将不胜感激 ;)

最佳答案

我问自己和你在这里做的一样的问题。在我继续解决这个问题几个小时后我想出的解决方案之前,我不得不提到一般如果您想在场景中包含大量小部件,则将小部件添加到场景中不是一个好主意 .您可以阅读有关此问题的信息 here .
现在回到正轨。以下是在尝试实现您想要的事情时出现的一些重大问题:

  • 如果你惹了mouseMove()mouseHover()你的小部件代理,你会搞砸小部件的 UI 组件的行为方式。
  • 同时,您希望它是可选的和可移动的,因此您必须以某种方式将此类功能添加到小部件代理

  • 我们怎么做?好吧,直接这似乎是不可能的。但是我想出了一个简单的解决方案来完成工作 - 结合 QGraphicsProxyWidgetQGraphicsItem !
    为了在小部件中保留 UI 组件的功能,您需要将代理作为子项添加到图形项中。另一方面,图形项(代理的父项)将覆盖选择和移动部分。
    这是一个小演示(我不排除错误,因为这是我目前正在研究的东西,而且大部分时间我使用 PyQt 而不是 C++ Qt):
    scenewithmovableproxies.ui
    <?xml version="1.0" encoding="UTF-8"?>
    <ui version="4.0">
    <class>SceneWithMovableProxies</class>
    <widget class="QWidget" name="SceneWithMovableProxies">
    <property name="geometry">
    <rect>
    <x>0</x>
    <y>0</y>
    <width>400</width>
    <height>300</height>
    </rect>
    </property>
    <property name="windowTitle">
    <string>SceneWithMovableProxies</string>
    </property>
    <layout class="QGridLayout" name="gridLayout">
    <item row="0" column="0">
    <widget class="QGraphicsView" name="graphicsView"/>
    </item>
    </layout>
    </widget>
    <layoutdefault spacing="6" margin="11"/>
    <resources/>
    <connections/>
    </ui>
    main.cpp
    #include "scenewithmovableproxies.hpp"
    #include <QApplication>

    int main(int argc, char *argv[])
    {
    QApplication a(argc, argv);
    SceneWithMovableProxies w;
    w.show();

    return a.exec();
    }
    scenewithmovableproxies.hpp
    #ifndef SCENEWITHMOVABLEPROXIES_HPP
    #define SCENEWITHMOVABLEPROXIES_HPP

    #include <QWidget>
    #include <QPoint>

    namespace Ui {
    class SceneWithMovableProxies;
    }

    class SceneWithMovableProxies : public QWidget
    {
    Q_OBJECT

    public:
    explicit SceneWithMovableProxies(QWidget *parent = 0);
    ~SceneWithMovableProxies();

    private:
    Ui::SceneWithMovableProxies *ui;
    void addWidgetToScene(QPoint initPos);
    };

    #endif // SCENEWITHMOVABLEPROXIES_HPP
    scenewithmovableproxies.cpp
    #include "scenewithmovableproxies.hpp"
    #include "ui_scenewithmovableproxies.h"
    #include "scenewidgetitem.hpp"
    #include <QGraphicsProxyWidget>

    SceneWithMovableProxies::SceneWithMovableProxies(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::SceneWithMovableProxies)
    {
    ui->setupUi(this);
    ui->graphicsView->setRenderHint(QPainter::Antialiasing);
    ui->graphicsView->setScene(new QGraphicsScene(this));

    // Add widget proxies + their parenting graphics items to scene
    addWidgetToScene(QPoint(10, 10));
    addWidgetToScene(QPoint(300, 100));
    addWidgetToScene(QPoint(200, 200));
    }

    SceneWithMovableProxies::~SceneWithMovableProxies()
    {
    delete ui;
    }

    void SceneWithMovableProxies::addWidgetToScene(QPoint initPos)
    {
    // Create a widget
    SceneWidgetItem *widget = new SceneWidgetItem();
    // Create the graphics item that will be used to move the widget around the screen as well as be selectable (for example in case we want to delete a widget that is in the scene)
    // Depending on the position of the graphics item relative to its widget proxy you can adjust the size and location of both
    QGraphicsRectItem *proxyControl = ui->graphicsView->scene()->addRect(initPos.x(), initPos.y(), widget->width(), 20, QPen(Qt::black), QBrush(Qt::darkGreen)); // widget->width() works properly here because of the resize(layout->sizeHint()) that we have used inside it
    proxyControl->setFlag(QGraphicsItem::ItemIsMovable, true);
    proxyControl->setFlag(QGraphicsItem::ItemIsSelectable, true);
    // Create the proxy by adding the widget to the scene
    QGraphicsProxyWidget * const proxy = ui->graphicsView->scene()->addWidget(widget);
    // In my case the rectangular graphics item is supposed to be above my widget so the position of the widget is shifted along the Y axis based on the height of the rectangle of that graphics item
    proxy->setPos(initPos.x(), initPos.y()+proxyControl->rect().height());
    proxy->setParentItem(proxyControl);

    // proxyControl->setRotation(45); // Because the widget is a child of the graphics item if we do some sort of transformation to it, the change will be propagated to the widget too!
    }
    scenewidgetitem.hpp
    #ifndef SCENEWIDGETITEM_HPP
    #define SCENEWIDGETITEM_HPP

    #include <QWidget>
    #include <QVBoxLayout>
    #include <QCheckBox>
    #include <QComboBox>
    #include <QLabel>
    #include <QPushButton>

    class SceneWidgetItem : public QWidget
    {
    Q_OBJECT
    QVBoxLayout *layout;
    QLabel *label;
    QCheckBox *checkbox;
    QComboBox *combobox;
    QPushButton *resetButton;
    public:
    explicit SceneWidgetItem(QWidget *parent = 0);
    ~SceneWidgetItem();

    signals:

    public slots:
    void reset();
    };

    #endif // SCENEWIDGETITEM_HPP
    scenewidgetitem.cpp
    #include "scenewidgetitem.hpp"

    // Create a widget with whichever UI components you like
    SceneWidgetItem::SceneWidgetItem(QWidget *parent) : QWidget(parent)
    {
    layout = new QVBoxLayout(this);
    checkbox = new QCheckBox("Enable proxy", this);
    checkbox->setChecked(true);
    combobox = new QComboBox(this);
    combobox->addItem("---");
    combobox->addItem("Item 1");
    combobox->addItem("Item 2");
    combobox->addItem("Item 3");
    label = new QLabel(this);
    label->setText(combobox->itemText(0));
    resetButton = new QPushButton("Reset", this);

    // Maybe add some signals :P
    connect(checkbox, SIGNAL(toggled(bool)), combobox, SLOT(setEnabled(bool)));
    connect(checkbox, SIGNAL(toggled(bool)), resetButton, SLOT(setEnabled(bool)));
    connect(resetButton, SIGNAL(clicked(bool)), this, SLOT(reset()));
    connect(combobox, SIGNAL(currentIndexChanged(QString)), label, SLOT(setText(QString)));

    layout->addWidget(checkbox);
    layout->addWidget(label);
    layout->addWidget(resetButton);
    layout->addWidget(combobox);

    // Resizing the widget to its layout's content is very important. If
    // you don't do that the parenting graphics item will not visually fit
    // to its child widget and you will get a mess
    resize(layout->sizeHint());
    setLayout(layout);
    }

    SceneWidgetItem::~SceneWidgetItem()
    {

    }

    void SceneWidgetItem::reset()
    {
    combobox->setCurrentIndex(0);
    label->setText("---");
    }
    以下是一些截图:
    初始 View
    enter image description here
    三选二
    enter image description here
    搬家
    enter image description here
    旋转
    enter image description here
    与小部件交互 - 使用 QComboBox
    enter image description here
    与小部件交互 - 使用 QCheckBox
    enter image description here
    现在由于 QGraphicsItem的性质(以及 QGraphicsProxyWidget )有一些问题最烦人的是重叠
    重叠
    enter image description here
    然而,通过使用碰撞检测和基本上 可以相对容易地避免重叠。根本不允许重叠 .自 QGraphicsProxyWidget也可以使用 QGraphicsItem功能 collisionWithItem(...)您可以实现一种机制来处理这种情况。因为我是新来的 QGraphicsScene所有这一切(2 天前开始,同时在 SO :D 上回答问题时开始)在 QGraphicsScene 中可能存在某种集成机制。自己来处理这个。
    失真
    在旋转屏幕截图中,您可能已经注意到,以前看起来很完美的直线出现了一些视觉上的怪异现象。这些就是所谓的 锯齿 .目前我不知道如何摆脱这些。我试过使用 高品质抗锯齿 但结果甚至比仅使用抗锯齿 ( QPainter::Antialiasing ) 还要糟糕。
    进一步研究
    我实际上目前正在从事我的一个小项目,我想在其中创建一个基于复合节点的用于图像处理的 UI。在线查找此主题总是返回人们使用简单的解决方案 QGraphicsItem s 并且节点配置本身部分外包给了 QGraphicsViewer 的外部。小部件。您可以使用我上面描述的设计,并根据您以后想要做的事情添加更多内容。多个 QGraphicItem s 也可以附加到小部件代理。您可以对此感到疯狂,但请记住,这会对性能产生影响(请一次又一次地阅读我在答案开头链接的博客文章)。

    关于c++ - 使 QGraphicsProxyWidget 可移动和可选择,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15413564/

    28 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com