@katavagner

Как задать событие для нескольких элементов из globals()?

Если написать следующим образом, то код замечательно работает (метод enter_course() просто выводит полученный аргумент):
globals()['btn_0'].clicked.connect(lambda: self.enter_course([1, 2, 3]))
globals()['btn_1'].clicked.connect(lambda: self.enter_course([2, 3, 4]))

т.е. при нажатии на первую кнопку выводится [1, 2, 3], а при нажатии на вторую кнопку - [2, 3, 4]. Так как кнопки генерируются автоматически, то подключить функции, выполняющиеся при нажатии на кнопку необходимо через цикл, поэтому я написал так:

i = 0
sorted_dict = {
    'a': [1, 2, 3],
    'b': [2, 3, 4]
}

for key, value in sorted_dict.items():
            globals()['btn_' + str(i)] = QPushButton( str(key.upper()), self.gridLayoutWidget)
            globals()['btn_' + str(i)].clicked.connect(lambda: self.enter_course(value))
            globals()['btn_' + str(i)].setToolTip(str(value)) # всплывающая подсказка
            i += 1

Но данный код работает не правильно. При нажатии на любую из кнопок, выводится значение, полученное последней кнопкой. При этом в всплывающей подсказке находится правильная информация. В чем может быть проблема?
  • Вопрос задан
  • 87 просмотров
Решения вопроса 1
@Taus
Описанное поведение связано с тем, как Python связывает аргументы в lambda. Вам уже написали в комментариях к вопросу, что не надо использовать globals, поэтому ориентируюсь на списки. В коде
for i in range(10):
    ...
    self.b_course[i].clicked.connect(lambda: self.enter_course(value))

значение value в lambda связывается с локальной переменной value. А поскольку она изменяется по ходу цикла, то изменяется и во всех lambda. Чтобы исправить это, нужно добавить явный аргумент в lambda:
for i in range(10):
    ...
    self.b_course[i].clicked.connect(lambda state, v=value: self.enter_course(v))

Первый аргумент state нужен, потому что clicked ещё передаёт состояние кнопки.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы