anfängerfrage: toplevel soll zugriff auf tk verhindern

Fragen zu Tkinter.
Antworten
geogre
User
Beiträge: 41
Registriert: Mittwoch 20. April 2005, 13:26

hallöchen... ich hab noch eine anfängerfrage - ähem - also, ich habe ein tk() für meine anwendung erstellt mit den ganzen widgets drin und möchte jetzt über ein menü ein toplevel() aufrufen, das klappt soweit auch ganz problemlos.

ich möchte nun aber - da in dem toplevel optionen eingestellt werden können sollen - daß solange das toplevel da ist man das tk (root) nicht mehr bedienen kann. muss ich dafür alle widgets darin einzeln deaktivieren oder kann ich dem toplevel eine eigenschaft geben die eben dies ermöglicht? ich hatte hier in einem beitrag von focus_force gelesen, aber das scheint es nicht zu sein.

das toplevel soll dann nur einen ok und einen abbrechen button haben (evtl. noch zurücksetzen), die beide das toplevel entfernen und das tk wieder zugänglich machen und aktivieren sollen, nur das ok-button halt die änerungen in eine datei speichert. wie mach ich das am besten (das toplevel zerstören mein ich). ich habe sys.exit(0) versucht, das fragt zweimal 'do you want to exit altogether' (was ich natürlich nicht will) und gibt dann eine fehlermeldung aus.

sorry, ich weiß daß das nicht sehr niveauvolle fragen sind, aber in meinem py-buch steht über toplevel-widgets nicht sehr viel drin. danke für evtl. hilfe!!
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Du suchst modale Fenster, gehen vermutlich mit grab_set().
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
Michael Schneider
User
Beiträge: 569
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Brandenburg

Leonidas hat geschrieben:Du suchst modale Fenster, gehen vermutlich mit grab_set().
Ja, ich bin auch vor ca. 2 Tagen rein zufällig auf dieses Thema in "Das Python-Buch" gestoßen. Hier eine Demo:

Code: Alles auswählen

from Tkinter import *

def create_main_window(tk):
    "Erzeuge das tk-Hauptfenster"
    wFrame = Frame(tk, width = 400, height = 300, bg = "#aaffaa")
    wFrame.master.wm_title("Tk Hauptfenster")
    wFrame.grid()
    wEntry = Entry(wFrame, width = 20)
    wEntry.insert(0, "hier Text eingeben")
    wEntry.grid(row = 10, column = 1, padx = 100, pady = 50)
    return wFrame

def create_options_window(wFrame):
    "Erzeuge das Pop-up Optionsfenster"
    oGrabStatus = IntVar()
    wTopLevel = Toplevel(wFrame, width = 400, height = 200)
    
    wLabel = Label(wTopLevel, text = "Einstellungen...", width = 60)
    wLabel.grid(row = 1, column = 1, columnspan = 3)

    def set_grab():
        wTopLevel.grab_set()
        wTopLevel.wm_title("Optionsfenster mit grab")
        oGrabStatus.set(True)
        print "grab gesetzt"
    wOptionGrabSet = Radiobutton(wTopLevel, text = "setze grab", value = 1, command = set_grab,
                                 variable = oGrabStatus, indicatoron = False)
    wOptionGrabSet.grid(row = 2, column = 1, columnspan = 3, ipadx = 10, ipady = 2)
    set_grab()      ##  Manuell bei Generierung setzen

    def release_grab():
        wTopLevel.grab_release()
        wTopLevel.wm_title("Optionsfenster ohne grab")
        oGrabStatus.set(False)
        print "grab geloest"
    wOptionGrabRelease = Radiobutton(wTopLevel, text = "loese grab", value = 0, command = release_grab,
                                     variable = oGrabStatus, indicatoron = False)
    wOptionGrabRelease.grid(row = 3, column = 1, columnspan = 3, ipadx = 10, ipady = 2)
        
    def ok_handler():
        print "OK Aktionen"
        wTopLevel.destroy()
    wButtonOk = Button(wTopLevel, text = "OK", command = ok_handler)
    wButtonOk.grid(row = 5, column = 1)

    def abbruch_handler():
        print "Abbruch Aktionen"
        wTopLevel.destroy()
    wButtonAbbruch = Button(wTopLevel, text = "Abbruch", command = abbruch_handler)
    wButtonAbbruch.grid(row = 5, column = 3)
    return wTopLevel

