bei größeren Programmen versuche ich, Berechnungen und GUI nach dem "Model-View-Controller"-Modell zu trennen. Da ich das ja nirgendwo in einer (Hoch-) Schule gelernt habe, wollte ich mal fragen, ob "man das so macht" oder doch lieber anders.
Also hier erstmal mein "Skeleton", das ich dann jeweils ausbaue, in vier Dateien:
1. "main.py":
Code: Alles auswählen
#!/usr/bin/env python
#-*- coding: iso-8859-1 -*-
import os
import model
import view
class Controller:
def __init__(self):
self.osname = os.name
self.model = model.Model(self)
self.view = view.View(self, self.model)
def run(self):
self.view.showMain()
def quit(self):
self.view.mw.destroy()
if __name__ == "__main__":
application = Controller()
application.run()
Code: Alles auswählen
#!/usr/bin/env python
#-*- coding: iso-8859-1 -*-
import data
class Model:
def __init__(self, controller):
self.controller = controller
self.data = data.ModelData()
Code: Alles auswählen
#!/usr/bin/env python
#-*- coding: iso-8859-1 -*-
import Tkinter as tk
import tkFileDialog
import ScrolledText
import data
class View:
def __init__(self, controller, model):
self.controller = controller
self.model = model
self.resolution = (1024, 768)
self.data = data.ViewData()
self.fonts = self.data.getFonts(self.controller.osname)
def showMain(self):
self.mw = tk.Tk()
self.mw.title("Title")
self.mw.geometry(self.getGeometry( (66, 60) ))
self.mw.option_add("*font", self.fonts["app"])
self.mw.bind(sequence = "<Control-q>", func = lambda e: self.controller.quit())
self.lab = tk.Label(self.mw,
text = "Hallo")
self.lab.pack()
self.fr1 = tk.Frame(self.mw)
self.fr1.pack()
self.btnexit = tk.Button(self.fr1,
text = "Exit",
command = self.controller.quit)
self.btnexit.pack()
# self.mw.after(2000, self.showWinsize)
self.mw.mainloop()
def showWinsize(self):
print self.mw.winfo_width()
print self.mw.winfo_height()
def getGeometry(self, winsize):
x = (self.resolution[0] - winsize[0]) // 2
y = (self.resolution[1] - winsize[1]) // 2
if x < 0:
x = 0
if y < 0:
y = 0
return "+" + str(x) + "+" + str(y)
Code: Alles auswählen
#!/usr/bin/env python
#-*- coding: iso-8859-1 -*-
class ViewData:
def getFonts(self, osname):
fonts = {"posix" : {"app" : '"Suse Sans" 16',
"small" : '"Suse Sans" 12',
"text" : '"Courier" 20' },
"nt" : {"app" : 'Arial 10',
"small" : 'Arial 8',
"text" : '"courier new" 10' }}
return fonts[osname]
class ModelData:
def __init__(self):
pass
Sondern: Das, was zu berechnen ist, fasse ich meist in weiteren Unterklassen von "Model" zusammen und gebe jeweils "Model" der __init__-Funktion der Unterklasse mit. Das heißt, "Model" ist dann der Unterklasse bekannt. Da "Model" auch "Controller" kennt (und "Controller" "View") können Daten aus den Unterklassen über "Model" und "Controller" auch an "View" weitergeleitet werden (und umgekehrt).
Ein Problem ist, ich bin immer versucht, aus der Unterklasse auf diesem Weg direkt auf "View" zuzugreifen.
Und ich bin ebenso versucht, aus "View" heraus, direkt Daten in "Model" oder den Unterklassen zu manipulieren.
Ist das ok, oder soll man immer alles stur über Funktionen in "Controller" und zusätzlich der jeweiligen manipulierten Klasse abwickeln (das wird dann aber manchmal ziemlich aufwendig und lang)?
Darf also auch eine Instanz direkt Werte in einer anderen Instanz verändern oder soll man das vermeiden?
Anders gefragt: Wenn man ein Objekt "flasche" und ein Objekt "person" hätte, dürfte
Code: Alles auswählen
person.trinkt(flasche)
Code: Alles auswählen
flasche.istvoll = False
Soweit erstmal. Bin diesmal echt auf eure Antworten gespannt ...
Gruß