簡體   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