Почему этот код только переключает синий цвет? (Python, PyQt)
По какой-то причине запуск этого кода только переключает цвет синий, когда он должен переключать каждый из цветов по отдельности.
Этот код является моей версией кода примера в http://eli.thegreenplace.net/2011/04/25/passing-extra-arguments-to-pyqt-slot , который является учебным пособием для PyQt, который я только что начал обучение.
import sys from PyQt5.QtWidgets import (QWidget, QPushButton, QFrame, QApplication) from PyQt5.QtGui import QColor class Example(QWidget): red = False blue = False green = False buttons = [] def __init__(self): super().__init__() self.init_UI() def init_UI(self): self.col = QColor(0, 0, 0) for x in range(0, 3): self.buttons.append(QPushButton('Red' if x == 0 else ('Green' if x == 1 else 'Blue'), self)) self.buttons[x].setCheckable(True) self.buttons[x].move(10, 10 + 50 * x) self.buttons[x].clicked[bool].connect(lambda: self.set_color(x)) self.square = QFrame(self) self.square.setGeometry(150, 20, 100, 100) self.square.setStyleSheet("QWidget { background-color: %s }" % self.col.name()) self.setGeometry(300, 300, 280, 170) self.setWindowTitle('Toggle button') self.show() def set_color(self, button): if button == 0: if self.red == False: self.red = True self.col.setRed(255) else: self.red = False self.col.setRed(0) elif button == 1: if self.green == False: self.green = True self.col.setGreen(255) else: self.green = False self.col.setGreen(0) else: if self.blue == False: self.blue = True self.col.setBlue(255) else: self.blue = False self.col.setBlue(0) self.square.setStyleSheet("QFrame { background-color: %s }" % self.col.name()) print(self.col.name()) if __name__ == '__main__': app = QApplication(sys.argv) ex = Example() sys.exit(app.exec_())
- эквивалент wxStaticBox для QT
- PyQt: получение значений из QLineEdit
- Загрузка страницы с фреймами для скриншота
- pyqtSlot () и возвращаемый тип списка python
- Исключение было неожиданно обработано в слотах Pyside
Причина, по которой connect(lambda: self.set_color(x))
не работает, заключается в том, что x
будет оцениваться только при вызове лямбда, т. connect(lambda: self.set_color(x))
сигнал, который будет намного позже, после завершения цикла. Таким образом, set_color()
получит значение x
во время выхода сигнала. В вашем коде это будет последнее значение, которое x
имеет в цикле, т. Е. 2.
Хотя ответ @ Hi верен, я нахожу решение Achayan (упомянутое в комментарии) более явным и работает просто отлично (вопреки некоторым комментариям – я проверил его с кодом):
for x in range(0, 3): ... self.buttons[x].clicked[bool].connect(partial(self.set_color, x))
Причина этого в том, что x
является аргументом вызова функции (функция functools.partial
), поэтому x
оценивается немедленно . Функция, возвращаемая partial(f, a)
когда f
является функцией одного arg, является функцией g()
которая не принимает аргументов и будет вызывать f(a)
.
- PyQt: виджет Qt.Popup иногда теряет фокус без закрытия, становится незамкнутым
- Используйте QAction без добавления в меню (или панели инструментов)
- Выравнивание виджета в ячейке pyqt
- Qt и Python, где настраивать сигналы и слоты
- Внедрение PyQtGraph в Qt без создания нового окна
- Как я могу создать исключение, которое включает строку Unicode?
- Сортировка в pyqt tablewidget
- Почему консоль python в PyCharm не отображает сообщение об ошибке при использовании pyqt?
- Событие отключения триггера в другом приложении в OSX