2

我尝试实现基于拖放的选择,用户可以将元素拖放到小部件内的不同位置以启动某些过程。我首先查看 Qt DropSite 示例,然后通过向 DropArea 添加一个大小为 60x60px 的标签来更改它。然后我根据http://qt-project.org/doc/qt-4.8/dnd.htmlDrop RectanglesDropArea::dragMoveEvent(QDragMoveEvent *event)部分)中的示例更改了方法,而我与提到的.labeldropFrame

DropArea::DropArea(QWidget *parent)
    : QLabel(parent)
{
    setMinimumSize(200, 200);
    setFrameStyle(QFrame::Sunken | QFrame::StyledPanel);
    setAlignment(Qt::AlignCenter);
    setAcceptDrops(true);
    setAutoFillBackground(true);
    clear();

    label = new QLabel("Target", this);
    label->setFixedSize(60, 60);
    label->setAutoFillBackground(true);
    label->setBackgroundRole(QPalette::Light);
    label->move(80, 60);
}

void DropArea::dragMoveEvent(QDragMoveEvent *event)
{
  if(event->answerRect().intersects(label->geometry()))
  {
    setText(tr("<drop content>"));
    setBackgroundRole(QPalette::Highlight);

    event->acceptProposedAction();
    emit changed(event->mimeData());
  }
}

根据文档,必须接受dragEnterEvent 中的QDragEnterEvent 才能接收dragMoveEvents。我接受了该事件,但这会在输入 DropArea 后立即将光标更改为复制数据符号,并且在整个小部件上都接受放置操作,而不仅仅是标签。

我是否必须自己处理光标更改,还是我忽略了一些细节以允许 Qt 正确处理该过程?

4

1 回答 1

1

我不确定我是否正确地回答了这个问题。不过我会试一试。

每当我尝试在非子类标准小部件上捕获诸如拖放之类的事件时,我更喜欢使用事件过滤器。

DropArea::DropArea(QWidget *parent)
: QLabel(parent)
{
  // ... stripped your example just showing the difference
  label->installEventFilter(this);
  label->setAcceptDrops(true);
}


bool DropArea::eventFilter(QObject *pFilterObj,QEvent *pEvent)
{
  if ( (pFilterObj == label) && (pEvent->type() == QEvent::DragEnter) )
  {
    QDragEnterEvent *dEvent = (QDragEnterEvent*)pEvent;
    if (dEvent->mimeData()->hasText()) dEvent->acceptProposedAction();
  }
  if ( (pFilterObj == label) && (pEvent->type() == QEvent::Drop) )
  {
    QDropEvent *dEvent = (QDropEvent*)pEvent;
    qDebug() << dEvent->mimeData()->text();
  }
  // give the default handlers a chance to act too
  return false;
}

如果您在应用程序中使用多个拖放标签,最好继承 QLabel 并覆盖拖放事件。即使使用 Qt Creator,您也可以这样做。只需在此处添加一个常规标签,并将其属性作为自定义类的占位符。

于 2014-05-29T11:54:16.833 回答