Функция ComboBox currentIndexChanged не работает правильно в pyqt4 - PullRequest
2 голосов
/ 25 апреля 2019

Я взял два comboBox, т. Е. ComboBox1 и comboBox_2 и две функции test и test1 и вызывая их с помощью currentIndexChanged (self.comboBOx1.currentIndexChanged и self.comboBOx_2.currentIndexChanged).Когда значение выбирается из comboBox1, вызывается соответствующая ему функция (self.comboBOx1.currentIndexChanged), и то же самое для comboBox_2.При выборе значения из comboBox1 изменяет значения в comboBox_2 и работает нормально.Но проблема, с которой я столкнулся, заключается в том, что сначала, когда я выбираю значение из comboBox1 и comboBox_2, я получаю ожидаемые значения из вызываемой функции (вывод «hello»).Во второй раз, когда я выбираю значение из comboBox1, должна вызываться только тестовая функция, но здесь обе функции (test и test1) вызываются, а вторая функция (test1) вызывается дважды (дважды выдает «hello») и для третьейвремя его вызова четыре раза (печать «привет» четыре раза).Пожалуйста, кто-нибудь может помочь мне с этой проблемой .?

Код:

from PyQt4 import QtCore, QtGui

try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    def _fromUtf8(s):
        return s

try:
    _encoding = QtGui.QApplication.UnicodeUTF8
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig)

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName(_fromUtf8("MainWindow"))
        MainWindow.resize(800, 600)
        self.centralwidget = QtGui.QWidget(MainWindow)
        self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
        self.comboBox1 = QtGui.QComboBox(self.centralwidget)
        self.comboBox1.setGeometry(QtCore.QRect(310, 150, 171, 31))
        self.comboBox1.setObjectName(_fromUtf8("comboBox1"))
        self.comboBox1.addItem(_fromUtf8(""))
        self.comboBox1.addItem(_fromUtf8(""))
        self.comboBox1.addItem(_fromUtf8(""))
        self.comboBox1.addItem(_fromUtf8(""))
        self.comboBox_2 = QtGui.QComboBox(self.centralwidget)
        self.comboBox_2.setGeometry(QtCore.QRect(310, 240, 171, 41))
        self.comboBox_2.setObjectName(_fromUtf8("comboBox_2"))
        self.comboBox_2.addItem(_fromUtf8(""))
        self.comboBox_2.addItem(_fromUtf8(""))
        self.comboBox_2.addItem(_fromUtf8(""))
        self.comboBox_2.addItem(_fromUtf8(""))
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtGui.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 21))
        self.menubar.setObjectName(_fromUtf8("menubar"))
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtGui.QStatusBar(MainWindow)
        self.statusbar.setObjectName(_fromUtf8("statusbar"))
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None))
        self.comboBox1.setItemText(0, _translate("MainWindow", "select", None))
        self.comboBox1.setItemText(1, _translate("MainWindow", "a", None))
        self.comboBox1.setItemText(2, _translate("MainWindow", "b", None))
        self.comboBox1.setItemText(3, _translate("MainWindow", "c", None))
        self.comboBox_2.setItemText(0, _translate("MainWindow", "select", None))
        self.comboBox_2.setItemText(1, _translate("MainWindow", "p", None))
        self.comboBox_2.setItemText(2, _translate("MainWindow", "q", None))
        self.comboBox_2.setItemText(3, _translate("MainWindow", "r", None))
        self.comboBox_2.setEnabled(0)
        self.comboBox1.currentIndexChanged.connect(self.test)

    def test(self):
        s = str(self.comboBox1.currentText())
        res=['aa','bb','cc','dd']

        if (s == "- - select - -"):
            self.comboBox_2.setEnabled(0)
            self.comboBox_2.setCurrentIndex(0)
        elif(len(s)== 0):
            self.comboBox_2.setEnabled(1)
            self.comboBox_2.clear()
            self.comboBox_2.addItem("- - select - -")
            self.comboBox_2.addItem("New Checklist")
        else:
            self.comboBox_2.setEnabled(1)
            self.comboBox_2.clear()
            self.comboBox_2.addItem("- - select - -")
            self.comboBox_2.addItem("New Checklist")
            self.comboBox_2.addItems(res)
            self.comboBox_2.currentIndexChanged.connect(self.test1)

    def test1(self):
        print ("Hello")

if __name__ == "__main__":
    import sys
    app = QtGui.QApplication(sys.argv)
    MainWindow = QtGui.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())

1 Ответ

1 голос
/ 25 апреля 2019

Чтобы понять поведение, мы будем использовать следующие примеры:

Пример 1 :

from PyQt4 import QtCore, QtGui


def on_clicked():
    print("clicked")


if __name__ == "__main__":
    import sys

    app = QtGui.QApplication(sys.argv)
    button = QtGui.QPushButton("Press me")
    for _ in range(4):
        button.clicked.connect(on_clicked)
    button.show()
    sys.exit(app.exec_())

Когда вы нажимаете кнопку, она печатает 4 раза, потому что Qt не помнит, если ранее уже была связь между сигналом и функцией, поэтому, если есть n соединений между одним и тем же сигналом и функцией, они будут вызваны n раз, когда сигнал испускается.

Пример 2 :

from PyQt4 import QtCore, QtGui


def on_currentIndexChanged(ix):
    print("currentIndex:", ix)


