我尝试实现基于drop的选择,其中用户可以将元素放在窗口小部件内的不同位置以启动某个过程。
我首先查看了Qt DropSite示例,并通过向DropArea添加大小为60x60px的其他标签来更改它。然后我根据http://qt-project.org/doc/qt-4.8/dnd.html中的示例(删除矩形)更改了方法DropArea::dragMoveEvent(QDragMoveEvent *event)
,而label
与我提到的dropFrame
相当。
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正确处理该过程?
答案 0 :(得分: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,您也可以这样做。只需在那里添加常规标签,然后将其属性作为自定义类的占位符。