Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
346 views
in Technique[技术] by (71.8m points)

python - How do i use QComboBox.setPlaceholderText?

In Qt 5.15 the placeholderText property was introduced - link to documentation

However using setPlaceholderText doesn't do anything for me. When running the code below i don't get any text in the QComboBox (unless of course i select one of the three items)

combo-box

Is this a bug or am i missing something? How can i make this work?

import sys
from PyQt5 import QtWidgets
from PyQt5 import QtCore


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()

        central_w = QtWidgets.QWidget()
        self.setCentralWidget(central_w)
        vbox = QtWidgets.QVBoxLayout()
        central_w.setLayout(vbox)

        self.combo_box = QtWidgets.QComboBox()
        self.combo_box.addItems(["one", "two", "three"])
        self.combo_box.setPlaceholderText("Some placeholder text here")
        self.combo_box.setCurrentIndex(-1)
        vbox.addWidget(self.combo_box)


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    main_window = MainWindow()
    main_window.show()
    app.exec_()

I have found no way of showing the placeholder text. I've tried having no items at all in the combo box but even this doesn't show the placeholder text


These are the versions i am running:

  • Qt: 5.15.2
  • PyQt (Python module) version: 5.15.2 (this happens to be the same as the Qt version but can sometimes differ slightly)
  • Python: "3.8.5 (default, Jul 28 2020, 12:59:40) [GCC 9.3.0]"
  • OS: Ubuntu 20.04.1 LTS (with Xfce)

PS: If you want to achieve a similar effect (that is: having a text on a clickable area which shows a drop-down with different options after being clicked) you can use a QPushButton with the setMenu function. Documentation: https://doc.qt.io/qt-5/qpushbutton.html#setMenu

question from:https://stackoverflow.com/questions/65830046/pyside2-5-15-qcombobox-setplaceholdertext-that-text-will-not-show

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Reviewing the modifications of the Qt source code, it is observed that to add the functionality of the placeHolderText in Qt 5.15.0, the currentText() was modified:

// https://code.qt.io/cgit/qt/qtbase.git/tree/src/widgets/widgets/qcombobox.cpp?h=5.15.0#n2344
QString QComboBox::currentText() const
{
    Q_D(const QComboBox);
    if (d->lineEdit)
        return d->lineEdit->text();
    else if (d->currentIndex.isValid())
        return d->itemText(d->currentIndex);
    else
        return d->placeholderText;
}

But that generates an undesirable effect that was reported in QTBUG-86580 so that functionality was removed in Qt 5.15.2:

QString QComboBox::currentText() const
{
    Q_D(const QComboBox);
    if (d->lineEdit)
        return d->lineEdit->text();
    if (d->currentIndex.isValid())
        return d->itemText(d->currentIndex);
    return {};
}

Forgetting to correct the side effect which is that the placeHolder is no longer visible. I have already reported the bug: QTBUG-90522.

Considering the above, there are the following alternatives:

  • Use PyQt5/PySide2 5.15.0 or 5.15.1.

  • Override the paintEvent method to set the placeHolderText as currentText:

import sys
from PyQt5 import QtCore, QtGui, QtWidgets

# or
# from PySide2 import QtCore, QtGui, QtWidgets


class ComboBox(QtWidgets.QComboBox):
    # https://code.qt.io/cgit/qt/qtbase.git/tree/src/widgets/widgets/qcombobox.cpp?h=5.15.2#n3173
    def paintEvent(self, event):
        
        painter = QtWidgets.QStylePainter(self)
        painter.setPen(self.palette().color(QtGui.QPalette.Text))

        # draw the combobox frame, focusrect and selected etc.
        opt = QtWidgets.QStyleOptionComboBox()
        self.initStyleOption(opt)
        painter.drawComplexControl(QtWidgets.QStyle.CC_ComboBox, opt)

        if self.currentIndex() < 0:
            opt.palette.setBrush(
                QtGui.QPalette.ButtonText,
                opt.palette.brush(QtGui.QPalette.ButtonText).color().lighter(),
            )
            if self.placeholderText():
                opt.currentText = self.placeholderText()

        # draw the icon and text
        painter.drawControl(QtWidgets.QStyle.CE_ComboBoxLabel, opt)


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()

        self.combo_box = ComboBox()
        self.combo_box.addItems(["one", "two", "three"])
        self.combo_box.setPlaceholderText("Some placeholder text here")
        self.combo_box.setCurrentIndex(-1)

        central_w = QtWidgets.QWidget()
        self.setCentralWidget(central_w)
        vbox = QtWidgets.QVBoxLayout(central_w)
        vbox.addWidget(self.combo_box)


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    main_window = MainWindow()
    main_window.show()
    app.exec_()

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...