Von einer Klasse in die Andere

Fragen zu Tkinter.
Antworten
superthorsten1
User
Beiträge: 6
Registriert: Mittwoch 16. November 2016, 20:08

Liebe Leute,

ich habe Probleme mit der Klasseninstanz eines Minimalbeispieles:

Code: Alles auswählen

#!/usr/bin/env python3
# coding: utf8

import tkinter as tk
#from hole_mini import *

class GUI(tk.Frame):

	def __init__(self,master=None):
			# erzeugen der graphischen Oberfläche
		super().__init__(master=master) 
		self.pack(side=tk.TOP, fill='x')
		self.create_widgets()
			# Erzeugen des Objektes zeug aus der Klasse Zeugs
		self.zeug = Zeugs()

	def create_widgets(self):
		self.l_pages = tk.Listbox(self,selectmode='extended',width=30)
		self.l_pages.pack()

		self.b_start = tk.Button(self,text="Start",command=self.test) # Page durchlaufen lassen
		self.b_start.pack()
		self.l_pages.insert(tk.END,"Hier sollen die Werte Eins Zwei und Drei hintereinander eingetragen werden")
	def test(self):
		self.zeug.listbox_fuellen()

	def appStart(self):
		self.mainloop()

class Zeugs():

	def listbox_fuellen(self):
		Values = ["Eins","Zwei","Drei"]
			# das hier funktioniert nicht
		for line in Values:
			gui.l_pages.insert(tk.END,line)		


def main():
	gui = GUI()
	gui.appStart()

if __name__ == "__main__":
	main()
Der Code besteht wesentlich aus zwei Klassen: GUI und Zeugs. aus GUI wird die Instanz gui erzeugt und aus gui heraus wird in der init aus Zeugs zeug als Objekt erstellt. Nun will ich mittels des Objektes zeug in gui eine Listbox füllen.

Frage:
Welche Instanz ist das dann ?
gui.l_pages.insert(tk.END,line) erzeugt:
NameError: global name 'gui' is not defined
Ist das nicht global ? Gut, ich habe es in main erzeugt, also könnte die Idee noch sein main.gui.l_pages.***
Das funktioniert aber auch nicht.

Für einen Tipp wäre ich dankbar.

Grüße,
Thorsten
Zuletzt geändert von Anonymous am Donnerstag 22. Dezember 2016, 16:11, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
Sirius3
User
Beiträge: 17746
Registriert: Sonntag 21. Oktober 2012, 17:20

@superthorsten1: alles, was eine Funktion an Variablen braucht, sollte sie über ihre Argumente bekommt. Wenn listbox_fuellen ein GUI-Objekt braucht, dann muß man es ihr übergeben. Insgesamt ist Dein Klassen-Design aber problematisch. Das sieht man zum Einen daran, dass Dir kein besserer Name als Zeugs für Zeugs eingefallen ist, zum Zweiten, dass Zeugs nur eine Methode hat, und keinen Zustand, dass das also gar keine Klasse ist, und zum Dritten, dass die Methode listbox_fuellen ein GUI-Objekt braucht, das ein l_pages Attribut hat. Damit ist die Klasse Zeugs zu eng mit GUI verbunden, so dass es keinen Sinn macht, hier eine Trennung einzuführen. listbox_fuellen sollte also eine Methode von GUI sein, womit Zeugs vollständig verschwindet.
superthorsten1
User
Beiträge: 6
Registriert: Mittwoch 16. November 2016, 20:08

@Sirius3: Danke dir. Ich sollte alles in eine Klasse machen, das ist wohl richtig, dass das nicht elegant ist. Es ging aber ein bisschen ums Verständnis, nicht darum ein Projekt zu optimieren. Du hast mir aber bezüglich des Verständisses weiter geholfen.
BlackJack

@superthorsten1: Ich würde eine sinnvolle Aufteilung in Klassen nicht als Optimierung ansehen. Insbesondere bei Klassen die semantisch gar keine Klassen sind sollte man eine gute Erklärung haben warum das kein *Fehler* ist.

Anmerkungen zum Code: Widgets sollten sich nicht selbst anordnen. Damit nimmt man dem Aufrufer die Möglichkeit solche Widgets beliebig zu verwenden.

Du hast kein explizites Tk-Objekt erstellt. Das ist ein bisschen magisch.

`appStart()` weicht in der Schreibweise von den üblichen Konventionen ab, die ansonsten in dem Quelltext ja (fast) befolgt werden.

`create_widgets()` würde ich nicht aus der `__init__()` herausziehen und die Schaltfläche muss kein Attribut der Klasse sein.

Kryptische Namenszusätze sind keine gute Idee `b_start` sollte besser `start_button` heissen, dann weiss man gleich was der Name bedeutet und muss nicht rätseln was das `b_*` bedeuten mag.
Antworten