继续之前,Python Tkinter检查单选按钮状态

时间:2015-03-06 13:44:39

标签: python tkinter

我有这个正在运行的代码

import Tkinter as tk
from Tkinter import *


LARGE_FONT= ("Verdana", 12)

class ChangePages(tk.Tk):

    def __init__(self, *args, **kwargs):

        tk.Tk.__init__(self, *args, **kwargs)
        container = tk.Frame(self)
        container.pack()
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)
        self.frames = {}
        for F in (MainPage, Page01, Page02):

            frame = F(container, self)

            self.frames[F] = frame

            frame.grid(row=0, column=0, sticky="nsew")

        self.show_frame(MainPage)

    def show_frame(self, cont):

        frame = self.frames[cont]
        frame.tkraise()

#MainPage
class MainPage(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self,parent)

        button1=Button(self,text='Go To Page 1',fg='blue',font=('Helvetica',26),height=5, width=20,command=lambda: controller.show_frame(Page01)).grid(row=1,column=1)

#Page01
class Page01(tk.Frame):

    def __init__(self, parent, controller):

        option1 = IntVar()
        option2 = IntVar()
        option3 = IntVar()

        tk.Frame.__init__(self, parent)
        f = Frame(self)
        f.pack(side='left')

        label1=Label(f,text='Select options',fg='blue', font=("Arial", 36, "bold"),width=54, relief='solid').grid(row=1,column=1,columnspan=3)

        labelspacing=Label(f,text='Option 1 ',font=("Arial", 18, "bold"),width=20,height=1).grid(row=2,column=1)
        labelspacing=Label(f,text='Option 2 ',font=("Arial", 18, "bold"),width=20,height=1).grid(row=2,column=2)
        labelspacing=Label(f,text='Option 3',font=("Arial", 18, "bold"),width=20,height=1).grid(row=2,column=3)

        buttonoption11=Radiobutton(f, text="Option 1 - A", variable=option1, value=1, indicatoron=0, fg='blue',font=('Helvetica',26),height=1, width=20).grid(row=3,column=1)
        buttonoption21=Radiobutton(f, text="Option 2 - A", variable=option2, value=1, indicatoron=0, fg='blue',font=('Helvetica',26),height=1, width=20).grid(row=3,column=2)
        buttonoption31=Radiobutton(f, text="Option 3 - A", variable=option3, value=1, indicatoron=0, fg='blue',font=('Helvetica',26),height=1, width=20).grid(row=3,column=3)

        buttonoption12=Radiobutton(f, text="Option 1 - B", variable=option1, value=2, indicatoron=0, fg='blue',font=('Helvetica',26),height=1, width=20).grid(row=4,column=1)
        buttonoption22=Radiobutton(f, text="Option 2 - B", variable=option2, value=2, indicatoron=0, fg='blue',font=('Helvetica',26),height=1, width=20).grid(row=4,column=2)
        buttonoption32=Radiobutton(f, text="Option 3 - B", variable=option3, value=2, indicatoron=0, fg='blue',font=('Helvetica',26),height=1, width=20).grid(row=4,column=3)

        buttonoption23=Radiobutton(f, text="Option 2 - C", variable=option2, value=3, indicatoron=0, fg='blue',font=('Helvetica',26),height=1, width=20).grid(row=5,column=2)

        buttonnback=Button(f,text='Back',fg='blue',font=('Helvetica',26),height=1,width=15,command=lambda: controller.show_frame(MainPage)).grid(row=10,column=1)
        buttonnext=Button(f,text='Next',fg='blue',font=('Helvetica',26),height=3,width=15,command=lambda: controller.show_frame(Page02)).grid(row=10,column=2)

#Page02
class Page02(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        label = tk.Label(self, text="Page 02!!!", font=LARGE_FONT)
        label.pack(pady=10,padx=10)

        button1 = tk.Button(self, text="Back to Home",
                            command=lambda: controller.show_frame(MainPage))
        button1.pack()

        button2 = tk.Button(self, text="Page 01",
                            command=lambda: controller.show_frame(PageSub35t))
        button2.pack()


#Root loop
app = ChangePages()
app.mainloop()

我想做的是:

当用户在pag01中按下一个时,我想检查单选按钮的状态。例如,如果用户选择"选项1 -A"和"选项2 -C",我想弹出一条消息说"你不能选择2c!只有选择了1B,才能选择2c"不要让他去第02页。

1 个答案:

答案 0 :(得分:0)

我理解您的问题以及您希望如何解决它。但是,从用户体验的角度来看,有一种更好的方法可以做到这一点。除了显示用户无法选择和显示错误消息的用户选项外,最好仅向用户显示他可以选择的内容。场景示例:

  

用户选择选项1 -A

     

单选按钮选项2 -C变为灰色(禁用)

这是一个演示:

#very bad code
#http://stackoverflow.com/questions/28900100/python-tkinter-check-radio-button-state-before-proceed/28901595#28901595

try:#3.X
    import tkinter as tk
except ImportError:#2.X
    import Tkinter as tk

#use ttk cascade style techniques instead !!!
LARGE_FONT= ("Verdana", 12)

class ChangePages(tk.Tk):

    def __init__(self, *args, **kwargs):

        tk.Tk.__init__(self, *args, **kwargs)
        container = tk.Frame(self)
        container.pack() #use grid everywhere
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)
        self.frames = {}
        for F in (MainPage, Page01, Page02):

            frame = F(container, self)

            self.frames[F] = frame

            frame.grid(row=0, column=0, sticky="nsew")

        self.show_frame(MainPage)

    def show_frame(self, cont):

        frame = self.frames[cont]
        frame.tkraise()

