Radiobutton in einer Klasse

Fragen zu Tkinter.
Antworten
silas247
User
Beiträge: 4
Registriert: Mittwoch 17. Dezember 2014, 21:19

Hey Leute,
ich habe hier bei der klasse das Problem das er die variablen von den radiobuttons nicht richtig abgreift
er sendet keinen fehler aus die Gui wird ausgeführt und alles aber er gibt mir jedes mal 0, 0 aus.
Vlt hat jmd eine Lösungsidee ? :)
Danke schonmal im vorraus .

Code: Alles auswählen

class SettingsGui(tk.Tk):
    def __init__(self,parent):
        tk.Tk.__init__(self,parent)
        self.initialize(parent)
        self.mainloop()
    def initialize(self,parent):
        
        self.bdfIn=tk.IntVar()
        self.bdfOut=tk.IntVar()
        
        self.grid()
        self.title("Settings")
        self.bdfFrame=tk.Frame(self)
        self.bdfInLabel=tk.Label(self.bdfFrame,text="Programm In")
        self.binIn=ttk.Radiobutton(self.bdfFrame,text="bin",value=0,
                                 variable=self.bdfIn)
        self.decIn=ttk.Radiobutton(self.bdfFrame,text="dec",value=1,
                                 variable=self.bdfIn)
        self.hexIn=ttk.Radiobutton(self.bdfFrame,text="hex",value=2,
                                 variable=self.bdfIn)
        self.bdfOutLabel=tk.Label(self.bdfFrame,text="Programm Out")
        self.binOut=ttk.Radiobutton(self.bdfFrame,text="bin",value=0,
                                 variable=self.bdfOut)
        self.decOut=ttk.Radiobutton(self.bdfFrame,text="dec",value=1,
                                 variable=self.bdfOut)
        self.hexOut=ttk.Radiobutton(self.bdfFrame,text="hex",value=2,
                                 variable=self.bdfOut)
        
        self.ButtFrame=tk.Frame(self)
        self.Cancel=ttk.Button(self.ButtFrame,text="Cancel", command=self.destroy)
        self.Save=ttk.Button(self.ButtFrame,text="Save",command=self.Save)
        
        
        self.bdfFrame.pack()
        self.bdfInLabel.grid(row=1,column=1)
        self.binIn.grid(row=1,column=3)
        self.decIn.grid(row=1,column=5)        
        self.hexIn.grid(row=1,column=7)
        self.bdfOutLabel.grid(row=3,column=1)
        self.binOut.grid(row=3,column=3)
        self.decOut.grid(row=3,column=5)        
        self.hexOut.grid(row=3,column=7)
        
        self.ButtFrame.pack()
        self.Cancel.grid(row=1,column=1)
        self.Save.grid(row=1,column=3)

    def Save(self):
        global bdfInput
        global bdfOutput
        bdfInput=self.bdfIn.get()
        bdfOutput=self.bdfOut.get()
        print(self.bdfIn.get(),self.bdfOut.get())
BlackJack

@silas247: Das Problem kann ich nicht nachvollziehen. Wenn ich andere Optionen wähle, dann gibt `Save()` auch andere Werte aus.

Die ``global``-Anweisungen solltest Du loswerden. Das ist ja grundsätzlich schon keine gute Idee, aber in Methoden ist das ein grober Entwurfsfehler.

Bei der Namensschreibweise und der Formatierung des Quelltextes lohnt ein Blick in den Style Guide for Python Code.

Die Das Attribut der schaltfläche zum Speichern überschreibt die Methode `Save()`. Da hast Du Glück das die danach nicht mehr verwendet wird. Man muss auch nicht alles an das Objekt binden sondern nur die Sachen die man später auch tatsächlich noch einmal benötigt. Das betrifft so einige Frames und Buttons.

Man sollte keine Abkürzungen in Namen verwenden die nicht allgemein bekannt sind. Besonders lustig fand ich `ButtFrame`. :-D

Ein Widget sollte sich nicht selbst layouten und auch nicht bei der Initialisierung die GUI-Hauptschleife aufrufen. Das schränkt den Aufrufer zu sehr ein. Kein vorhandenes Widget macht so etwas.

Eine extra `initialize()`-Methode zusätzlich zur `__init__()` ist irgendwie sinnfrei. Zum initialisieren des Objekts ist die `__init__()` doch schon da.

Es wiederholt sich Code in der `initialize()`-Methode. Das würde ich da herausziehen. Als Methode/Funktion oder gleich als eigenes Widget. Die `grid()`\s dort haben Lücken. Falls das Absicht war um irgendwelche Abstände in der Anzeige zu erzielen: Das sollte man nicht als garantiert ansehen. Ob da Abstände bei leeren Zeilen/Spalten angezeigt werden und wie gross die sind falls es sie gibt, kann von der Plattform, Themes, und anderen Faktoren abhängen.
silas247
User
Beiträge: 4
Registriert: Mittwoch 17. Dezember 2014, 21:19

