The application GUI I working requires a combo box for user to select item. When the application starts, the combo box will show a hint text something like \"Please select\"
There is no way to set place holder text for QComboBox. But you can solve this problem. Use setEditText( const QString& )
slot for setting your text. If user selects an item in comboBox, item's text will be set. But if user selects the text, deletes it, and selects other control element (combo box looses its focus), your text won't be there anymore. Its possible to solve by inheriting from QComboBox
, and reimplementing focusOutEvent(...)
, where you check: if ( currentIndex() == -1 ) setEditText( tr( "Please select" ) );
. And dont forget to call QComboBox::focusOutEvent(...)
first.
There is an elegant solution if the QComboBox
is editable
:
myQComboBox->lineEdit()->setPlaceHolderText("Please select");
QComboBox
es that are not editable
do not have QLineEdit
s in them, so this would not work on those.
For newer versions of Qt try QComboBox::setPlaceholderText().
I happened to be working with an older version of Qt (5.11.3) on a Raspberry Pi and needed different solution.
Here is a working pyqt5 example using a proxy model to adjust for the extra item added as the placeholder. (credit to this answer):
import sys
from PyQt5.QtCore import Qt, QT_VERSION_STR, QAbstractProxyModel, QModelIndex, QItemSelection
from PyQt5.QtGui import QStandardItemModel, QStandardItem
from PyQt5.QtWidgets import (QApplication, QGridLayout, QWidget, QComboBox)
from typing import Any
class Main(QWidget):
def __init__(self):
super().__init__()
self.setGeometry(50,50,320,200)
self.setWindowTitle(f"Qt Version {QT_VERSION_STR}")
layout = QGridLayout()
cmbox = QComboBox()
model = QStandardItemModel()
for i in range(1, 11):
model.appendRow(QStandardItem(f"Item {i}"))
cmbox.setModel(ProxyModel(model, '---PlaceholderText---'))
cmbox.setCurrentIndex(0)
layout.addWidget(cmbox, 0, 0)
self.setLayout(layout)
self.show()
class ProxyModel(QAbstractProxyModel):
def __init__(self, model, placeholderText='---', parent=None):
super().__init__(parent)
self._placeholderText = placeholderText
self.setSourceModel(model)
def index(self, row: int, column: int, parent: QModelIndex = ...) -> QModelIndex:
return self.createIndex(row, column)
def parent(self, index: QModelIndex = ...) -> QModelIndex:
return QModelIndex()
def rowCount(self, parent: QModelIndex = ...) -> int:
return self.sourceModel().rowCount()+1 if self.sourceModel() else 0
def columnCount(self, parent: QModelIndex = ...) -> int:
return self.sourceModel().columnCount() if self.sourceModel() else 0
def data(self, index: QModelIndex, role: int = Qt.DisplayRole) -> Any:
if index.row() == 0 and role == Qt.DisplayRole:
return self._placeholderText
elif index.row() == 0 and role == Qt.EditRole:
return None
else:
return super().data(index, role)
def mapFromSource(self, sourceIndex: QModelIndex):
return self.index(sourceIndex.row()+1, sourceIndex.column())
def mapToSource(self, proxyIndex: QModelIndex):
return self.sourceModel().index(proxyIndex.row()-1, proxyIndex.column())
def mapSelectionFromSource(self, sourceSelection: QItemSelection):
return super().mapSelection(sourceSelection)
def mapSelectionToSource(self, proxySelection: QItemSelection):
return super().mapSelectionToSource(proxySelection)
def headerData(self, section: int, orientation: Qt.Orientation, role: int = Qt.DisplayRole):
if not self.sourceModel():
return None
if orientation == Qt.Vertical:
return self.sourceModel().headerData(section-1, orientation, role)
else:
return self.sourceModel().headerData(section, orientation, role)
def removeRows(self, row: int, count: int, parent: QModelIndex = ...) -> bool:
return self.sourceModel().removeRows(row, count -1)
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Main()
sys.exit(app.exec_())