alphanumeric
alphanumeric

Reputation: 19329

How to hide QComboBox items instead of clearing them out

I can't find a way to hide QComboBox items. So far the only way to filter its items out is to delete the existing ones (with .clear() method). And then to rebuild the entire QComboBox again using its .addItem() method.

I would rather temporary hide the items. And when they are needed to unhide them back. Is hide/unhide on QCombobox items could be accomplished?

Upvotes: 6

Views: 15655

Answers (7)

Kef
Kef

Reputation: 440

In case someone still looking for an answer:

By default, QComboBox uses QListView to display the popup list and QListView has the setRowHidden() method:

qobject_cast<QListView *>(comboBox->view())->setRowHidden(0, true);

Edit: fix code according to @Tobias Leupold's comment.
Edit: Python version:

# hide row
view = comboBox.view()
view.setRowHidden(row, True)

# disable item
model = comboBox.model()
item = model.item(row)
item.setFlags(item.flags() & ~Qt.ItemIsEnabled)

# enable item
view.setRowHidden(row, false)
item.setFlags(item.flags() | Qt.ItemIsEnabled)

Upvotes: 14

Mecgrad
Mecgrad

Reputation: 64

I came across this thread after getting frustrated with a lack of hide functionality that would keep the item indexing etc. I got it to work based on @Kef and @CJCombrink answers. This is basically just a python translation.

I had a problem with qobject_cast. Solved it by setting .setView(QListView()) to the QComboBox.

combo=QComboBox()
combo.setView(QListView())

hide:

combo.view().setRowHidden(rowindex,True)
tmp_item=combo.model().item(rowindex)
tmp_item.setFlags(tmp_item.flags() & ~Qt.ItemIsEnabled)

unhide:

combo.view().setRowHidden(rowindex,False)
tmp_item=combo.model().item(rowindex)
tmp_item.setFlags(tmp_item.flags() | Qt.ItemIsEnabled)

I decided to subclass the QComboBox and add the hide functionality. Bellow is an use example for testing. You are welcome to use it. I make no assurances.

import sys
from PySide2.QtWidgets import *
from PySide2.QtCore import *
from PySide2.QtGui import *

#subclassed QComboBox with added hide row functionality
class ComboBox_whide(QComboBox):
    def __init__(self):
        super().__init__()
        self.setView(QListView())#default self.view() is a QAbstractItemView object which is missing setRowHidden, therefore a QListView needs to be set 
    def hide_row_set(self,row,value=True):
        """sets the row accesibility
        value=True hides the row"""
        self.view().setRowHidden(row,value)#hides the item from dropdown, however the item is stil accesible by moving down with arrow keys or mouse wheel. The following disables solves that
        tmp_item=self.model().item(row)
        if value:#hide -> disable
            tmp_item.setFlags(tmp_item.flags() & ~Qt.ItemIsEnabled)
        else:#enable
            tmp_item.setFlags(tmp_item.flags() | Qt.ItemIsEnabled)
    def hide_row_toggle(self,row):
        """toggles the row accesibility"""
        if self.view().isRowHidden(row):#is hidden, therefore make available
            self.hide_row_set(row,False)
        else:#is not hidden, therefore hide
            self.hide_row_set(row,True)

class Main(QMainWindow):
    def __init__(self):
        super().__init__()
        cwidg=QWidget()
        clayer=QVBoxLayout()
        cwidg.setLayout(clayer)
        self.setCentralWidget(cwidg)
        #button for testing
        self.btn=QPushButton('Button')
        self.btn.setCheckable(True)
        clayer.addWidget(self.btn)
        
        #subclassed QComboBox
        self.combo=ComboBox_whide()
        for n in range(3):#add 3 items with tooltips
            self.combo.addItem('item%i'%n)
            self.combo.setItemData(n,'tip%i'%n,Qt.ToolTipRole)
        clayer.addWidget(self.combo)
        
        #button test function - choose either or for testing
        self.btn.clicked.connect(self.btn_clicked)
        #uncomment for add/remove example self.btn.clicked.connect(self.remove_add_item)
        
    def btn_clicked(self):
        self.combo.hide_row_toggle(1)
    def remove_add_item(self):# here for naive comparison and to show why removing and adding is not ok
        if self.combo.count()==3:
            self.combo.removeItem(1)
        else:
            self.combo.addItem('new')#new "item1" withouth the ToolTip
        
if __name__ == '__main__':
    app = QApplication.instance()
    if app is None:#Pyside2 ipython notebook check
        app = QApplication(sys.argv)
    main = Main()
    main.show()
    app.exec_()
    

Upvotes: 0

CJCombrink
CJCombrink

Reputation: 3950

To build on what @kef answered:

(excuse the C++ on the python question)

By default the QComboBox will use a QListView for the view, thus you can do the following:

QListView* view = qobject_cast<QListView *>(combo->view());
Q_ASSERT(view != nullptr);
view->setRowHidden(row, true);

The one drawback with the above is, that even though the item will be hidden from the popup, the user can still select it using the mouse wheel. To overcome this add the following for the hidden row:

QStandardItemModel* model = qobject_cast<QStandardItemModel*>(combo->model());
Q_ASSERT(model != nullptr);
QStandardItem* item = model->item(row);
item->setFlags(item->flags() & ~Qt::ItemIsEnabled);

With the above the row will be hidden and the user will not be able to scroll to it with the mouse wheel.

To unhide it, just do the reverse:

view->setRowHidden(row, false);
item->setFlags(item->flags() | Qt::ItemIsEnabled);

Upvotes: 8

Tony Rietwyk
Tony Rietwyk

Reputation: 65

To show the item again:

comboBox->setItemData(row, QVariant(), Qt::SizeHintRole);

Note: changing the SizeHintRole doesn't work on OS X.

Upvotes: 0

ljc123456gogo
ljc123456gogo

Reputation: 61

Althought there is no direct way to hide the item of the QComboBox, but you can use QComboBox::setItemData and set the size to (0,0) to hide the item of QComboBox:

comboBox->setItemData(row, QSize(0,0), Qt::SizeHintRole);

Upvotes: 1

esorton
esorton

Reputation: 1572

You can use the removeItem() method to remove an item from the QComboBox.

void QComboBox::removeItem ( int index )

Removes the item at the given index from the combobox. This will update the current index if the index is removed.

This function does nothing if index is out of range.

If you don't know the index, use the findText() method.

There are no hide/unhide methods for QComboBox items.

Upvotes: 1

James Mertz
James Mertz

Reputation: 8759

Use the setVisible() to alter the visibility of your object:

.setVisible(False) # Not Visible
.setVisible(True) # Visible

Upvotes: 0

Related Questions