def create_main_menubar(wFrame):
    "Erzeuge Menuezeile, die an einen Frame angehaengt wird"
    wFrame.MenuBarFrame = Frame(wFrame, relief = RAISED, bd = 2)
    wFrame.MenuBarFrame.grid(row = 1, column = 1, sticky = NSEW)

    wFrame.MenuBarButtonOptions = Menubutton(wFrame.MenuBarFrame, text = "Optionen",
                                             underline = 0, relief = RIDGE)
    wFrame.MenuBarButtonOptions.pack(side = LEFT)

    wFrame.MenuBarMenuOptions = Menu(wFrame.MenuBarButtonOptions, tearoff = False)
    MBMO = wFrame.MenuBarMenuOptions

    def option_handler():
        wTopLevel = create_options_window(wFrame)
        wTopLevel.grid()
        wTopLevel.focus_set()
        wTopLevel.grab_set()

    def option_handler_global():
        wTopLevel = create_options_window(wFrame)
        wTopLevel.grid()
        wTopLevel.focus_set()
        wTopLevel.grab_set_global()
        
    wFrame.MenuBarButtonOptions["menu"] = MBMO
    MBMO.add_command(label = "Einstellungen mit localem grab", command = option_handler)
    MBMO.add_command(label = "Einstellungen mit globalem grab", command = option_handler_global)
    MBMO.add_separator()
    MBMO.add_command(label = "Beenden", command = wFrame.master.destroy)


tk = Tk()
main = create_main_window(tk)
create_main_menubar(main)
main.mainloop()
Mit grab schnappt man also den anderen Fenstern die Eingaben weg. Ich habe hier (Auflage '97) folgende Methoden:
toplevel.grab_set() - für Grabs der Anwendung
toplevel.grab_set_global() - für Grabs aller Fenster (laut meinem Buch, aber da steht auch "grab_global", vielleicht geht das unter X11 anders)
toplevel.grab_release() - locale und globale grabs lösen
toplevel.grab_current() - Widget mit aktuellem Grab erfragen[/quote]
Ich hoffe, die Demo ist nicht zu umfangreich, denn man kann damit schön rumspielen. Sie erzeugt ein Fenster mit Menü, von dem aus man das Einstellungsfenster mit grab aufrufen kann. So habe ich jedenfalls die Spezifikation von geogre verstanden.

Grüße,
Michael
Diese Nachricht zersört sich in 5 Sekunden selbst ...
jocsch
User
Beiträge: 31
Registriert: Freitag 4. April 2003, 13:09
Wohnort: Egloffstein (Hundshaupten)

Moin!
Ich nehem dafür immer die Klasse 'Dialog' aus dem Modul 'tkSimpleDialog':

Code: Alles auswählen

import tkSimpleDialog

class meinDialog(tkSimpleDialog.Dialog):
    #hier können voreinstellungen übergeben werden
    def __init__(self, master, einWert = 'ich bin die Eingabe'):
        self.einWert = einWert
        tkSimpleDialog.Dialog.__init__(self, master)
    
    #hier kommt der inhalt des dialogfensters
    def body(self, master):
        self.eingabe = Entry(master, bg = 'red')
        self.eingabe.pack()
        self.eingabe.insert(0, self.einWert) #...die voreinstellungen

    #apply wird beim druck auf ok aufgerufen
    def apply(self):
        self.result = self.eingabe.get()

#jetzt braucht man noch eine funktion, die das ganze 'auswertet'
def welcherWert(parent, somewhat): #parent ist das Tk(), innerhalb einer von Tk() abgeleiteten Applikation durch 'self' ersetzen.
    spam = meinDialog(parent, somewhat)
    return spam.result

#so benutzt man das ganze dann:
wertDenIchBrauche = welcherWert(parent, '4ogre')
Der 'Dialog' ist zwar nicht ganz so komfortabel (Kein 'Anwenden'-Knopf), dafür aber ziemlich simple.

grüsse, jocsch
(vlpgj1)
Benutzeravatar
Michael Schneider
User
Beiträge: 569
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Brandenburg

jocsch hat geschrieben:Moin!
Ich nehem dafür immer die Klasse 'Dialog' aus dem Modul 'tkSimpleDialog'
...
Der 'Dialog' ist zwar nicht ganz so komfortabel (Kein 'Anwenden'-Knopf), dafür aber ziemlich simple.
Moin Jocsch!

Wahrscheinlich ist das wesentliche meines Postings untergegangen, denn was ich dort oben schrieb war schon eine ganze Beispielanwendung zum rumspielen.
Worauf es ankommt sind die Methoden grab_set und evtl. grab_release (sofern das Toplevel-Fenster nach Eingabe nicht zerstört wird), die vermutlich auch von dem Dialog gerufen werden.

Im Prinzip reicht der Ruf von grab_set völlig aus, um die gewünschte Funktionalität des Toplevelfensters zu erhalten. Ist doch mindestens genauso einfach. :D

Gruß,
der Michel
Diese Nachricht zersört sich in 5 Sekunden selbst ...
Antworten