繁体   English   中英

为什么拖放不调用dropEvent?

[英]Why drag&drop does not called dropEvent?

我想没有人知道这件事。 同一个问题问了两天,没人回答。

我找到了一个关于拖放的 toDoList 项目。 我想知道我能得到拖放的项目吗? 我正在阅读文档 2 天。 我实施这些方法。

protected:
    void dragEnterEvent( QDragEnterEvent *anEvent ) override;
    void dragMoveEvent( QDragMoveEvent *anEvent ) override;
    void dragLeaveEvent( QDragLeaveEvent *anEvent ) override;
    void dropEvent( QDropEvent *anEvent ) override;

有 2 个列表视图和工具栏。 我将添加和删除添加到工具栏。
我可以拖放,但我无法获取拖动项目的文本。 这是主要代码。 我真的很想知道,我们是否正确地覆盖了方法。 但是我们没有将方法与某事联系起来。 该方法如何工作?

todolist::todolist(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::todolist)
{
    QWidget* pWidget = new QWidget(this);
        pWidget->setStyleSheet("background-color: #ECF0F1");
        setCentralWidget(pWidget);

        QVBoxLayout* pMainLayout = new QVBoxLayout();
        pWidget->setLayout(pMainLayout);

        QLabel* pwTitle = new QLabel("To Do List", this);
        pMainLayout->addWidget(pwTitle);
        pwTitle->setAlignment(Qt::AlignCenter);
        pwTitle->setStyleSheet("font-size: 30pt; margin: 10%;");

        QHBoxLayout* pHLayoutLabels = new QHBoxLayout();
        pMainLayout->addLayout(pHLayoutLabels);

        QLabel* plblPending = new QLabel("Pending", this);
        plblPending->setStyleSheet("font-size: 15pt;");
        pHLayoutLabels->addWidget(plblPending);

        QLabel* plblCompleted = new QLabel("Completed", this);
        plblCompleted->setStyleSheet("font-size: 15pt;");
        pHLayoutLabels->addWidget(plblCompleted);

        QHBoxLayout* pHLayout = new QHBoxLayout();
        pMainLayout->addLayout(pHLayout);

        m_pwPending = new QListView(this);
        m_pwPending->setDragEnabled(true);
        m_pwPending->setAcceptDrops(true);
        m_pwPending->setDropIndicatorShown(true);
        m_pwPending->setDefaultDropAction(Qt::MoveAction);
        pHLayout->addWidget(m_pwPending);

        m_pwCompleted = new QListView(this);
        m_pwCompleted->setDragEnabled(true);
        m_pwCompleted->setAcceptDrops(true);
        m_pwCompleted->setDropIndicatorShown(true);
        m_pwCompleted->setDefaultDropAction(Qt::MoveAction);
        pHLayout->addWidget(m_pwCompleted);

        m_pwPending->setModel(new QStringListModel());
        m_pwCompleted->setModel(new QStringListModel());

        m_pwPending->setStyleSheet
        ("QListView { font-size: 20pt; font-weight: bold; }"
         "QListView::item { background-color: #E74C3C; padding: 10%;"
         "border: 1px solid #C0392B; }"
         "QListView::item::hover { background-color: #C0392B }");

        m_pwCompleted->setStyleSheet
        ("QListView { font-size: 20pt; font-weight: bold; }"
         "QListView::item { background-color: #2ECC71; padding: 10%;"
         "border: 1px solid #27AE60; }"
         "QListView::item::hover { background-color: #27AE60 }");


        QToolBar* pToolBar = new QToolBar(this);
        addToolBar(pToolBar);

        m_pActAdd = new QAction(this);
            m_pActAdd->setIcon(QIcon(":/resources/add.png"));
            connect(m_pActAdd, &QAction::triggered, this, &todolist::onAdd);

            m_pActRemove = new QAction(this);
            m_pActRemove->setIcon(QIcon(":/resources/remove.png"));
            connect(m_pActRemove, &QAction::triggered, this, &todolist::onRemove);

        pToolBar->addAction(m_pActAdd);
        pToolBar->addAction(m_pActRemove);

        setAcceptDrops(true);
}

void todolist::onAdd()
{
    m_pwPending->model()->insertRow(m_pwPending->model()->rowCount());
    QModelIndex oIndex = m_pwPending->model()->index(
    m_pwPending->model()->rowCount() - 1, 0);

    m_pwPending->edit(oIndex);

}

void todolist::onRemove()
{
    QModelIndex oIndex = m_pwPending->currentIndex();
    m_pwPending->model()->removeRow(oIndex.row());
}
void todolist::dropEvent(QDropEvent* event) {
    const QMimeData* mimeData = event->mimeData();
    QString temp;
    if(mimeData->hasText()) {
        temp = mimeData->text();
    }

    QMessageBox::information(this,"x",temp);
}

void todolist::dragEnterEvent(QDragEnterEvent *anEvent)
{
    anEvent->setAccepted(true);
}

void todolist::dragMoveEvent(QDragMoveEvent *anEvent)
{

}

