为什么只有" 9"按钮切换无论我点击哪个按钮?

时间:2015-09-20 23:09:42

标签: python button tkinter bind

这个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

提前感谢您提供给我的任何启示。

&lt;&lt;&lt;&lt; --- UM,请检查以下内容。 。 。 ---&GT;&GT;&GT;

在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;谢谢大家的灵感!

0 个答案:

没有答案