Ошибка инициализации переключателя Tkinter - PullRequest
7 голосов
/ 22 февраля 2011

Если я вставлю переключатель в функцию и нарисую их;в первый раз, когда они нарисованы, вы не можете навести на них курсор, не сделав их похожими на всех.

Этот же код из функции не демонстрирует такое поведение.

from Tkinter import *

def App(master):
    v = StringVar()
    v.set('python') # initialize
    lable1 = Label(master, text=' hovering over below radio buttons will cause them to look like they are selected')
    lable1.pack()
    runtimeFrame = Frame(master, relief=GROOVE,  borderwidth = 3)
    runtimeFrame.pack(fill = X, pady = 5, padx = 5)
    for mode in ['java', 'python', 'jython']:
        b = Radiobutton(runtimeFrame, text=mode, variable=v, value=mode, indicatoron = 1 )
        b.pack(side = LEFT)


if __name__ == '__main__':
    master = Tk()

    App(master)

    #The following code chunk is the same as that in App()
    #------------------------
    v = StringVar()
    v.set('python') # initialize
    lable1 = Label(master, text=' hovering over below radio buttons will cause them to Not look selected as expected')
    lable1.pack()
    runtimeFrame = Frame(master, relief=GROOVE,  borderwidth = 3)
    runtimeFrame.pack(fill = X, pady = 5, padx = 5)
    for mode in ['java', 'python', 'jython']:
        b = Radiobutton(runtimeFrame, text=mode, variable=v, value=mode, indicatoron = 1 )
        b.pack(side = LEFT)
    #------------------------

    mainloop() 

После того, как вы сделали выбор, это больше не повторяется.Я делаю что-то неправильно?Есть ли обходной путь, потому что мой код должен быть в функции!

Это вторая элементарная ошибка, которую я обнаружил в Tkinter.Есть ли что-то лучшее для разработки Python GUI?

ps: я использую python 2.7

Ответы [ 4 ]

10 голосов
/ 23 июня 2011

Место, где вы храните переменный объект (в вашем случае StringVar, v), должно сохраняться, чтобы это странное поведение не проявилось. Я предполагаю, что мы наблюдаем это поведение, потому что v выходит из области видимости, что-то идет не так. Помимо использования global, я не могу придумать способ сделать это из функции.

Сломанный код:

from Tkinter import *

def App(master):
    v = StringVar()
    v.set('python')

    lable1 = Label(master, text=' hovering over below radio buttons will cause them to look like they are selected')
    lable1.pack()

    runtimeFrame = Frame(master, relief=GROOVE, borderwidth=3)
    runtimeFrame.pack(fill=X, pady=5, padx=5)
    for mode in ['java', 'python', 'jython']:
        b = Radiobutton(runtimeFrame, text=mode, variable=v, value=mode, indicatoron=1)
        b.pack(side=LEFT)

if __name__ == '__main__':
    master = Tk()
    App(master)
    mainloop()

Пример исправления:

from Tkinter import *

def App(master, radio_var):
    radio_var.set('python')

    lable1 = Label(master, text=' hovering over below radio buttons will cause them to look like they are selected')
    lable1.pack()

    runtimeFrame = Frame(master, relief=GROOVE, borderwidth=3)
    runtimeFrame.pack(fill=X, pady=5, padx=5)
    for mode in ['java', 'python', 'jython']:
        b = Radiobutton(runtimeFrame, text=mode, variable=radio_var, value=mode, indicatoron=1)
        b.pack(side=LEFT)

if __name__ == '__main__':
    master = Tk()
    radio_var = StringVar()
    App(master, radio_var)
    mainloop()

Учтите, что если вам нужно сохранить несколько переменных, вы можете передать список или словарь переменных.

Кроме того, на случай, если «должен быть в функции» - это требование к домашнему заданию, подумайте об упаковке кода в классе. Я не эксперт по тк, но, похоже, это предпочтительный способ организации вашего кода.

Пример исправления 2:

    from Tkinter import *

class App(object):
    def __init__(self, master):
        self.radio_var = StringVar()
        self.radio_var.set('python')

        lable1 = Label(master, text=' hovering over below radio buttons will cause them to look like they are selected')
        lable1.pack()

        runtimeFrame = Frame(master, relief=GROOVE, borderwidth=3)
        runtimeFrame.pack(fill=X, pady=5, padx=5)
        for mode in ['java', 'python', 'jython']:
            b = Radiobutton(runtimeFrame, text=mode, variable=self.radio_var, value=mode, indicatoron=1)
            b.pack(side=LEFT)

if __name__ == '__main__':
    master = Tk()
    app = App(master)
    mainloop()

Обратите внимание на незначительное изменение в

app = App(master)

Это необходимо для того, чтобы экземпляр приложения не собирался преждевременно. Это фактически вывело бы self.radio_var из области видимости, и мы вернулись на круги своя.

1 голос
/ 11 июня 2018

Я знаю, что прошло много времени, но я перепробовал все стратегии, показанные здесь, и ни одна из них не работала со мной. Для меня сработало простое «переписывание» обработчика событий для события движения мыши. Это не идеальное решение, потому что я печатаю какую-то фигню в терминал, но в моем конкретном случае это не проблема.

server_name = IntVar()
server_name.set(1)
server_name_rb_1 = Radiobutton(container_3, text="Server", variable=server_name, value=1)
server_name_rb_1.select()
server_name_rb_1.pack()
server_name_rb_2 = Radiobutton(container_3, text="Local", variable=server_name, value=2)
server_name_rb_2.deselect()
server_name_rb_2.pack()

server_name_rb_2.bind('<Motion>',lambda e: print(str(server_name.get())) )

P.S .: Вам не нужно переписывать все функции, просто достаточно переписать одну из них.

0 голосов
/ 21 мая 2016

Попробуйте, у меня все работает.

v = 0  # this is global variable

def some_function():
    global v
    v = IntVar()
    v.set(0)


    rb1 = Radiobutton (parent, variable = v, value = 0)
    rb1.pack()
    rb2 = Radiobutton (parent, variable = v, value = 1)
    rb2.pack()

Сделайте ваши радио-кнопки, а затем вы получите ваши радио-кнопки, как они должны.

0 голосов
/ 07 марта 2011

Я признаю, что вы нашли довольно странный "глюк".Я не совсем готов назвать это сбивкой с толку, поскольку я не уверен, что является причиной этого.Казалось, что это вытекает из аргумента переменная .Обходной путь - вместо получения переменной получить фактический текст виджета с помощью метода .cget ('text') .

Мои изменения в функции вашего приложения:

def App(master):
    v = StringVar()
    v.set('python') # initialize
    lable1 = Label(master, text=' hovering over below radio buttons will cause them to look like they are selected')
    lable1.pack()
    runtimeFrame = Frame(master, relief=GROOVE,  borderwidth = 3)
    runtimeFrame.pack(fill = X, pady = 5, padx = 5)
    for mode in ['java', 'python', 'jython']:
        b = Radiobutton(runtimeFrame, text=mode, value=mode, indicatoron = 1 ) # I omitted the variable argument, which seemed to be the root of your troubles. 
        b.pack(side = LEFT)
        b.deselect() # manually deselects each instance of the Radiobutton. 

    b.select() # manually selects a default instance of the Radiobutton. 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...