我需要在窗口上放置6个按钮以供我的应用程序使用。但随着应用程序的增长,可能需要更多按钮(可能是7,8,......)。这就是我将这些按钮放在Python列表中的原因。您可以在下面看到我的代码。您可以简单地复制/粘贴它,它应该在您的系统上运行而不会出现任何错误:
import sys
import os
from PyQt4 import QtGui
from PyQt4 import QtCore
def setCustomSize(x, width, height):
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(x.sizePolicy().hasHeightForWidth())
x.setSizePolicy(sizePolicy)
x.setMinimumSize(QtCore.QSize(width, height))
x.setMaximumSize(QtCore.QSize(width, height))
''''''
class CustomMainWindow(QtGui.QMainWindow):
def __init__(self):
super(CustomMainWindow, self).__init__()
# Define the geometry of the main window
self.setGeometry(300, 300, 800, 400)
self.setWindowTitle("my first window")
# Create FRAME_A
self.FRAME_A = QtGui.QFrame(self)
self.FRAME_A.setStyleSheet("QWidget { background-color: %s }" % QtGui.QColor(210,210,235,255).name())
self.LAYOUT_A = QtGui.QHBoxLayout()
self.LAYOUT_A.setAlignment(QtCore.Qt.AlignLeft)
self.FRAME_A.setLayout(self.LAYOUT_A)
self.setCentralWidget(self.FRAME_A)
# Place the buttons
self.placeButtons()
self.show()
''''''
def placeButtons(self):
self.btn = []
for i in range(6):
self.btn.append(QtGui.QPushButton(text = 'btn[' + str(i) + ']'))
setCustomSize(self.btn[i], 100, 50)
self.btn[i].clicked.connect(lambda: self.btnAction(i))
self.LAYOUT_A.addWidget(self.btn[i])
''''''
''''''
def btnAction(self,n):
print("btn[" + str(n) + "] is clicked")
''''''
''' End Class '''
if __name__== '__main__':
app = QtGui.QApplication(sys.argv)
QtGui.QApplication.setStyle(QtGui.QStyleFactory.create('Plastique'))
myGUI = CustomMainWindow()
sys.exit(app.exec_())
''''''
我使用标准信号/插槽机制将每个按钮连接到btnAction(self,n)
功能。如您所见,我使用了一个特殊功能 - 让我们称之为lambda
功能 - 传递一个参数。参数是按钮编号。
不幸的是,无论我按下什么按钮,我都会得到以下输出:
>>> btn[5] is clicked
>>> btn[5] is clicked
>>> btn[5] is clicked
>>> btn[5] is clicked
我将placeButtons(self)
功能更改为:
def placeButtons(self):
self.btn = []
for i in range(6):
self.btn.append(QtGui.QPushButton(text = 'btn[' + str(i) + ']'))
setCustomSize(self.btn[i], 100, 50)
if(i==0):
self.btn[i].clicked.connect(lambda: self.btnAction(0))
elif(i==1):
self.btn[i].clicked.connect(lambda: self.btnAction(1))
elif(i==2):
self.btn[i].clicked.connect(lambda: self.btnAction(2))
elif(i==3):
self.btn[i].clicked.connect(lambda: self.btnAction(3))
elif(i==4):
self.btn[i].clicked.connect(lambda: self.btnAction(4))
elif(i==5):
self.btn[i].clicked.connect(lambda: self.btnAction(5))
self.LAYOUT_A.addWidget(self.btn[i])
''''''
''''''
现在我得到了正确的输出:
>>> btn[0] is clicked
>>> btn[1] is clicked
>>> btn[2] is clicked
>>> btn[3] is clicked
所以新的placeButtons(self)
函数有效,但它效率低且繁琐。有谁知道第一个(和更清洁的)实现有什么问题?
注意:我在Windows 10上工作,使用Python v3并使用PyQt4库(anaconda包)制作我的GUI。
修改
谢谢先生。 salomonderossi。现在你的解决方案有效我首先要导入functools:import functools
接下来,我将应用您的解决方案:
def placeButtons(self):
self.btn = []
for i in range(6):
self.btn.append(QtGui.QPushButton(text = 'btn[' + str(i) + ']'))
setCustomSize(self.btn[i], 100, 50)
self.btn[i].clicked.connect(functools.partial(self.btnAction, i))
self.LAYOUT_A.addWidget(self.btn[i])
''''''
''''''
答案 0 :(得分:2)
您需要为每个创建的(lambda)函数绑定值。为此,您可以将它们作为参数传递,并使用默认值:
for i in range(6):
self.btn[i].clicked.connect(lambda i=i: self.btnAction(i))
以下是显示效果的最小示例:
def test_function(x):
return x
def test():
# DO NOT USE THIS. This is just for showing the effect
wrong = list()
for i in range(6):
wrong.append(lambda: test_function(i))
for w in wrong:
print(w()) # will always print 5
print("-"*10)
# This is the desired behaviour
right = list()
for i in range(6):
right.append(lambda i=i: test_function(i))
for r in right:
print(r())
if __name__ == '__main__':
test()
其中给出了以下输出:
5
5
5
5
5
5
----------
0
1
2
3
4
5
或者,您可以使用functools包中的partial:
for i in range(6):
self.btn[i].clicked.connect(partial(self.btnAction, i))