这个Python 2.7 Tkinter代码,对于我点击的任何按钮,只切换" 9"按钮。那是为什么?
from Tkinter import *
class ButtonTestClass(Frame):
def __init__(self):
self.root=Tk()
self.root.title("Button Tester!")
self.root.option_add('*font', ('arial', 14, 'bold'))
self.frame=Frame(self.root, height=600, width=405, \
borderwidth=2, relief=GROOVE, background='steelblue'
)
self.frame.pack(fill=X, expand=False)
self.frame.pack_propagate(False)
self.label = Label(self.frame, \
text="Why is only the \"9\" button toggling?", bg='steelblue')
self.label.pack(padx=25, pady=15, side=TOP)
self.root.event_add('<<ev_quit>>', '<Control-c>', '<Control-q>', '<q>')
self.root.bind('<<ev_quit>>', lambda e: self.bye_bye())
self.numBtn = [None] * 9
self.numBtnToggleOnFlag = False
self.numBtnPressedFlag = False
self.sillyNilly = 0
self.lastNumBtn = self.entryNumber = self.lastEntryNumber = self.sillyNilly
self.byeWindow = None
def numBtnPressed(self, n):
#n = StringVar()
self.numBtn[n-1].configure(text=n-1)
if self.lastNumBtn != self.sillyNilly:
self.lastNumBtn.configure(text=self.lastEntryNumber, background='steelblue')
if self.numBtnPressedFlag == True and self.entryNumber == n:
self.lastNumBtn.configure(text=self.lastEntryNumber,background='steelblue')
self.numBtnPressedFlag = False
else:
#self.numBtn[n-1] = Button(text=n.get(), background='cyan')
self.numBtn[n-1].configure(text=n, background='cyan')
self.entryNumber = n
self.lastEntryNumber = n
self.lastNumBtn = self.numBtn[n-1]
self.numBtnPressedFlag = True
if self.numBtnToggleOnFlag == True and self.numBtnPressedFlag == False:
self.lastNumBtn.configure(text=self.lastEntryNumber,background=self.bgColor)
self.numBtnPressedFlag = False
self.lastNumBtn = self.sillyNilly
def createAndDrawNumButtons(self):
""" Create the left frame's number selection buttons """
nbx = 175
nby = 65
nbw = nbh = 40
nbp = 12
self.entryNumber = StringVar()
for i in range(9):
self.entryNumber.set(i+1)
self.numBtn[i] = Button(
self.frame,
textvariable=i+1,
text=(i+1),
background='steelblue',
activebackground='steelblue3',
command=lambda: self.numBtnPressed(i+1)
)
self.entryNumber.set(i+1)
print "in numBtnPressed(), self.numBtnToggleOnFlag is '%r', " % \
self.numBtnToggleOnFlag, \
"self.entryNumber is '%r', self.lastNumBtn is '%r', " % \
(self.entryNumber, self.lastNumBtn), \
"self.lastEntryNumber is '%r', button number is '%r'" % \
(self.lastEntryNumber, self.entryNumber.get())
self.numBtn[i].place(
x=nbx,
y=nby,
width=nbw,
height=nbh
)
nby += nbh + nbp
def createQuitButton(self):
pbx=157
pby=550
pbw=75
pbh=25
pbp=10
self.quitBtn=Button(
self.frame,
text='Quit',
activebackground='steelblue3',
font='arial 10 bold',
bg='steelblue',
command=self.bye_bye
)
self.quitBtn.place(
x=pbx,
y=pby,
width=pbw,
height=pbh
)
pbx += pbw + pbp
def dontQuit(self, tlref):
tlref.destroy()
self.byeWindow = None
def bye_bye(self):
if self.byeWindow is not None:
return
self.byeWindow=Toplevel()
self.byeWindow.title("Really quit?")
self.byeWindow.config(bg='steelblue', height=40, width=80)
sureMsgLabel=Label(self.byeWindow,
text="Are you sure you want to quit?",
font='arial 11 bold',
bg='steelblue'
)
sureMsgLabel.pack(side=TOP, padx=10, pady=15)
yesButton=Button(self.byeWindow,
text=" Yes. ",
font='arial 10 bold',
bg='steelblue',
activebackground='steelblue3',
command=lambda: quit()
)
yesButton.pack(side=LEFT, anchor=N, padx=40, pady=20)
yesButton.bind('<Key-Return>', lambda: yesButton.invoke())
noButton = Button(self.byeWindow,
text=" No. ",
activebackground='steelblue3',
font='arial 10 bold',
bg='steelblue',
command=lambda: self.dontQuit(self.byeWindow)
)
noButton.focus_force()
noButton.pack(side=RIGHT, anchor=N, padx=40, pady=20)
noButton.bind('<Key-Return>', lambda: noButton.invoke())
bT = ButtonTestClass()
bT.createAndDrawNumButtons()
bT.createQuitButton()
if __name__ == '__main__':
bT.root.mainloop()
现在,这个Ruby 1.8 Tcl / Tk代码(我从中转换)在“青色”中打开和关闭每个单击的按钮。颜色如预期......
def numBtnPressed(n)
if @lastNumBtn != nil
@lastNumBtn.text(@lastEntryNumber).background(@bgColor)
end
if @numBtnPressedFlag == true and @entryNumber == n
@lastNumBtn.text(@lastEntryNumber).background(@bgColor)
@numBtnPressedFlag = false
else
@entryNumber = n
@lastEntryNumber = n
@lastNumBtn = @numBtn[n-1]
@numBtnPressedFlag = true
@numBtn[n-1].text(n).background('cyan')
end
if @numBtnToggleOnFlag == true and @numBtnPressedFlag == false
@lastNumBtn.text(@lastEntryNumber).background(@bgColor)
@numBtnPressedFlag = false
@lastNumBtn = nil
end
end
def createAndDrawNumButtons()
nbx = 25
nby = 20
nbw = nbh = 40
nbp = 10
9.times { |i|
@numBtn[i] = TkButton.new(@middleLeftFrame, :text=>(i+1).to_s , \
:command=> proc { numBtnPressed(i+1) }).place(
:x=>nbx,
:y=>nby,
:width=>nbw,
:height=>nbh
)
nby += nbh + nbp
}
end
提前感谢您提供给我的任何启示。
在Python和Tkinter编程:Python程序的图形用户界面,Manning Publications Company,John E. Grayson,第103页中,Grayson提供了Timothy R. Evans在Python新闻组中提出的一个类,它消除了需要对于lambda机制,如下......
class Command(object):
def __init__(self, func, *args, **kw):
self.func = func
self.args = args
self.kw = kw
def __call__(self, *args, **kw):
args = self.args + args
kw.update(self.kw)
apply(self.func, args, kw)
然后按钮的命令选项&#39; lambda&#39;可以替换为......
command=Command(self.numBtnPressed, (i+1))
使用此技术修改的代码如下......
from Tkinter import *
class Command(object):
def __init__(self, func, *args, **kw):
self.func = func
self.args = args
self.kw = kw
def __call__(self, *args, **kw):
args = self.args + args
kw.update(self.kw)
apply(self.func, args, kw)
class ButtonTestClass(Frame):
def __init__(self):
self.root=Tk()
self.root.title("Button Tester!")
self.root.option_add('*font', ('arial', 14, 'bold'))
self.frame=Frame(self.root, height=600, width=405, \
borderwidth=2, relief=GROOVE, background='steelblue'
)
self.frame.pack(fill=X, expand=False)
self.frame.pack_propagate(False)
self.label = Label(self.frame, \
text="Why is only the \"9\" button toggling?", bg='steelblue')
self.label.pack(padx=25, pady=15, side=TOP)
self.root.event_add('<<ev_quit>>', '<Control-c>', '<Control-q>', '<q>')
self.root.bind('<<ev_quit>>', lambda e: self.bye_bye())
self.numBtn = [None] * 9
self.numBtnToggleOnFlag = False
self.numBtnPressedFlag = False
self.sillyNilly = 0
self.lastNumBtn = self.entryNumber = self.lastEntryNumber = self.sillyNilly
self.byeWindow = None
def numBtnPressed(self, n):
#n = StringVar()
self.numBtn[n-1].configure(text=n-1)
if self.lastNumBtn != self.sillyNilly:
self.lastNumBtn.configure(text=self.lastEntryNumber, background='steelblue')
if self.numBtnPressedFlag == True and self.entryNumber == n:
self.lastNumBtn.configure(text=self.lastEntryNumber,background='steelblue')
self.numBtnPressedFlag = False
else:
#self.numBtn[n-1] = Button(text=n.get(), background='cyan')
self.numBtn[n-1].configure(text=n, background='cyan')
self.entryNumber = n
self.lastEntryNumber = n
self.lastNumBtn = self.numBtn[n-1]
self.numBtnPressedFlag = True
if self.numBtnToggleOnFlag == True and self.numBtnPressedFlag == False:
self.lastNumBtn.configure(text=self.lastEntryNumber,background=self.bgColor)
self.numBtnPressedFlag = False
self.lastNumBtn = self.sillyNilly
def createAndDrawNumButtons(self):
""" Create the left frame's number selection buttons """
nbx = 175
nby = 65
nbw = nbh = 40
nbp = 12
self.entryNumber = StringVar()
for i in range(9):
self.entryNumber.set(i+1)
self.numBtn[i] = Button(
self.frame,
textvariable=i+1,
text=(i+1),
background='steelblue',
activebackground='steelblue3',
command=Command(self.numBtnPressed, (i+1)) # <<-- command 'lambda' replacement
)
self.entryNumber.set(i+1)
print "in numBtnPressed(), self.numBtnToggleOnFlag is '%r', " % \
self.numBtnToggleOnFlag, \
"self.entryNumber is '%r', self.lastNumBtn is '%r', " % \
(self.entryNumber, self.lastNumBtn), \
"self.lastEntryNumber is '%r', button number is '%r'" % \
(self.lastEntryNumber, self.entryNumber.get())
self.numBtn[i].place(
x=nbx,
y=nby,
width=nbw,
height=nbh
)
nby += nbh + nbp
def createQuitButton(self):
pbx=157
pby=550
pbw=75
pbh=25
pbp=10
self.quitBtn=Button(
self.frame,
text='Quit',
activebackground='steelblue3',
font='arial 10 bold',
bg='steelblue',
command=self.bye_bye
)
self.quitBtn.place(
x=pbx,
y=pby,
width=pbw,
height=pbh
)
pbx += pbw + pbp
def dontQuit(self, tlref):
tlref.destroy()
self.byeWindow = None
def bye_bye(self):
if self.byeWindow is not None:
return
self.byeWindow=Toplevel()
self.byeWindow.title("Really quit?")
self.byeWindow.config(bg='steelblue', height=40, width=80)
sureMsgLabel=Label(self.byeWindow,
text="Are you sure you want to quit?",
font='arial 11 bold',
bg='steelblue'
)
sureMsgLabel.pack(side=TOP, padx=10, pady=15)
yesButton=Button(self.byeWindow,
text=" Yes. ",
font='arial 10 bold',
bg='steelblue',
activebackground='steelblue3',
command=lambda: quit()
)
yesButton.pack(side=LEFT, anchor=N, padx=40, pady=20)
yesButton.bind('<Key-Return>', lambda: yesButton.invoke())
noButton = Button(self.byeWindow,
text=" No. ",
activebackground='steelblue3',
font='arial 10 bold',
bg='steelblue',
command=lambda: self.dontQuit(self.byeWindow)
)
noButton.focus_force()
noButton.pack(side=RIGHT, anchor=N, padx=40, pady=20)
noButton.bind('<Key-Return>', lambda: noButton.invoke())
bT = ButtonTestClass()
bT.createAndDrawNumButtons()
bT.createQuitButton()
if __name__ == '__main__':
bT.root.mainloop()
如果你运行它,你可以看到每个数字按钮现在都可以切换&#39;点击时。
尽管如此,我仍然希望应用BrenBarn的封闭技术,但我无法让它发挥作用。我以为我理解他的解释是关闭操作的名字&#39;而不是“价值观”,但我似乎是在语法上受到挑战&#34;让它工作。我尝试了我能想到的每一种组合。任何人都可以帮我解决这个问题吗?
哇!拿着电话!这种语法有效:&#34; command = lambda i = i:self.numBtnPressed(i + 1)&#34;谢谢大家的灵感!