if __name__ == "__main__":
    import sys

    app = QtGui.QApplication(sys.argv)
    combo = QtGui.QComboBox()
    print("currentIndex:", combo.currentIndex())
    combo.currentIndexChanged.connect(on_currentIndexChanged)
    button_add = QtGui.QPushButton("Add Items")
    button_add.clicked.connect(lambda: combo.addItems("1 2 3".split()))
    button_clear = QtGui.QPushButton("Clear")
    button_clear.clicked.connect(combo.clear)
    w = QtGui.QWidget()
    lay = QtGui.QVBoxLayout(w)
    for widget in (combo, button_add, button_clear):
        lay.addWidget(widget)
    w.show()
    sys.exit(app.exec_())

Значение по умолчанию currentIndex для QComboBox равно -1, когда вы добавляете элементы, это меняет значение currentIndex на 0, а при очистке QComboBox значение currentIndex возвращается к -1. Поэтому, когда вы добавляете или очищаете элементы, генерируется сигнал currentIndexChanged.


Исходя из вышеизложенного, я объясню поведение, на которое вы указываете: когда в QCombobox 1 выбирается новый currentIndex, вызывается метод тестирования, и если он вводит оператор else после очистки и добавления элементы, которые вы делаете первое соединение, если теперь повторяется то же самое, что и соединение, сигнал currentIndexChanged излучается дважды (один для clear () и другой для addItems ()), и вы также создаете второе соединение, если оно повторяется снова, сигнал испускается 4 раза (1 сброс () x 2 соединения + 1 addItems () x 2 соединения).

Решение:

  • Установите соединение в функции, которая вызывается только один раз.
  • Чтобы сигналы clear () и addItems () не излучали сигнал currentIndexChanged, необходимо использовать blockSignals ().
  • В качестве дополнительного пункта рекомендуется не модифицировать код, сгенерированный Qt Designer, желательно создать другой класс, который использует начальный класс в качестве интерфейса, в дополнение к использованию украшения @ QtCore.pyqtSlot ().
from PyQt4 import QtCore, QtGui

try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    def _fromUtf8(s):
        return s

try:
    _encoding = QtGui.QApplication.UnicodeUTF8
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig)

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName(_fromUtf8("MainWindow"))
        MainWindow.resize(800, 600)
        self.centralwidget = QtGui.QWidget(MainWindow)
        self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
        self.comboBox1 = QtGui.QComboBox(self.centralwidget)
        self.comboBox1.setGeometry(QtCore.QRect(310, 150, 171, 31))
        self.comboBox1.setObjectName(_fromUtf8("comboBox1"))
        self.comboBox1.addItem(_fromUtf8(""))
        self.comboBox1.addItem(_fromUtf8(""))
        self.comboBox1.addItem(_fromUtf8(""))
        self.comboBox1.addItem(_fromUtf8(""))
        self.comboBox_2 = QtGui.QComboBox(self.centralwidget)
        self.comboBox_2.setGeometry(QtCore.QRect(310, 240, 171, 41))
        self.comboBox_2.setObjectName(_fromUtf8("comboBox_2"))
        self.comboBox_2.addItem(_fromUtf8(""))
        self.comboBox_2.addItem(_fromUtf8(""))
        self.comboBox_2.addItem(_fromUtf8(""))
        self.comboBox_2.addItem(_fromUtf8(""))
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtGui.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 21))
        self.menubar.setObjectName(_fromUtf8("menubar"))
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtGui.QStatusBar(MainWindow)
        self.statusbar.setObjectName(_fromUtf8("statusbar"))
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None))
        self.comboBox1.setItemText(0, _translate("MainWindow", "select", None))
        self.comboBox1.setItemText(1, _translate("MainWindow", "a", None))
        self.comboBox1.setItemText(2, _translate("MainWindow", "b", None))
        self.comboBox1.setItemText(3, _translate("MainWindow", "c", None))
        self.comboBox_2.setItemText(0, _translate("MainWindow", "select", None))
        self.comboBox_2.setItemText(1, _translate("MainWindow", "p", None))
        self.comboBox_2.setItemText(2, _translate("MainWindow", "q", None))
        self.comboBox_2.setItemText(3, _translate("MainWindow", "r", None))


class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.setupUi(self)

        self.comboBox_2.setEnabled(False)
        self.comboBox1.currentIndexChanged[str].connect(self.test)
        self.comboBox_2.currentIndexChanged.connect(self.test1)

    @QtCore.pyqtSlot(str)
    def test(self, s):
        res=['aa','bb','cc','dd']

        if s == "- - select - -":
            self.comboBox_2.setEnabled(False)
            self.comboBox_2.setCurrentIndex(0)
        elif not s:
            self.comboBox_2.setEnabled(True)
            self.comboBox_2.blockSignals(True)
            self.comboBox_2.clear()
            self.comboBox_2.addItem("- - select - -")
            self.comboBox_2.addItem("New Checklist")
            self.comboBox_2.blockSignals(False)
        else:
            self.comboBox_2.setEnabled(True)
            self.comboBox_2.blockSignals(True)
            self.comboBox_2.clear()
            self.comboBox_2.addItem("- - select - -")
            self.comboBox_2.addItem("New Checklist")
            self.comboBox_2.addItems(res)
            self.comboBox_2.blockSignals(False)


    @QtCore.pyqtSlot(int)
    def test1(self, ix):
        print("Hello", ix)

if __name__ == "__main__":
    import sys
    app = QtGui.QApplication(sys.argv)
    w = MainWindow()
    w.show()
    sys.exit(app.exec_())
...