如何调试QComboBox发出多个“激活”信号

问题描述 投票:0回答:2

我发现了一个很好的资源here,用于构建QComboBox,该列表提供了建议的过滤列表。每次我在组合框中选择建议的选项时,“激活的”和“ currentIndexChanged”信号都会发出三次,但效果很好。行为是不同的,具体取决于是通过鼠标还是使用箭头键和回车按钮选择了选项。

我的问题是,我该如何调试?代码中没有任何要捕捉和阻止前两个信号发出的意义。有没有一种方法可以覆盖QComboBox“已激活”信号以尝试将其捕获到行为中?还是我必须定义自己的信号并改用它?

这里是代码:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from PySide2 import QtCore, QtGui, QtWidgets
from PySide2.QtCore import Qt, QSortFilterProxyModel
from PySide2.QtWidgets import QCompleter, QComboBox

class ExtendedComboBox(QComboBox):
    def __init__(self, parent=None):
        super(ExtendedComboBox, self).__init__(parent)

        self.setFocusPolicy(Qt.StrongFocus)
        self.setEditable(True)

        # add a filter model to filter matching items
        self.pFilterModel = QSortFilterProxyModel(self)
        self.pFilterModel.setFilterCaseSensitivity(Qt.CaseInsensitive)
        self.pFilterModel.setSourceModel(self.model())

        # add a completer, which uses the filter model
        self.completer = QtWidgets.QCompleter(self)
        self.completer.setModel(self.pFilterModel)

        # always show all (filtered) completions
        self.completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion)
        self.setCompleter(self.completer)

        # connect signals
        self.lineEdit().textEdited.connect(self.pFilterModel.setFilterFixedString)
        self.completer.activated.connect(self.on_completer_activated)

    # on selection of an item from the completer, select the corresponding item from combobox 
    def on_completer_activated(self, text):
        if text:
            index = self.findText(text)
            self.setCurrentIndex(index)
            # self.activated.emit(self.itemText(index))


    # on model change, update the models of the filter and completer as well 
    def setModel(self, model):
        super(ExtendedComboBox, self).setModel(model)
        self.pFilterModel.setSourceModel(model)
        self.completer.setModel(self.pFilterModel)


    # on model column change, update the model column of the filter and completer as well
    def setModelColumn(self, column):
        self.completer.setCompletionColumn(column)
        self.pFilterModel.setFilterKeyColumn(column)
        super(ExtendedComboBox, self).setModelColumn(column)    

def change_option(text):
    print(text)

if __name__ == "__main__":
    import sys
    from PySide2.QtWidgets import QApplication
    from PySide2.QtCore import QStringListModel

    app = QApplication(sys.argv)

    string_list = ['hola muchachos', 'adios amigos', 'hello world', 'good bye']

    combo = ExtendedComboBox()

    # either fill the standard model of the combobox
    combo.addItems(string_list)
    combo.currentIndexChanged[str].connect(change_option)
    # or use another model
    #combo.setModel(QStringListModel(string_list))

    combo.resize(300, 40)
    combo.show()

    sys.exit(app.exec_())

[您会注意到,如果您运行代码并开始在文本框中输入“ hello”,然后单击建议的“ hello world”,activated信号将返回正确的“ hello world”。如果您开始输入“ hello”,但是这次使用箭头键向下滚动到“ hello world”,它将发出3次。

我已经尝试过以相同的结果实现相同结果的多个实现。在用新模型替换掉模型后,我什至注意到未修改的QComboBox的类似行为。

PySide2 5.6.0a1Windows 10.0.18362内部版本18362

感谢您的光临!

python pyside2 qcombobox
2个回答
1
投票

我使用的是PySide2 5.6.0a1,因为那是Anaconda在Python 2.7环境中安装的。 @eyllanesc指出这是一个过时的早期版本,可能有错误。

[当我在带有PySide2-5.13.1的Python 3.7环境中尝试相同的代码时,一切都按预期工作。


0
投票

我没有PySide2,但在大多数情况下,我认为您要做的就是用PySide2替换我的PyQt5参考-因为这是我为使您的程序从PySide2切换到PyQt5所做的一切-与进行了一些重组和微调,这使我获得了以下功能代码:

from sys import exit as sysExit

from PyQt5.QtCore import Qt, QSortFilterProxyModel, QStringListModel, pyqtSlot
from PyQt5.QtWidgets import QApplication, QWidget, QCompleter, QComboBox, QCompleter, QHBoxLayout

class ExtendedComboBox(QComboBox):
    def __init__(self):
        QComboBox.__init__(self)

        self.setFocusPolicy(Qt.StrongFocus)
        self.setEditable(True)

        # add a filter model to filter matching items
        self.pFilterModel = QSortFilterProxyModel(self)
        self.pFilterModel.setFilterCaseSensitivity(Qt.CaseInsensitive)
        self.pFilterModel.setSourceModel(self.model())

        # add a completer, which uses the filter model
        self.completer = QCompleter(self)
        self.completer.setModel(self.pFilterModel)

        # always show all (filtered) completions
        self.completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion)
        self.setCompleter(self.completer)

        # connect signals
        self.lineEdit().textEdited.connect(self.pFilterModel.setFilterFixedString)
        self.completer.activated.connect(self.on_completer_activated)

    # on selection of an item from the completer, select the corresponding item from combobox 
    def on_completer_activated(self, text):
        if text:
            index = self.findText(text)
            self.setCurrentIndex(index)
            # self.activated.emit(self.itemText(index))


    # on model change, update the models of the filter and completer as well 
    def setModel(self, model):
        self.setModel(model)
        self.pFilterModel.setSourceModel(model)
        self.completer.setModel(self.pFilterModel)


    # on model column change, update the model column of the filter and completer as well
    def setModelColumn(self, column):
        self.completer.setCompletionColumn(column)
        self.pFilterModel.setFilterKeyColumn(column)
        self.setModelColumn(column)    

class MainApp(QWidget):
    def __init__(self):
        QWidget.__init__(self)

        string_list = ['hola muchachos', 'adios amigos', 'hello world', 'good bye']

        self.combo = ExtendedComboBox()

        # either fill the standard model of the combobox
        self.combo.addItems(string_list)
        self.combo.currentIndexChanged[str].connect(self.change_option)
        # or use another model
        #combo.setModel(QStringListModel(string_list))

        self.resize(300, 100)
        self.combo.resize(300, 50)

        HBox = QHBoxLayout()
        HBox.addWidget(self.combo)

        self.setLayout(HBox)

    @pyqtSlot(str)
    def change_option(self, text):
        print(text)

if __name__ == "__main__":
    MainThred = QApplication([])

    MainGui = MainApp()
    MainGui.show()

    sysExit(MainThred.exec_())

我认为问题是您试图将信号/插槽与非QObject函数一起使用(aka),您的change_option函数没有直接与从QObject继承的任何东西相关联,所以我不确定它是做什么的还是没有做的但这只是一个猜测,因为我所做的全部都放入了正常的Qt结构中,并且效果很好

© www.soinside.com 2019 - 2024. All rights reserved.