2
votes

I've spent better half of today trying to resolve seemingly trivial QListWidget behavior customization: when used presses mouse left button and moves mouse cursor, the content of ListWidget is scrolled and selection is moved to another item that happens to appear under mouse cursor. I am alright with scrolling, but I want to avoid selecting all consequtive items because this causes timely operation in my program. Finally I would like to keep list content scrolling on mouse press and move, but select items only by clicking directly on them. Drag-n-drop is disabled for this list (which is default behavior) and it should be; I've tried to disable it explicitly: no changes whatsoever.

I have read all available docs on Qt related classes like QListWidget, QListWidgetItem, QListView, you name it! Tried to make sense of source code for these widgets; dug up StackOverflow and Google... but sadly no result :(

Here is all relevant code for my QListWidget: single selection, nothing fancy:

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 if that's somehow relevant, both Win and Mac platforms share similar behavior.

2
Have you tried using the eventFilter function to filter out the event that is causing issues?user3147395
What event do you mean? There are mouse Press, mouseMove and mouseRelease, classic combination. I would refrain from writing my own custom version of ListWidget if there is a simple way to custmomize its behavior (which I failed to find). Before this one I made 4 other customizations to the same ListWidget, all of them took like 2hrs each to get through docs, samples, etc. and resulted in one line of code: set this flag or change that setting. I really hope to find something similar.Andriy Gulé
Sorry, I don't know a flag that will implement this behavior, but I don't have much experience with ListWidgets, so there may be a flag that I don't know about.user3147395

2 Answers

2
votes

For the sake of whoever stumbles upon the same question, here is my solution: subclass QListWidget and make child class ignore mouseMove events when leftButton is pressed.

Header:

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);
};

Source:

//////////////////////////////////////////////////////////////////////////
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);
}
//////////////////////////////////////////////////////////////////////////

Usage is trivial, for as many List Widgets as you need:

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

Want it done right? then do it yourself! :)

0
votes

Your solution killed scrolling for me. I am using QListView. Here's another way:

In the constructor of the QListView's parent:

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

In the connected slot:

on_listview_clicked(const QModelIndex &index)
{
    if (index.isValid())
    {
        ui->listView->selectionModel->select(index, QItemSelectionModel::Toggle | QItemSelectionModel::Rows);

    }
}

So, it only selects on a click.