Отдельное взаимодействие пользователя с программными изменениями: PyQt, QComboBox - PullRequest
4 голосов
/ 08 февраля 2012

У меня есть несколько QComboBox в моем PyQt4 / Python3 GUI, и они заполнены некоторыми записями из базы данных во время инициализации.Начальный CurrentIndex установлен в 0. Также есть поле для галочки, которое меняет язык элементов в моих полях со списком.Чтобы сохранить текущий выбор пользователя, я делаю резервную копию индекса текущего элемента и устанавливаюCurrentIndex на это число после того, как я заполняю ComboBox переведенными элементами.Все эти действия генерируют сигнал currentIndexChanged.

На основе элементов, выбранных в QComboBoxes, отображается некоторый график.Идея состоит в том, чтобы перерисовать сюжет онлайн - как только пользователь изменит какой-либо текущий элемент ComboBox.И здесь у меня возникает проблема, поскольку, если я перерисовываю график каждый раз, когда испускается сигнал currentIndexChanged, я перерисовываю его также несколько раз во время инициализации, и если изменен флажок перевода.

Каков наилучший способ разделенияэти случаи?В принципе, мне необходимо отделить текущее изменение индекса программного от пользователя и обновить график только в последнем случае (во время инициализации графического интерфейса пользователя я могу программно вызвать функцию обновления графика один раз).Должен ли я написать / переписать какой-либо сигнал?Если так, я никогда не делал этого раньше и приветствовал бы любой намек или хороший пример.Использовать другой сигнал?Или, может быть, есть способ временно заблокировать все сигналы?

1 Ответ

10 голосов
/ 08 февраля 2012

Есть несколько разных вещей, которые вы можете попробовать.

Во-первых, вы можете убедиться, что вы выполнили всю свою инициализацию до того, как подключите сигналы.

Во-вторыхВы можете использовать активированный сигнал, который отправляется только тогда, когда пользователь выбирает элемент.(Но учтите, что, в отличие от currentIndexChanged , этот сигнал отправляется, даже если индекс не изменился).

В-третьих, вы можете использовать blockSignals для временной остановки любогосигналы, посылаемые в то время, как текущий индекс изменяется программно.

Вот скрипт, который демонстрирует эти возможности:

from PyQt4 import QtGui, QtCore

class Window(QtGui.QWidget):
    def __init__(self):
        QtGui.QWidget.__init__(self)
        layout = QtGui.QVBoxLayout(self)
        self.combo = QtGui.QComboBox()
        self.combo.setEditable(True)
        self.combo.addItems('One Two Three Four Five'.split())
        self.buttonOne = QtGui.QPushButton('Change (Default)', self)
        self.buttonOne.clicked.connect(self.handleButtonOne)
        self.buttonTwo = QtGui.QPushButton('Change (Blocked)', self)
        self.buttonTwo.clicked.connect(self.handleButtonTwo)
        layout.addWidget(self.combo)
        layout.addWidget(self.buttonOne)
        layout.addWidget(self.buttonTwo)
        self.changeIndex()
        self.combo.activated['QString'].connect(self.handleActivated)
        self.combo.currentIndexChanged['QString'].connect(self.handleChanged)
        self.changeIndex()

    def handleButtonOne(self):
        self.changeIndex()

    def handleButtonTwo(self):
        self.combo.blockSignals(True)
        self.changeIndex()
        self.combo.blockSignals(False)

    def changeIndex(self):
        index = self.combo.currentIndex()
        if index < self.combo.count() - 1:
            self.combo.setCurrentIndex(index + 1)
        else:
            self.combo.setCurrentIndex(0)

    def handleActivated(self, text):
        print('handleActivated: %s' % text)

    def handleChanged(self, text):
        print('handleChanged: %s' % text)

if __name__ == '__main__':

    import sys
    app = QtGui.QApplication(sys.argv)
    window = Window()
    window.show()
    sys.exit(app.exec_())
...