Okay iwie scheint das Problem nicht allein bei der Klasse auszugehen wie ich es vermutet hatte(weil der rest des programmes ohne Probleme läuft)
Das mit dem Global hatte ich gemacht weil auch andere Klassen darauf zugreifen müssen.

was meinst du mit
Die Das Attribut der schaltfläche zum Speichern überschreibt die Methode `Save()`. Da hast Du Glück das die danach nicht mehr verwendet wird.
so hier ist der rest des programmcodes sry ist ziemlich lang aufgerufen wird die klasse SettingsGui in Zeile: 106
ja ich weis mein code ist nicht leicht zu entziffern werde ich bald überarbeiten damit er für andere leichter zu erschließen ist :roll:
In der letzten Zeile gebe ich nochmal die eig ja veränderten globalen variablen aus die sich aber nicht verändert haben :/

Code: Alles auswählen

import tkinter as tk
from tkinter import ttk

#Variablem
bdfInput=0
bdfOutput=0

def popmsg(msg):
    popmsg=tk.Tk()
    label=ttk.Label(popmsg,text=msg)
    button=ttk.Button(popmsg,text="Okay",command=popmsg.destroy)
    label.pack()
    button.pack()
    popmsg.mainloop()
    return

class main(tk.Tk):
    def __init__(self,parent):
        tk.Tk.__init__(self,parent)
        self.parent=parent
        self.initialize()

    def initialize(self):
        self.grid()
        self.geometry("500x500")
        self.title("Rom Designer")
        assFrame=AssemblerFrame(self)
        codFrame=CodingFrame(self)
        menubar=Menu(self)

        

class SettingsGui(tk.Tk):
    def __init__(self,parent):
        tk.Tk.__init__(self,parent)
        self.initialize(parent)
        self.mainloop()
    def initialize(self,parent):
        
        self.bdfIn=tk.IntVar()
        self.bdfOut=tk.IntVar()
        
        self.grid()
        self.title("Settings")
        self.bdfFrame=tk.Frame(self)
        self.bdfInLabel=tk.Label(self.bdfFrame,text="Programm In")
        self.binIn=ttk.Radiobutton(self.bdfFrame,text="bin",value=0,
                                 variable=self.bdfIn)
        self.decIn=ttk.Radiobutton(self.bdfFrame,text="dec",value=1,
                                 variable=self.bdfIn,command=self.Save)
        self.hexIn=ttk.Radiobutton(self.bdfFrame,text="hex",value=2,
                                 variable=self.bdfIn)
        self.bdfOutLabel=tk.Label(self.bdfFrame,text="Programm Out")
        self.binOut=ttk.Radiobutton(self.bdfFrame,text="bin",value=0,
                                 variable=self.bdfOut)
        self.decOut=ttk.Radiobutton(self.bdfFrame,text="dec",value=1,
                                 variable=self.bdfOut)
        self.hexOut=ttk.Radiobutton(self.bdfFrame,text="hex",value=2,
                                 variable=self.bdfOut)
        
        self.ButtFrame=tk.Frame(self)
        self.Cancel=ttk.Button(self.ButtFrame,text="Cancel", command=self.destroy)
        self.Save=ttk.Button(self.ButtFrame,text="Save",command=self.Save)
        
        
        self.bdfFrame.pack()
        self.bdfInLabel.grid(row=1,column=1)
        self.binIn.grid(row=1,column=3)
        self.decIn.grid(row=1,column=5)        
        self.hexIn.grid(row=1,column=7)
        self.bdfOutLabel.grid(row=3,column=1)
        self.binOut.grid(row=3,column=3)
        self.decOut.grid(row=3,column=5)        
        self.hexOut.grid(row=3,column=7)
        
        self.ButtFrame.pack()
        self.Cancel.grid(row=1,column=1)
        self.Save.grid(row=1,column=3)
        
        
    def Save(self):
        global bdfInput
        global bdfOutput
        bdfInput=self.bdfIn.get()
        bdfOutput=self.bdfOut.get()
        print(self.bdfIn.get(),self.bdfOut.get())
        

class Menu(tk.Frame):
    def __init__(self,parent):
        tk.Frame.__init__(self,parent)
        self.pack(side="top",fill="both",expand=True)
        self.initialize(parent)
        
    def initialize(self,parent):
        self.menuBar=tk.Menu(self)
        
        self.fileMenu=tk.Menu(self.menuBar)
        self.fileMenu.add_command(label="New",command=lambda:fm_New)
        self.fileMenu.add_command(label="Open",command=lambda:fm_Open)
        self.fileMenu.add_command(label="Save as",command=lambda:fm_SaveAs)
        self.fileMenu.add_command(label="Exit", command=lambda:fm_Quit)
        self.menuBar.add_cascade(label="File",menu=self.fileMenu)

        self.optionsMenu=tk.Menu(self.menuBar,tearoff=0)
        self.optionsMenu.add_command(label="Settings",command=lambda:SettingsGui(None))
        self.optionsMenu.add_command(label="Font")
        self.menuBar.add_cascade(label="Options",menu=self.optionsMenu)

        self.helpMenu=tk.Menu(self.menuBar,tearoff=0)
        self.helpMenu.add_command(label="Help Documents")
        self.helpMenu.add_command(label="About")
        self.menuBar.add_cascade(label="Help",menu=self.helpMenu)

        
        parent.config(menu=self.menuBar)
        


