2017-12-11 9 views
0

Ich arbeite mit Tkinter und habe Probleme, das OptionMenu ordnungsgemäß zu verwenden. Ich erstelle ein neues Fenster innerhalb einer Funktion, mit einem OptionMenu und einem Label. Einfach genug. Aber es scheint, dass ich keine Option aus dem OptionMenu auswählen kann. Wenn ich es außerhalb der Funktion stelle, funktioniert es gut. Aber ich muss in der Lage sein, das Fenster bei einem Funktionsaufruf zu erstellen.tkinter optionmenu funktioniert nicht

Hier ist die Funktion:

def ask_a_question(): 
    question = Tk() 
    question.geometry('300x100') 
    qs = ['test0', 'test1', 'test2'] 
    q = StringVar() 
    q.set(None) 
    Label(question, text = "placeholder").grid(row = 0, column = 0, padx = 10, pady = 10) 
    questions = OptionMenu(question, q, *qs) 
    questions.grid(row = 1, column = 0, padx = 10, pady = 10) 
    question.mainloop() 

Der obige Code ausführt, als ein Befehl auf eine Schaltfläche.

In dem Fenster, das es erstellt, kann ich alle Widgets sehen, aber die Auswahl einer der Optionen im OptionMenu aktualisiert es nicht. Ich hatte ein ähnliches Problem mit Schaltflächenbildern, als ich ein Fenster im Hauptcode erstellte und eine Schaltfläche in einer Funktion erstellte. Spielt tkinter nicht gut mit Funktionen? Oder gibt es einen Trick, damit es richtig funktioniert?

+3

Dies ist, weil Sie ein neues Fenster erstellen müssen, verwenden Sie 'Toplevel', nicht' Tk'. Ein Programm sollte nur einen einzigen Aufruf von 'Tk' haben. – Novel

+0

Ich denke, Sie sollten Klassen als Ihre 'Frage'-Fenster verwenden, die von' Toplevel'-Widget erben. Verwenden Sie dann eine Funktion, um ein Objekt dieser Klasse zu instanziieren. – Nae

+1

Um ein zweites Fenster zu erstellen, benutzen Sie 'question = Toplevel()' und benutzen Sie nicht das zweite 'mainloop()' weil es Probleme mit Werten in 'StringVar' verursacht. – furas

Antwort

0

zusammenfassend, was in den Kommentaren gesagt wurde:

  • Niemals mehrere Tk Instanzen verwenden, anstatt Toplevel Widgets verwenden.

  • Rufen Sie mainloop nur einmal auf dem Stammfenster (d. H. Die einzige Tk-Instanz).

So von Tk durch Toplevel in der Funktion ersetzen sollte Ihr Problem lösen. Hier ist der entsprechende Code:

import tkinter as tk 

def ask_a_question(): 
    question = tk.Toplevel(root) 
    question.geometry('300x100') 
    qs = ['test0', 'test1', 'test2'] 
    q = tk.StringVar(question, 'None') 
    tk.Label(question, text = "placeholder").grid(row=0, column=0, padx=10, pady=10) 
    questions = tk.OptionMenu(question, q, *qs) 
    questions.grid(row=1, column=0, padx=10, pady=10) 

root = tk.Tk() 

tk.Button(root, text='Question', command=ask_a_question).pack() 

root.mainloop() 

By the way, können Sie direkt den Anfangswert des StringVar als zweites Argument übergeben: tk.StingVar(master, initial_value).

Wenn das Hauptfenster so lange eingefroren werden soll, wie das Toplevel mit der Frage geöffnet ist, können Sie question.grab_set() in ask_a_question hinzufügen.

+0

Haben Sie einen Vorteil beim Importieren von tkinter als tk? Oder ist das nur der Klarheit halber? – user3477099

+0

@ user3477099 Wenn Sie 'von tkinter import *' ausführen, drängen Sie den Namespace mit vielen Dingen und manchmal kann es zu Problemen führen. Wenn Sie beispielsweise eine Klasse/Funktion/Variable mit demselben Namen wie eine TKinter definieren, kann es zu Namenskonflikten kommen. –

Verwandte Themen