Форум сайта python.su
from PyQt4 import QtGui class win(QtGui.QWidget): def __init__(self): QtGui.QWidget.__init__(self) self.lay = QtGui.QVBoxLayout() self.setLayout(self.lay) self.mass = [{"obj":None, "name":"one", "text":"Первая кнопка", "val":1}, {"obj":None, "name":"two", "text":"Вторая кнопка", "val":2}] for i in self.mass: i["obj"] = QtGui.QPushButton(i["text"]) i["obj"].setObjectName(i["name"]) self.lay.addWidget(i["obj"]) i["obj"].clicked.connect(lambda: self.myfunc(i["val"])) # как тут сделать-то? def myfunc(self, val): print (str(val)) if __name__ == "__main__": import sys app = QtGui.QApplication(sys.argv) window = win() window.show() sys.exit(app.exec_())
Офлайн
в цикле значение i на каждой итерации перезаписывается
for i in range(3): pass print i
lst = [] for i in range(3): lst.append(i) print lst[0]
Отредактировано vrabey (Март 8, 2015 16:11:50)
Офлайн
Что-то не пойму.
Как это применимо к моей программе?
i на каждой итерации содержит ссылку на словарь из списка. Я использую значения именно из словаря.
Офлайн
или мне надо в каждый словарь ещё и лямбду как отдельный элемент засунуть и к нему сигналы кнопок коннектить?
Офлайн
from PyQt4 import QtGui class win(QtGui.QWidget): def __init__(self): QtGui.QWidget.__init__(self) self.lay = QtGui.QVBoxLayout() self.setLayout(self.lay) self.mass = [{"obj":None, "name":"one", "text":"Первая кнопка", "val":lambda:self.myfunc(1)}, # эвона как! {"obj":None, "name":"two", "text":"Вторая кнопка", "val:"lambda:self.myfunc(2)}] for i in self.mass: i["obj"] = QtGui.QPushButton(i["text"]) i["obj"].setObjectName(i["name"]) self.lay.addWidget(i["obj"]) i["obj"].clicked.connect(i["val"]) # вот так срабатывает верно def myfunc(self, val): print (str(val)) if __name__ == "__main__": import sys app = QtGui.QApplication(sys.argv) window = win() window.show() sys.exit(app.exec_())
Отредактировано Pluto (Март 8, 2015 16:42:06)
Офлайн
Ну первое, что приходит в голову это замыкания
import sys from PyQt4 import QtGui def wrapper(*args): def myfunc(): print(*args) return myfunc class Window(QtGui.QWidget): def __init__(self): QtGui.QWidget.__init__(self) self.lay = QtGui.QVBoxLayout() self.setLayout(self.lay) self.mass = [{"obj": None, "name": "one", "text": "Первая кнопка", "val": 1}, {"obj": None, "name": "two", "text": "Вторая кнопка", "val": 2}] for i in self.mass: i["obj"] = QtGui.QPushButton(i["text"]) i["obj"].setObjectName(i["name"]) self.lay.addWidget(i["obj"]) i["obj"].clicked.connect(wrapper(i["val"])) if __name__ == "__main__": app = QtGui.QApplication(sys.argv) window = Window() window.show() sys.exit(app.exec_())
Офлайн
Твой код с lambda не работает, потому что lambda реализует ленивые вычисления, то есть функция инициализируется в не в момент её создания, а момент вызова (и получается, что все созданные функции инициализируются с последним значением переменной цикла).
Именно по этому в цикле анонимные функции для откладывания вызова функции использовать не получится.
Отредактировано alex925 (Март 8, 2015 17:01:52)
Офлайн
так можно
from functools import partial # <<< from PyQt4 import QtGui class win(QtGui.QWidget): def __init__(self): QtGui.QWidget.__init__(self) self.lay = QtGui.QVBoxLayout() self.setLayout(self.lay) self.mass = [{"obj":None, "name":"one", "text":u"Первая кнопка", "val":1}, {"obj":None, "name":"two", "text":u"Вторая кнопка", "val":2}] for i in self.mass: i["obj"] = QtGui.QPushButton(i["text"]) i["obj"].setObjectName(i["name"]) self.lay.addWidget(i["obj"]) i["obj"].clicked.connect(partial (self.myfunc, i["val"])) # <<< def myfunc(self, val): print (str(val)) if __name__ == "__main__": import sys app = QtGui.QApplication(sys.argv) window = win() window.show() sys.exit(app.exec_())
Отредактировано vrabey (Март 8, 2015 17:07:17)
Офлайн
Спасибо всем ответившим.
Vrabey отдельное БОЛЬШОЕ спасибо! Все проблемы с этим способом решились.
Приведённый тут мной пример был упрощен. В оригинальном коде мне понадобилось в качестве аргумента передать вообще ссылку на весь словарь, а не на отдельное значение его. И получилось без проблем!
partial - наше всё.
Офлайн
Plutoi["obj"].clicked.connect(lambda: self.myfunc(i["val"])) # как тут сделать-то?
i["obj"].clicked.connect(lambda e, i=i: self.myfunc(i["val"]))
[guest@localhost py]$ ./t.py
1
2
1
2
[guest@localhost py]$
Отредактировано py.user.next (Март 9, 2015 02:22:22)
Офлайн