Search code examples
c++qtqcomboboxqlistview

Add QListView to QComboBox for proper display of scrollbar


I have a combobox with long texts to fit into the combobox, so when I drop down, they are displayed like "very_long...long_text".

When I do:

QAbstractItemView* view = myCombo->view();
view->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOn );

The horizontal scrollbar appears, but it is inactive and the ...-s are still present at the middle of the strings.

This bugreport says that to get a horizontal scrollbar, a custom QListView can be used. So how should I construct this custom QListView, which I add then to the combobox?

I tried the following.

QListView* lw = new QListView( 0 );

QStandardItemModel* model = new QStandardItemModel;

QStandardItem *item = new QStandardItem( "long long long long long long long long long long long long text 1" );
QStandardItem *item2 = new QStandardItem( "long long long long long long long long long long long long text 2" );

model->insertRow( 0, item );
model->insertRow( 1, item2 );

lw->setModel( model );

QWidget* test = new QWidget( 0 );
test->setGeometry( 100, 100, 100, 150 );
test->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );

QGridLayout* layout = new QGridLayout;

test->setLayout( layout );

layout->addWidget( lw );
layout->setSizeConstraint( QLayout::SizeConstraint::SetFixedSize );

test->show();

Then I have something I want to see (unfortunately I'm not allowed to attach images), there is the scrollbar.

But when I want to add this to a combo:

QListView* lw = new QListView( 0 );

QStandardItemModel* model = new QStandardItemModel;

QStandardItem *item = new QStandardItem( "long long long long long long long long long long long long text 1" );
QStandardItem *item2 = new QStandardItem( "long long long long long long long long long long long long text 2" );

model->insertRow( 0, item );
model->insertRow( 1, item2 );

lw->setModel( model );

QWidget* test = new QWidget( 0 );
test->setWindowTitle( "test" );
test->setGeometry( 100, 100, 100, 150 );
test->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );

QGridLayout* layout = new QGridLayout;

test->setLayout( layout );

QComboBox* combo = new QComboBox;
combo->setGeometry( 0, 0, 80, 20 );
combo->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed );
combo->setView( lw );

layout->addWidget( combo );
layout->setSizeConstraint( QLayout::SizeConstraint::SetFixedSize );
test->show();

Then I get an empty combo. Thanks for any answers.


Solution

  • You need to set fixed width for the list view and update it when combo box is resized. Also you need to adjust list view's popup window width. You can do it using event filters. Here is a proof-of-concept implementation (don't write in such style in production):

    class Test_class : public QObject {
      Q_OBJECT
    public:
      Test_class() {}
      virtual ~Test_class() {}
    
      QComboBox* combo_box;
      QListView* list_view;
      bool eventFilter(QObject *object, QEvent *event) {
        if (object == combo_box && event->type() == QEvent::Resize) {
          list_view->setFixedWidth(combo_box->width());
        } else if (object == list_view && event->type() == QEvent::Show) {
          list_view->window()->resize(list_view->width(), list_view->window()->height());
        }
        return false;
      }
    };
    
    //...
    test->show();
    lw->setFixedWidth(200);
    lw->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
    
    Test_class test_object;
    test_object.combo_box = combo;
    test_object.list_view = lw;
    lw->installEventFilter(&test_object);
    combo->installEventFilter(&test_object);