class AssemblerFrame(tk.Frame):
    def __init__(self,parent):
        tk.Frame.__init__(self,parent)
        self.pack(side="left",fill="both",expand=True)
        self.initialize()

    def initialize(self):        
        self.DelButton=ttk.Button(self,text="Delete",command= lambda: self.Delete(0))
        self.AddButton=ttk.Button(self,text="Add",command= lambda: self.Add(0))
        self.RenButton=ttk.Button(self,text="Rename",command= lambda: self.Rename())
        self.Entry=ttk.Entry(self,width=37)
        self.TextBox=tk.Listbox(self,width=37,selectmode="extended")
        
        
        self.DelButton.grid(row=1,column=1)
        self.AddButton.grid(row=1,column=3)
        self.RenButton.grid(row=1,column=5)
        self.Entry.place(x=0,y=25)
        self.TextBox.place(x=0,y=50)

        
        self.bind("<Delete>", self.Delete)
        self.Entry.bind("<Return>", self.Add)

    def Add(self, x):
        self.TextBox.insert(tk.END, self.Entry.get())
        self.Entry.delete(0,tk.END)
    def Delete(self, x):
        select=self.TextBox.curselection()
        if select!=():
            for i in range(len(select)-1,-1,-1):
                self.TextBox.delete(select[i])
        else:
            tk.messagebox.showerror(title="Error",message="Nothing is currently selected")
    def Rename(self):
        self.TextBox.insert(tk.ACTIVE, self.Entry.get())
        self.TextBox.delete(tk.ACTIVE)
            
    
        
class CodingFrame(tk.Frame):

    def __init__(self,parent):
        tk.Frame.__init__(self,parent)
        self.pack(side="right",fill="both",expand=True)
        self.initialize()

    def initialize(self):        
        self.DelButton=ttk.Button(self,text="Delete",command= lambda: self.Delete(0))
        self.AddButton=ttk.Button(self,text="Add",command= lambda: self.Add(0))
        self.ChanButton=ttk.Button(self,text="Change",command= lambda: self.Change())
        self.Entry=ttk.Entry(self,width=37)
        self.TextBox=tk.Listbox(self,width=37,selectmode="extended")
        
        
        self.DelButton.grid(row=1,column=1)
        self.AddButton.grid(row=1,column=3)
        self.ChanButton.grid(row=1,column=5)
        self.Entry.place(x=0,y=25)
        self.TextBox.place(x=0,y=50)

        self.bind("<Delete>", self.Delete)
        self.Entry.bind("<Return>", self.Add)
        
    def Add(self, x):
        self.TextBox.insert(tk.END,self.Entry.get())
        self.Entry.delete(0,tk.END)
    def Delete(self, x):
        select=self.TextBox.curselection()
        if select!=():
            for i in range(len(select)-1,-1,-1):
                self.TextBox.delete(select[i])
        else:
            tk.messagebox.showerror(title="Error",message="Nothing is currently selected")
    def Change(self):
        self.TextBox.insert(tk.ACTIVE, self.Entry.get())
        self.TextBox.delete(tk.ACTIVE)



app=main(None)
app.mainloop()
print(bdfInput,bdfOutput)
BlackJack

@silas247: Das andere ”Klassen” darauf zugreifen sollen ist kein Grund für ``global``. Dann muss man halt die Objekte untereinander bekannt machen die auf die Werte zugreifen müssen. Klassen sind ja gerade *der* Weg um diese globalen Daten und damit Abhängigkeiten loszuwerden.

Du hast eine Methode die heisst `Save` auf dem Objekt und in der `__init__()` bindest Du das Attribut `Save` an eine Schaltfläche. Damit ist die Methode dann nicht mehr unter dem Namen erreichbar denn bei einem Attributzugriff kann es genau einen Wert als Ergebnis geben.

Die Ursache des Problems sind die `Tk`-Exemplare. Das ist *das* *Haupt*fenster. Es darf davon zur gleichen Zeit immer nur *ein* einziges Objekt davon geben. Sonst passieren komische Sachen. Zusätzliche Fenster erstellt man als `Tkinter.Toplevel`-Exemplare. Solange man sich nicht wirklich gut mit Tk auskennt sollte man auch nur eine `mainloop()` am laufen haben.

Oh mann, `assFrame` ist ja noch besser als `buttFrame`… :-D
Antworten