void todolist::dragLeaveEvent(QDragLeaveEvent *anEvent)
{

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

QMimeData* ListModel::mimeData(const QModelIndexList& qMIndices) const {

  QMimeData* const pQMimeData = new QMimeData;
  QString qText;

  for (const QModelIndex& qMIndex : qMIndices) {
    qText += data(qMIndex, Qt::DisplayRole).toString() + "\n";
  }
  pQMimeData->setText(qText);

  std::cout << "1" << std::endl;
  draggedData = qText;
  return pQMimeData;
}

draggedData = qText; 此行会引发错误。

我使用了推荐的网站Qt Doc。 - 模型/视图编程 - 使用拖放和项目视图来编织一个小的示例应用程序,以满足 OP 的要求。

我的 MCVE testQListViewDragNDrop.cc

#include <QtWidgets>

class ListModel: public QStringListModel {

  public:
    using QStringListModel::QStringListModel;

  protected:
    // for drag site
  
    // encodes dragged items (different from default).
    virtual QMimeData* mimeData(const QModelIndexList& qMIndices) const override;
    
    // for drop site

    // returns which kind of drop actions are supported.
    virtual Qt::DropActions supportedDropActions() const override
    {
      return Qt::MoveAction;
    }

    // checks whether certain dragged MIME data is droppable.
    virtual bool canDropMimeData(
      const QMimeData* pQMimeData, // dragged data
      Qt::DropAction action, // not evaluated
      int row, // not evaluated
      int column, // uninteresting for lists (but relevant for tables and trees)
      const QModelIndex& qMIndex) // uninteresting for lists (but relevant for trees)
      const override
    {
      return pQMimeData->hasText();
    }

    // drops dragged MIME data into model.
    virtual bool dropMimeData(
      const QMimeData* pQMimeData, // dropped data
      Qt::DropAction action, // not evaluated
      int row, // where to insert
      int column, // uninteresting for lists (but relevant for tables and trees)
      const QModelIndex& qMIndex) // uninteresting for lists (but relevant for trees)
      override;
};

QMimeData* ListModel::mimeData(const QModelIndexList& qMIndices) const
{
  QMimeData* const pQMimeData = new QMimeData;
  QString qText;
  for (const QModelIndex& qMIndex : qMIndices) {
    qText += data(qMIndex, Qt::DisplayRole).toString() + "\n";
  }
  pQMimeData->setText(qText);
  return pQMimeData;
}

bool ListModel::dropMimeData(
  const QMimeData* pQMimeData, Qt::DropAction action,
  int row, int, const QModelIndex& qMIndex)
{
  // get text from mime data
  const QString qText = pQMimeData->text().trimmed();
  if (qText.isEmpty()) return true;
  // split text into lines
  const QStringList qLines = qText.split(QChar('\n'));
  const int n = qLines.size();
  // fix row
  if (qMIndex.isValid()) row = qMIndex.row(); // dropped on row
  if (row < 0 || row > rowCount()) row = rowCount();
  // insert list into list model
  if (insertRows(row, n)) {
    for (const QString& qLine : qLines) {
      setData(index(row, 0), qLine);
    }
  }
  // done
  return true;
}

QStringList makeSampleData()
{
  QStringList qList;
  qList
    << "Read the Qt doc."
    << "Write CMakeLists.txt"
    << "Write testQListViewDragNDrop.cc"
    << "Test and Debug"
    << "Fix bugs"
    << "Test and Debug"
    << "Fix bugs"
    << "Test and Debug"
    << "Fix bugs"
    << "Test and Debug"
    << "Fix bugs"
    << "Test and Debug"
    << "Fix bugs"
    << "Write SO answer";
  return qList;
}

int main(int argc, char** argv)
{
  QApplication app(argc, argv);
  // setup GUI
  QWidget qWinMain;
  qWinMain.setWindowTitle("Test QListView Drag & Drop");
  qWinMain.resize(640, 480);
  QGridLayout qGrid;
  qGrid.addWidget(new QLabel("<b>To Do</b>"), 0, 0);
  qGrid.addWidget(new QLabel("<b>Done</b>"), 0, 1);
  qGrid.setRowStretch(1, 1);
  QListView qListToDo; // drag site
  ListModel qListModelToDo;
  qListModelToDo.setStringList(makeSampleData());
  qListToDo.setModel(&qListModelToDo);
  qListToDo.setDragEnabled(true); // allow drag in ToDo list
  qGrid.addWidget(&qListToDo, 1, 0);
  QListView qListDone; // drop site
  ListModel qListModelDone;
  qListDone.setModel(&qListModelDone);
  qListDone.viewport()->setAcceptDrops(true); // allow drops
  qListDone.setDropIndicatorShown(true); // adjust drop indicator
  qGrid.addWidget(&qListDone, 1, 1);
  qWinMain.setLayout(&qGrid);
  qWinMain.show();
  // run-time loop
  return app.exec();
}

演示 Session:

演示环节的GIF动画

笔记:

  • 不需要自定义列表视图。 &emdash; 可以使用QListView ,但必须配置 Drag 和 Drop。 因此,与我的示例代码相比,可以将QListView配置为拖放
  • 与我在评论中推荐的相反,无可否认,没有必要覆盖dragEnterEvent() (或公司)。 这些事件已经在QListView中被覆盖,并咨询相应的 model 以获得拖放支持。
  • 甚至没有必要的自定义字符串列表 model。 在为拖放配置列表视图之后,它也开始与QStringListModel一起使用。 我派生QStringListModel来演示如何自定义拖放。
  • 重写的函数mimeData()canDropMimeData()dropMimeData()也不是必需的。 即使没有它们,拖放也可以工作。 (我在添加它们之前对此进行了测试。)我不知道使用什么 MIME 数据来传达拖动的内容。 由于在我的示例中拖放站点和拖放站点是相同的小部件 class,因此可以拖放拖动的数据(但它存储在内部)也就不足为奇了。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM