简体   繁体   English

我如何使用 QComboBox.setPlaceholderText?

[英]How do i use QComboBox.setPlaceholderText?

In Qt 5.15 the placeholderText property was introduced - link to documentation在 Qt 5.15中引入了placeholderText属性 -文档链接

However using setPlaceholderText doesn't do anything for me .但是使用setPlaceholderText对我没有任何作用 When running the code below i don't get any text in the QComboBox (unless of course i select one of the three items)当运行下面的代码时,我没有在QComboBox中得到任何文本(当然除非我 select 三项之一)

组合框

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 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) PyQt(Python 模块)版本:5.15.2(这恰好与 Qt 版本相同,但有时会略有不同)
  • Python: "3.8.5 (default, Jul 28 2020, 12:59:40) \n[GCC 9.3.0]" Python:“3.8.5(默认,2020 年 7 月 28 日,12:59:40)\n[GCC 9.3.0]”
  • OS: Ubuntu 20.04.1 LTS (with Xfce)操作系统:Ubuntu 20.04.1 LTS(带 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 PS:如果你想达到类似的效果(即:在可点击区域有一个文本,点击后显示一个下拉菜单,其中包含不同的选项)你可以使用带有setMenu function的QPushButton 。文档: https:// doc.qt.io/qt-5/qpushbutton.html#setMenu

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:查看 Qt 源代码的修改,观察到为了在 Qt 5.15.0 中添加 placeHolderText 的功能,currentText() 被修改:

// 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:但这会产生QTBUG-86580中报告的不良影响,因此在 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.忘记纠正 placeHolder 不再可见的副作用。 I have already reported the bug: QTBUG-90522 .我已经报告了这个错误: QTBUG-90522

Considering the above, there are the following alternatives:考虑到上述情况,有以下替代方案:

  • Use PyQt5/PySide2 5.15.0 or 5.15.1.使用 PyQt5/PySide2 5.15.0 或 5.15.1。

  • Override the paintEvent method to set the placeHolderText as currentText:重写 paintEvent 方法将 placeHolderText 设置为 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_()

As addendum to eyllanesc's answer, which is very precise, here is just a bit simpler workaround for the placeholder text bug in Qt 5.15.2, which is very important version because it is the last non-commercial version ever for Qt5.作为 eyllanesc 答案的附录,非常精确,这里是 Qt 5.15.2 中占位符文本错误的一个更简单的解决方法,这是非常重要的版本,因为它是 Qt5 的最后一个非商业版本。 It is C++ but it is easy to translate to Python.它是 C++ 但很容易翻译成 Python。

#include <QApplication>
#include <QComboBox>
#include <QLabel>
#include <QVBoxLayout>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QComboBox combo;
    combo.show();
    combo.addItem("AAAA");
    combo.addItem("BBBB");

    // The following line does not work e.g. in Qt 5.15.2.
    //combo.setPlaceholderText("Select something...");

    // This is a simple workaround:
    auto space = QString(" ");
    auto placeholder = new QLabel(space + "Select something...");
    combo.setLayout(new QVBoxLayout());
    combo.layout()->setContentsMargins(0, 0, 0, 0);
    combo.layout()->addWidget(placeholder);
    QObject::connect(&combo, &QComboBox::currentIndexChanged, &combo, [placeholder](int index){ placeholder->setVisible(index == -1); });
    combo.setCurrentIndex(-1);

    return a.exec();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM