Anwendung von __dict__[]

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Dictionaries sehen bereits nach dem richtigen Weg aus. Aber um meine Frage von oben noch einmal auf Dictionaries anzuwenden: was genau meinst du mit "Namensraum"? Gibt es zu jedem Schlüssel eine vorher bekannte Anzahl an Variablen und ist die Anzahl der Variablen bei allen Schlüsseln gleich? Handelt es sich nur um Daten oder sind es eher Objekte?
Das Leben ist wie ein Tennisball.
hypnoticum
User
Beiträge: 132
Registriert: Dienstag 15. März 2011, 15:43

Ich kriegs nicht hin. Die Checkboxen werden einfach nicht gestzt, obwohl die Werte im "TestDict"-Dictionary stehen. Hier mal nur für einen Namen:
(Korrektur: Es funktioniert doch, aber seltsamerweise nur in diesem Minimalbeispiel. Ich werde mal sehen, wo der Fehler ist ...)

Code: Alles auswählen

import Tkinter

TestDict = {'eins': '1', 'zwei': '0'}
class TestClass(object): pass
MasterName = Tkinter.Tk()
       
i = 0
TestInstance = TestClass()
for Test in TestDict:
    setattr(TestInstance, Test, Tkinter.IntVar())
    TestInstance.__dict__[Test].set(int(TestDict[Test]))
    Tkinter.Checkbutton(MasterName, text = Test, variable = TestInstance.__dict__[Test]).grid(sticky = Tkinter.W, row = i, column = 0, columnspan = 1)
    i = i + 1
    
MasterName.mainloop()
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

Ich habe dein vorheriges Script auch noch gesehen... Was zur Hölle tust du da? Nochmal und das gilt für beide Scripte - Finger weg von .__dict__

Vieleicht wäre es besser mal den Sinn dahinter zu erklären warum du solch eine Strucktur brauchst, dann könnte man vieleicht eine adäquat Lösung finden.
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
BlackJack

@hypnoticum: Ich würde mich dem anschliessen: Finger weg von `__dict__` und versuch doch mal "pythonischer" zu schreiben. Das mit der Gross-/Kleinschreibung führt zum Beispiel IMHO immer wieder zu Verständnisproblemen -- wenn etwas mit einem Grossbuchstaben beginnt, dann ist das in den Köpfen von Pythonprogrammierern der Name einer Klasse und man muss immer umdenken wenn dem dann nicht so ist. Dann kann man sich auch Zusätze wie `Class` oder `Instance` sparen, denn dann ist klar das `Test` eine Klasse und `test` ein Exemplar ist.

`MasterName` ist irreführend, weil es kein Name ist.

Das manuelle hochzählen von `i` würde man eher durch `enumerate()` ersetzen und wenn Du in der Schleife immer auch den Wert zu einem Schlüssel benötigst, kannst Du auch gleich über die Schlüssel/Wert-Paare iterieren. So sieht das IMHO auch deutlich "aufgeräumter" aus:

Code: Alles auswählen

import Tkinter as tk

name2value = {'eins': '1', 'zwei': '0'}

class Test(object):
    pass

master = tk.Tk()

test = Test()
for i, (name, value) in enumerate(name2value.iteritems()):
    int_var = tk.IntVar()
    int_var.set(int(value))
    setattr(test, name, int_var)
    checkbutton = tk.Checkbutton(master, text=name, variable=int_var)
    checkbutton.grid(sticky=tk.W, row=i, column=0)

master.mainloop()
hypnoticum
User
Beiträge: 132
Registriert: Dienstag 15. März 2011, 15:43

OK, vielen Dank für die Hilfe.
Ich werde versuchen mich hinsichtlich meiner Schreibweise zu bessern.
Eine weitere Frage habe ich aber noch. Die gehört dann eher in die Ecke Tkinter-Probleme:

Wenn ich die Variable vom Typ IntVar() in einem Toplevel-Fenster erzeuge, dann muss ich das komischerweise immer als Atttribut des Master-Fensters machen ("self.master.test"), damit die CheckButtons auch gesetzt werden. Eigentlich geht es doch das Master-fenster nichts an, oder?

Code: Alles auswählen

from Tkinter import *

