【问题标题】:Drag item from QTreeWidget to QGraphicsView将项目从 QTreeWidget 拖到 QGraphicsView
【发布时间】:2020-09-27 05:39:10
【问题描述】:

我有以下情况:

基本上我有一个带有一些项目的QTreeWidget,以及一个作为QGraphicsView 子类的画布。我想要完成的是在QGraphicsView 子类中拖动一个QTreeWidgetItem。当鼠标在QGraphicsView 子类中释放时,我想创建一个新形状(比如说一个圆圈),其中包含拖动项目的一些数据(假设名称本身写在圆圈内)。

我能够通过使用setDragEnabled(true) 方法从QTreeWidget 启用拖动,并且我能够在QGraphicsView 中接收事件,因为当我进入它的区域时它会调用dragEnterEvent .

在我的子类中,我有一个 QGraphicsScene,如下所示:

#ifndef SEQUENCECANVAS_HPP_
#define SEQUENCECANVAS_HPP_

#include <QWidget>
#include <QGraphicsScene>
#include <QGraphicsView>

class SequenceCanvas : public QGraphicsView {

  Q_OBJECT

public:

  SequenceCanvas(QWidget* parent = nullptr);
  virtual ~SequenceCanvas() = default;

protected:

  void dragEnterEvent(QDragEnterEvent* event) override;
  void dropEvent(QDropEvent* event) override;

private:

  void createWidgets();
  void createLayout();

private:

  QGraphicsScene m_scene;
};

#endif // !SEQUENCECANVAS_HPP_
#include "SequenceCanvas.hpp"
#include <QString>
#include <QHBoxLayout>
#include <QDragEnterEvent>
#include <QMimeData>

SequenceCanvas::SequenceCanvas(QWidget* parent) :
  QGraphicsView(parent) {
  createWidgets();
  createLayout();
  setScene(&m_scene);
  setAcceptDrops(true);
}

void SequenceCanvas::dragEnterEvent(QDragEnterEvent* event) {
  event->acceptProposedAction(); // no filter at the moment I just want to test
}

void SequenceCanvas::dropEvent(QDropEvent* event) {
  int i = 0; // just for putting a breakpoint now. Its breakpoint is never raised
}

void SequenceCanvas::createWidgets() {

}

void SequenceCanvas::createLayout() {

}

即使在拖动过程中鼠标进入小部件时调用了dragEnterEvent,也不会调用dropEvent 方法,因此当我在SequenceCanvas 类中释放鼠标时,没有任何反应。

基本上我有两个问题:

  • 如何在我的 SequenceCanvas 类中引发 drop 事件,该类是 QGraphicsView 的子类?
  • 如何通过 drop 事件传递自定义数据(比如字符串向量),以便传递管理事件所需的所有信息?

编辑:

我错过了重新实现void dragMoveEvent(QDragMoveEvent* event) 方法。我已经添加了它,现在我收到了丢弃事件。我现在需要知道如何通过拖放事件传递自定义数据...感谢 zeFrenchy。

我现在的班级是:

SequenceCanvas::SequenceCanvas(QWidget* parent) :
  QGraphicsView(parent) {
  createWidgets();
  createLayout();
  setScene(&m_scene);
  setAcceptDrops(true);
  bool ok = acceptDrops();
}

///////////////////////////////////////////////////////////////////////////////
// VIRTUAL PROTECTED SECTION                                                 //
///////////////////////////////////////////////////////////////////////////////

void SequenceCanvas::dragEnterEvent(QDragEnterEvent* event) {
  event->acceptProposedAction();
}

void SequenceCanvas::dragMoveEvent(QDragMoveEvent* event) {
  event->acceptProposedAction();
}

void SequenceCanvas::dropEvent(QDropEvent* event) {
  int i = 0;
}

///////////////////////////////////////////////////////////////////////////////
// PRIVATE SECTION                                                           //
///////////////////////////////////////////////////////////////////////////////

void SequenceCanvas::createWidgets() {

}

void SequenceCanvas::createLayout() {

}

【问题讨论】:

  • 您的小部件上的 acceptDrops 是否设置为 true?
  • 我在SequenceDiagram 构造函数中调用setAcceptDrops(true);。如果我在它之后调用acceptDrops(),它会返回true
  • 哎呀,错过了????
  • 该文档对 DragMoveEvent 进行了说明(只需接受该操作就值得一试):如果小部件接受拖放事件并输入事件,则小部件将在拖动位于其边界内时重复接收拖动移动事件。小部件应检查事件以查看它提供的数据类型,并在适当的情况下调用 accept() 函数来接受丢弃。
  • 我怀疑拖放事件需要由视口而不是 QGraphicsView 本身来处理。尝试在视口小部件上安装事件过滤器或设置您自己的自定义视口小部件来处理相关事件。

标签: c++ qt drag-and-drop qgraphicsview qtreewidget


【解决方案1】:

文档中关于DragMoveEvent 的内容如下:

如果小部件接受放置事件和输入事件,则当拖动在其边界内时,小部件将重复接收拖动移动事件。小部件应检查事件以查看它提供的数据类型,并在适当的情况下调用 accept() 函数来接受放置。

因此,您应该为 dragMoveEvent(QDragMoveEvent* event) 提供覆盖,您只需接受建议的操作即可。

【讨论】:

    猜你喜欢
    • 2021-09-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-15
    • 1970-01-01
    相关资源
    最近更新 更多