如何在 QComboBox 上设置不可选择的默认文本?

发布于 2024-12-07 18:00:37 字数 201 浏览 2 评论 0原文

使用填充有项目的常规 QComboBox,如果 currentIndex 设置为 -1,则小部件为空。如果在组合框中显示初始描述性文本(例如“--选择国家/地区--”、“--选择主题--”等),而该文本未显示在下拉列表中,则非常有用。

我在文档中找不到任何内容,也找不到任何先前的问题及其答案。

Using a regular QComboBox populated with items, if currentIndex is set to -1, the widget is empty. It would be very useful to instead have an initial descriptive text visible in the combo box(e.g. "--Select Country--", "--Choose Topic--", etc.) which is not shown in the dropdown list.

I couldn't find anything in the documentation, nor any previous questions with answers.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

稳稳的幸福 2024-12-14 18:00:37

组合框 API 中似乎没有预期这种情况。但凭借底层模型的灵活性,您似乎应该能够将您的 --Select Country-- 添加为第一个“合法”项目,然后阻止用户选择它:

QStandardItemModel* model =
        qobject_cast<QStandardItemModel*>(comboBox->model());
QModelIndex firstIndex = model->index(0, comboBox->modelColumn(),
        comboBox->rootModelIndex());
QStandardItem* firstItem = model->itemFromIndex(firstIndex);
firstItem->setSelectable(false);

取决于具体的行为如果您愿意,您可能需要使用 setEnabled 来代替。或者我个人更喜欢它,如果它只是一个不同的颜色项目,我可以将其设置回:

Qt,如何更改 QComboBox 的一项的文本颜色? (C++)

(我不喜欢当我点击某个东西然后陷入无法回到原来位置的地方,即使它是一个尚未选择的状态! )

It doesn't appear that case was anticipated in the Combo Box API. But with the underlying model flexibility it seems you should be able to add your --Select Country-- as a first "legitimate" item, and then keep it from being user selectable:

QStandardItemModel* model =
        qobject_cast<QStandardItemModel*>(comboBox->model());
QModelIndex firstIndex = model->index(0, comboBox->modelColumn(),
        comboBox->rootModelIndex());
QStandardItem* firstItem = model->itemFromIndex(firstIndex);
firstItem->setSelectable(false);

Depending on what precise behavior you want, you might want to use setEnabled instead. Or I'd personally prefer it if it was just a different color item that I could set it back to:

Qt, How do I change the text color of one item of a QComboBox? (C++)

(I don't like it when I click on something and then get trapped to where I can't get back where I was, even if it's a nothing-selected-yet-state!)

反话 2024-12-14 18:00:37

执行类似操作的一种方法是设置占位符:

comboBox->setPlaceholderText(QStringLiteral("--Select Country--"));
comboBox->setCurrentIndex(-1);

这样您就有了一个无法选择的默认值。

输入图像描述这里

One way you can do something similar is to set a placeholder:

comboBox->setPlaceholderText(QStringLiteral("--Select Country--"));
comboBox->setCurrentIndex(-1);

This way you have a default that cannot be selected.

enter image description here

以酷 2024-12-14 18:00:37

在这里留下我的 PyQt5 解决方案。创建一个代理模型并将所有行下移一位,并在第 0 行返回默认值。

class NullRowProxyModel(QAbstractProxyModel):
    """Creates an empty row at the top for null selections on combo boxes
    """

    def __init__(self, src, text='---', parent=None):
        super(NullRowProxyModel, self).__init__(parent)
        self._text = text
        self.setSourceModel(src)

    def mapToSource(self, proxyIndex: QModelIndex) -> QModelIndex:
        if self.sourceModel():
            return self.sourceModel().index(proxyIndex.row()-1, proxyIndex.column())
        else:
            return QModelIndex()

    def mapFromSource(self, sourceIndex: QModelIndex) -> QModelIndex:
        return self.index(sourceIndex.row()+1, sourceIndex.column())

    def data(self, proxyIndex: QModelIndex, role=Qt.DisplayRole) -> typing.Any:
        if proxyIndex.row() == 0 and role == Qt.DisplayRole:
            return self._text
        elif proxyIndex.row() == 0 and role == Qt.EditRole:
            return None
        else:
            return super(NullRowProxyModel, self).data(proxyIndex, role)

    def index(self, row: int, column: int, parent: QModelIndex = ...) -> QModelIndex:
        return self.createIndex(row, column)

    def parent(self, child: 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 headerData(self, section: int, orientation: Qt.Orientation, role: int = ...) -> typing.Any:
        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)

Leaving my solution here from PyQt5. Create a proxy model and shift all the rows down one, and return a default value at row 0.

class NullRowProxyModel(QAbstractProxyModel):
    """Creates an empty row at the top for null selections on combo boxes
    """

    def __init__(self, src, text='---', parent=None):
        super(NullRowProxyModel, self).__init__(parent)
        self._text = text
        self.setSourceModel(src)

    def mapToSource(self, proxyIndex: QModelIndex) -> QModelIndex:
        if self.sourceModel():
            return self.sourceModel().index(proxyIndex.row()-1, proxyIndex.column())
        else:
            return QModelIndex()

    def mapFromSource(self, sourceIndex: QModelIndex) -> QModelIndex:
        return self.index(sourceIndex.row()+1, sourceIndex.column())

    def data(self, proxyIndex: QModelIndex, role=Qt.DisplayRole) -> typing.Any:
        if proxyIndex.row() == 0 and role == Qt.DisplayRole:
            return self._text
        elif proxyIndex.row() == 0 and role == Qt.EditRole:
            return None
        else:
            return super(NullRowProxyModel, self).data(proxyIndex, role)

    def index(self, row: int, column: int, parent: QModelIndex = ...) -> QModelIndex:
        return self.createIndex(row, column)

    def parent(self, child: 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 headerData(self, section: int, orientation: Qt.Orientation, role: int = ...) -> typing.Any:
        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)
比忠 2024-12-14 18:00:37

我发现这个问题是因为我以不同的方式实现了这个问题,但我的新行不可选择,而且必须可以选择。上面的答案之一指出了如何使其不可选择,并指出了我的问题的解决方案。

我创建了一个从 QSortFilterProxyModel 派生的新类来操作“data”和“setData”例程以添加额外的行。无论源表有多少列,“data”方法都会为第 0 行返回空值。 “setData”方法忽略对第 0 行的任何请求(尽管不应该有任何请求),并将其余请求传递到源模型的“setData”并调整索引。我实现了mapToSource 和mapFromSource 来补偿源和代理之间的行号差异。

我还实现了“rowCount”来返回附加行。代理自动从源返回“columnCount”,并且保持不变。

我忘记的是实现“flags”方法,因此我的代理没有为空白行返回 ItemIsSelectable 标志,从而使其不可选择。

I found this question because I've implemented this in a different way, but my new row wasn't selectable and must be. One of the answers above pointed out how to make it non-selectable and that pointed me to the fix for my issue.

I created a new class derived from QSortFilterProxyModel to manipulate the "data" and "setData" routines to add the extra row. The "data" method returns empty values for row 0 and however many columns the source table has. The "setData" method ignores any requests for row 0 (although there shouldn't be any), and passes on the rest to the source model's "setData" with an adjusted index. I implemented mapToSource and mapFromSource to compensate for the difference in row numbers between the source and the proxy.

I also implemented "rowCount" to return an additional row. The proxy automatically returns "columnCount" from the source, and that remains the same.

The thing I forgot was to implement the "flags" method, so my proxy wasn't returning an ItemIsSelectable flag for the blank row, making it non-selectable.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文