class TestGUI(object):
    def __init__(self):
        self.master = Tk()
        self.init_widgets()
        self.master.mainloop()
        
    def init_widgets (self):
        btn = Button(master = self.master,
              text = 'Configure',
              command = lambda: ConfigDia(self.master))
        btn.pack()

class ConfigDia(object): 
    def __init__(self, Master):
        self.master = Master
        self.top = Toplevel()
        self.init_widgets()
          
    def init_widgets(self):
        class Test(object): 
            pass
        
        testDict = {'eins': '1', 'zwei': '0'}
        self.master.test = Test()
        for i, (name, value) in enumerate(testDict.iteritems()):
            int_var = IntVar()
            int_var.set(int(value))
            setattr(self.master.test, name, int_var)
            checkbutton = Checkbutton(self.top, text=name, variable=int_var)
            checkbutton.grid(sticky=W, row=i, column=0)
            
newTestGUI = TestGUI()
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

Tut es auch nicht, aber dem Toplevel-Widget interessiert das sehr.

Und tut mir leid das so sagen zu müssen, aber dein Programm da oben entbehrt sich mir jeder Logik, du hast sowohl die OOP umgangen als auch die grundlegenden Struckturen von Tk. Du solltest dringend mal in das Tkinter-Unterforum oder auf effbot.org dir ansehen wie man mit Tkinter arbeitet. Ich wüsste jetzt gar nicht wo ich anfangen soll.
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
BlackJack

@hypnoticum: Es muss nicht das "Masterfenster" sein sondern halt irgend ein Objekt das auch bestehen bleibt. Dein `ConfigDia`-Objekt wird ja erstellt, aber da nirgends eine Referenz drauf gehalten wird, kann es auch sofort nachdem die `__init__()` fertig ist, wieder aus dem Speicher beseitigt werden. Und damit auch alle Attribute des Objekts.

Edit: Insofern ist es schon fast Zufall dass das `Toplevel` überhaupt dauerhaft angezeigt wird und nicht verschwindet. Selbst auf Tk-Seite ist es nicht explizit mit irgendeinem "Objekt" verbunden, weil Du beim erstellen vom `Toplevel` kein Eltern-Widget angibst. Das sollte man besser tun, sonst kann es dadurch auch zu komischen Effekten kommen.
hypnoticum
User
Beiträge: 132
Registriert: Dienstag 15. März 2011, 15:43

@Xynon1:
Tut mir leid, dass ich keine Zeit dafür habe mich da einzuarbeiten.
Ich muss es learning on the fly versuchen.
ICH BIN WEDER PROGRAMMIERER, NOCH INFORMATIKER.
Bisher konnte ich mir in MSVS meine GUI zusammenklicken.
Auch mit OOP hatte ich wenig Kontakt, hatte halt immer nur kleine Probleme ohne wirklich nötige Projektstruktur.
Ich kann nicht erst zu jedem Thema ein Buch was lesen bevor ich anfange. Ein Buch zu Python habe ich überflogen, aber bekanntlich steht in keinem Buch alles.

@BlackJack:
Also darum kann ich nun dem Toplevel-Widget zB. ein Attribut des master-Fensters bekannt machen, obwohl es in einem ganz anderen Dialog "hängt", das hilft mir weiter.
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

Diese Art von "learning on the fly" endet aber immer gleich man stürzt ab. Versuch es mal so:

Code: Alles auswählen

import Tkinter as tk
import tkSimpleDialog

class TestGUI(tk.Frame):
    
    def __init__(self, master, **kwargs):
        tk.Frame.__init__(self, master, kwargs) 
        self.init_widgets()

    def get_config(self):
        config = ConfigDia(self)
        print dir(config)
        print config.eins
        
    def init_widgets(self):
        btn = tk.Button(self, text="Configure", command=self.get_config)
        btn.pack()


class ConfigDia(tkSimpleDialog.Dialog):

    def body(self, master):
        test_dict = {'eins': '1', 'zwei': '0'}
        for i, (name, value) in enumerate(test_dict.iteritems()):
            int_var = tk.IntVar()
            int_var.set(int(value))
            setattr(self, name, int_var)
            # Edit: self zu master gemacht 
            checkbutton = tk.Checkbutton(master, text=name, variable=int_var)
            checkbutton.pack()
            

if __name__ == "__main__":
    root = tk.Tk()

    test = TestGUI(root)
    test.pack()

    root.mainloop()
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
Antworten