在单击+拖动时禁用 QListWidget 中的自动选择项目

Posted

技术标签:

【中文标题】在单击+拖动时禁用 QListWidget 中的自动选择项目【英文标题】:Disable auto-selecting items in QListWidget on click+drag 【发布时间】:2016-03-25 20:38:38 【问题描述】:

我今天花了大半的时间试图解决看似微不足道的 QListWidget 行为定制:当使用时按下鼠标左键并移动鼠标光标,ListWidget 的内容会滚动,并且选择会移动到恰好出现在鼠标下的另一个项目光标。我可以滚动,但我想避免选择所有后续项目,因为这会导致我的程序及时操作。最后,我想保持列表内容在鼠标按下和移动时滚动,但只能通过直接单击它们来选择项目。 此列表禁用拖放(这是默认行为),它应该是;我试图明确禁用它:没有任何变化。

我已经阅读了所有关于 Qt 相关类的可用文档,例如 QListWidget、QListWidgetItem、QListView,应有尽有!试图理解这些小部件的源代码;挖了 *** 和 Google ......但遗憾的是没有结果 :(

这是我的 QListWidget 的所有相关代码:单选,没什么花哨的:

QListWidget* categoryListWidget;
...
categoryListWidget = new QListWidget();
categoryListWidget->move(offsetX, offsetY);
categoryListWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
categoryListWidget->setSelectionMode(QAbstractItemView::SingleSelection);
categoryListWidget->setFocusPolicy(Qt::NoFocus);
categoryListWidget->setStyleSheet(listQSS);
...
categoryListWidget->clear();
new QListWidgetItem(tr("1 - Sample Category 1"), categoryListWidget);
new QListWidgetItem(tr("2 - Sample Category 2"), categoryListWidget);
new QListWidgetItem(tr("3 - Sample Category 3 with a very long name"), categoryListWidget);
new QListWidgetItem(tr("4 - Sample Category 4"), categoryListWidget);

C++/Qt 5.5 如果这有点相关,Win 和 Mac 平台都有相似的行为。

【问题讨论】:

您是否尝试过使用 eventFilter 函数来过滤掉导致问题的事件? 你是什么意思?有鼠标Press、mouseMove和mouseRelease,经典组合。如果有一种简单的方法可以自定义其行为(我没有找到),我会避免编写我自己的自定义版本的 ListWidget。在此之前,我对同一个 ListWidget 进行了 4 次其他自定义,所有这些都花费了大约 2 小时来完成文档、示例等,并产生了一行代码:设置此标志或更改该设置。我真的希望能找到类似的东西。 抱歉,我不知道会实现这种行为的标志,但我对 ListWidgets 没有太多经验,所以可能有一个我不知道的标志。跨度> 【参考方案1】:

为了遇到同样问题的人,这里是我的解决方案:子类 QListWidget 并让子类在按下 leftButton 时忽略 mouseMove 事件。

标题:

class QtListWidget: public QListWidget
 // QListWidget clone that suppresses item selection on mouse click+drag
private:
    bool    mousePressed;
public:
     QtListWidget():QListWidget(), mousePressed(false) 
protected:
    virtual void mousePressEvent(QMouseEvent *event);
    virtual void mouseMoveEvent(QMouseEvent *event);
    virtual void mouseReleaseEvent(QMouseEvent *event);
;

来源:

//////////////////////////////////////////////////////////////////////////
void QtListWidget::mousePressEvent(QMouseEvent *event)
//    qDebug() << "QtListWidget::mousePressEvent";
    if(event->button() == Qt::LeftButton)
        mousePressed = true;
    QListWidget::mousePressEvent(event);


void QtListWidget::mouseMoveEvent(QMouseEvent *event)
//    qDebug() << "QtListWidget::mouseMoveEvent";
    if(!mousePressed)   // disable click+drag
        QListWidget::mouseMoveEvent(event);


void QtListWidget::mouseReleaseEvent(QMouseEvent *event)
//    qDebug() << "QtListWidget::mouseReleaseEvent";
    if(event->button() == Qt::LeftButton)
        mousePressed = false;
    QListWidget::mouseReleaseEvent(event);

//////////////////////////////////////////////////////////////////////////

使用很简单,您可以根据需要使用尽可能多的列表小部件:

QtListWidget* categoryListWidget;
// all original code above would still work as expected
...

想要正确完成吗?然后自己做! :)

【讨论】:

【参考方案2】:

您的解决方案让我无法滚动。我正在使用 QListView。这是另一种方式:

在 QListView 的父级的构造函数中:

ui->listView->setSelectionMode(QAbstractItemView::NoSelection);
connect(ui->listView, SIGNAL(clicked(QModelIndex)), this, SLOT(on_listview_clicked(QModelIndex)));

在连接的插槽中:

on_listview_clicked(const QModelIndex &index)

    if (index.isValid())
    
        ui->listView->selectionModel->select(index, QItemSelectionModel::Toggle | QItemSelectionModel::Rows);

    

所以,它只会在点击时选择。

【讨论】:

以上是关于在单击+拖动时禁用 QListWidget 中的自动选择项目的主要内容,如果未能解决你的问题,请参考以下文章

在 QHeaderView 和 QListWidget 之间拖放列

在PyQt5中的QTreeWidget和QListWidget之间拖动项目?

可拖动按钮时如何将单击事件设置为禁用?

QListWidget 向下滚动列表后拖动

将单击与 JQuery 中的可拖动功能分开

在 QListWidget 项目上绘制边框使文本在单击时消失