class MainPage(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self,parent)

        button1 = tk.Button(self,text='Go To Page 1',fg='blue',font=('Helvetica',26),height=5, width=20,command=lambda: controller.show_frame(Page01)).grid(row=1,column=1)

class Page01(tk.Frame):

    def __init__(self, parent, controller):

        option1 = tk.IntVar()
        option2 = tk.IntVar()
        option3 = tk.IntVar()

        tk.Frame.__init__(self, parent)
        f = tk.Frame(self)
        f.pack(side='left')

        label1 = tk.Label(f,text='Select options',fg='blue', font=("Arial", 36, "bold"),width=54, relief='solid').grid(row=1,column=1,columnspan=3)

        #not used
        #labelspacing = tk.Label(f,text='Option 1 ',font=("Arial", 18, "bold"),width=20,height=1).grid(row=2,column=1)
        #labelspacing = tk.Label(f,text='Option 2 ',font=("Arial", 18, "bold"),width=20,height=1).grid(row=2,column=2)
        #labelspacing = tk.Label(f,text='Option 3',font=("Arial", 18, "bold"),width=20,height=1).grid(row=2,column=3)

        buttonoption21 = tk.Radiobutton(f, text="Option 2 - A", variable=option2, value=1, indicatoron=0, fg='blue',font=('Helvetica',26),height=1, width=20)
        buttonoption21.grid(row=3,column=2)
        buttonoption22 = tk.Radiobutton(f, text="Option 2 - B", variable=option2, value=2, indicatoron=0, fg='blue',font=('Helvetica',26),height=1, width=20)
        buttonoption22.grid(row=4,column=2)
        buttonoption32 = tk.Radiobutton(f, text="Option 3 - B", variable=option3, value=2, indicatoron=0, fg='blue',font=('Helvetica',26),height=1, width=20)
        buttonoption32.grid(row=4,column=3)

        buttonoption23 = tk.Radiobutton(f, text="Option 2 - C", variable=option2, value=3, indicatoron=0, fg='blue',font=('Helvetica',26),height=1, width=20)
        buttonoption23.grid(row=5,column=2)

        # this entire list is affected by switch_all_button()
        list_conditional = [buttonoption21, buttonoption22, buttonoption32, buttonoption23]


        def switch_button(button, active=True):
            if button is not None:
                button['state'] = {True: tk.NORMAL, False: tk.DISABLED}[active]
                #here you can also unselect

        def switch_all_button(active=True):
            for button in list_conditional:
                switch_button(button, active=active)

        def after_option_command(what_button_should_be_disabled=None):
            def after_option():
                switch_all_button(active=True)
                switch_button(what_button_should_be_disabled, active=False)
            return after_option


        # to update the state of other buttons after 1 is pressed
        # use command=after_option_command(button_x) in the constructor
        buttonoption11 = tk.Radiobutton(f, command=after_option_command(buttonoption23), text="Option 1 - A", variable=option1, value=1, indicatoron=0, fg='blue',font=('Helvetica',26),height=1, width=20)
        buttonoption11.grid(row=3,column=1)
        buttonoption12 = tk.Radiobutton(f, command=after_option_command(), text="Option 1 - B", variable=option1, value=2, indicatoron=0, fg='blue',font=('Helvetica',26),height=1, width=20)
        buttonoption12.grid(row=4,column=1)



        buttonnback = tk.Button(f,text='Back',fg='blue',font=('Helvetica',26),height=1,width=15,command=lambda: controller.show_frame(MainPage)).grid(row=10,column=1)
        buttonnext = tk.Button(f,text='Next',fg='blue',font=('Helvetica',26),height=3,width=15,command=lambda: controller.show_frame(Page02)).grid(row=10,column=2)

class Page02(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        label = tk.Label(self, text="Page 02!!!", font=LARGE_FONT)
        label.pack(pady=10,padx=10)

        button1 = tk.Button(self, text="Back to Home",
                            command=lambda: controller.show_frame(MainPage))
        button1.pack()

        button2 = tk.Button(self, text="Page 01",
                            command=lambda: controller.show_frame(PageSub35t))
        button2.pack()


#Root loop
app = ChangePages()
app.mainloop()

您不需要两次导入tkinter。使用此语法

try:  # 3.X
    import tkinter as tk
except ImportError:  # 2.X
    import Tkinter as tk
每次使用显式优于隐式的tkinter对象时,

都会强制您使用tk.。它也适用于Python 3。

#Page02
class Page02(tk.Frame):

这是一个无用的评论,因为它没有增加价值。 代码质量很差,但这里有解决方法:

  • 关注PEP8
  • 不要使用类作为词组的键
  • 使用ttkttk.Style()
  • 而不是在主代码中描述内容,而是在文件的外部或顶部进行操作
  • Widget.grid方法返回None,表示

    buttonoption11 = tk.Radiobutton(f, command=after_option_command(buttonoption23), text="Option 1 - A", variable=option1, value=1, indicatoron=0, fg='blue',font=('Helvetica',26),height=1, width=20).grid(row=3,column=1)

    • buttonoption11不是tk.Radiobutton,而是None
    • 除非你有充分的理由不
    • ,否则在任何地方使用.grid
    • 使用for循环创建类似的小部件

警告我给出的代码没有修复,请不要在应用上面给出的所有提示之前使用它

编辑:在评论中按预期工作,阅读评论以扩展API