Mein erstes Programm:"Verbrauch Optimierung"

Fragen zu Tkinter.
Antworten
Psijic
User
Beiträge: 5
Registriert: Dienstag 16. September 2014, 07:55
Wohnort: Gotha

Hallo alle miteinander,
ich bin der neue und Poste jetzt öfters. :)
Im voraus schoneinmal vielen dank an die Regulars hier in diesem Forum. Durch eure guten Tutorials und Hilfestellungen ist mir der Anfang in der Python Programmierung sehr viel leichter gefallen. :D
Nachdem ich so viel Wissen von euch abgeschöpft habe (und das ohne euch zu fragen o.O) und im sinne der Open-Source-Philosophie will jetzt auch mal mein erstes Programm veröffentlichen und euch gleich dazu bitten mir eventuelle verbesserungen vorzuschlagen.
Das wichtigste zum Programm:
Es soll eine Art verschnitt Optimierung werden mit der ich eventuel material einsparen kann.Also wie wir es früher im Bastelunterricht machen mussten , die gröst mögliche Kartonfläche ausnutzen und so wenig wie möglich wegwerfen . In meinem Fall ist es kein Karton sondern Rohre . 8)
Der größte Teil des Code's läuft , hatt aber noch so ein Paar macken (z.b Reste von bereits geschnittenen Rohren noch weiter zu verwerten).

Code: Alles auswählen

import tkinter as tk
import copy



class MyApp(tk.Frame):
    

    def __init__(self,root):
        self.myFrame=tk.Frame.__init__(self,root)
        self.HauptMenuBar(root)
        self.auto_resize(root)
        self.container(self)
        
    def HauptMenuBar(self,root):
        
        menuBar = tk.Menu(root)
        root.config(menu=menuBar)
        menuFile = tk.Menu(menuBar, tearoff = False)
        menuFile.add_command(label='Oeffnen')
        menuFile.add_separator()
        menuFile.add_command(label='Schliesen',command=self.schliesen)
        menuBar.add_cascade(label='Datei',menu=menuFile)
        #Menu2
        menuFile2 = tk.Menu(root, tearoff = False)
        menuFile2.add_command(label='Schnelle Hilfe')
        menuFile2.add_command(label='Version',command=self.Version)
        menuFile2.add_command(label='Impresum')
        menuBar.add_cascade(label='Hilfe',menu=menuFile2)
        #Menu3
        menuFile3 = tk.Menu(root,tearoff = False)
        menuFile3.add_command(label='Aufloesung')
        menuBar.add_cascade(label='Einstellungen',menu=menuFile3)
        
    def container (self,root):
        self.auftragsposition = list()
        self.myList = list()
        spinlist = list ()  
        self.merker_dict={} 
        for i in range (0,241,1):
            i = tk.StringVar()
            i.set(0)
            self.myList.append(i)
        
        v1 = tk.IntVar()
        self.v = v1
        # Handels Laengen bestimmen
        tk.Radiobutton(self.myFrame,text='Rohrlaenge : 6500mm',variable=v1,value=6500).grid(row=0,column=0,padx=5,pady=2,sticky=tk.W+tk.N)
        tk.Radiobutton(self.myFrame,text='Rohrlaenge : 6000mm',variable=v1,value=6000).grid(row=1,column=0,padx=5,pady=2,sticky=tk.W+tk.N)
        tk.Radiobutton(self.myFrame,text='Rohrlaenge : 7000mm',variable=v1,value=7000).grid(row=2,column=0,padx=5,pady=2,sticky=tk.W+tk.N)
        tk.Radiobutton(self.myFrame,text='Rohrlaenge : 8000mm',variable=v1,value=8000).grid(row=3,column=0,padx=5,pady=2,sticky=tk.W+tk.N)
        
        # Spinnbox fuer die Einspannlaenge
        tk.Label(self.myFrame,text='Einspannlaengen in mm :').grid ( row=4 ,column=0,sticky=tk.N+tk.W,padx=5,pady=2)
        self.spinbox1 = self.spinbox = tk.Spinbox(self.myFrame,width=20)
        for i in range (20,110,10):
            spinlist.append(i) 
        self.spinbox1['values'] = spinlist   
        self.spinbox1.grid(row=5,column=0,pady=2,sticky = tk.N+tk.W,padx=5)
        
        #Entry fuer Anzahl der Auftrags Position
        tk.Label(text='Auftragspositions Nummer : ').grid(row=8,column=0,sticky=tk.N+tk.W,padx=5,pady=2)
        self.entry_anzahl_auftragsposition=tk.Entry(self.myFrame,width=30)
        self.entry_anzahl_auftragsposition['textvariable'] = self.myList[1]
        self.entry_anzahl_auftragsposition.grid(row = 9 , column=0,padx=5,sticky=tk.W+tk.N,pady=2)
        tk.Button(self.myFrame,text='Uebernehmen',command=self.entrys).grid(row=10,column=0,sticky=tk.N+tk.S+tk.W+tk.E,padx=5,pady=2) 
        
    def entrys (self):
        mystring_anzahl= 'Rohr_Anzahl_'
        mystring_laenge='Rohr_Laenge_'
        myint = 0
        root1 = tk.Tk()
        counter = 0
        counter1=2
        counter2=1
        counter3 = 1
        counter4 = 1
        counter5= 1
        index = 0
        self.auftragsposition = int(self.entry_anzahl_auftragsposition.get())+1
        tk.Button(root1,text='Ich bin ein Test o.O',command=self.Auswertung).grid(row=1,column=6,sticky=tk.N+tk.S+tk.W+tk.E,padx=5,pady=2) 
        
        for index in range (1,40,1):
            
            tk.Grid.rowconfigure(root1,index,weight=1)
            tk.Grid.columnconfigure(root1,index,weight=1)
            index = index + 1
            
        for row in range(1,self.auftragsposition,1):
            counter += 1
            counter2+=1
            counter5 += 1
            
            if row <= 20 :
                myint = myint +1
                mystring_laenge +=str(myint)
                mystring_anzahl += str(myint)
                tk.Label(root1,text=str(counter)+'.',anchor=tk.W).grid(row=counter2,column=0,sticky=tk.W+tk.N,padx=3,pady=2)
                tk.Label(root1,text=str(counter)+'.',anchor=tk.W).grid(row=counter2,column=1,sticky=tk.W+tk.N,padx=3,pady=2)
                self.entry_anzahl = tk.Entry(root1,width=6)
                self.entry_anzahl['textvariable'] = self.myList[counter5]
                self.entry_anzahl.grid(row = counter2 , column=0,sticky=tk.E+tk.N,pady=2)
                self.merker_dict[mystring_anzahl]=self.entry_anzahl
                counter5 +=1
                self.entry_laenge=tk.Entry(root1,width=6)
                self.entry_laenge['textvariable'] = self.myList[counter5]
                self.entry_laenge.grid(row = counter2 , column=1,sticky=tk.E+tk.N,pady=2)
                self.merker_dict[mystring_laenge]=self.entry_laenge
                #self.entry_anzahl1=tk.Entry(root1,width=6).grid(row = counter2 , column=1,sticky=tk.E+tk.N,pady=2)
                #print(mystring)
                mystring_anzahl='Rohr_Anzahl_'
                mystring_laenge = 'Rohr_Laenge_'
                
                if counter == 1 :
                    tk.Label(root1,bg='Khaki',relief=tk.SOLID,text=' Nr.   Anzahl ',anchor=tk.W).grid(row=1,column=0,sticky=tk.W+tk.N+tk.E+tk.S,pady=2,padx=2)
                    tk.Label(root1,bg='Khaki',relief=tk.SOLID,text=' Nr.   Laenge ',anchor=tk.W).grid(row=1,column=1,sticky=tk.W+tk.N+tk.E+tk.S,pady=2,padx=2)
                else:
                    pass
                    
            elif row >= 21 and row < 41  :
                myint = myint +1
                mystring_laenge +=str(myint)
                mystring_anzahl += str(myint)
                counter3 += 1
                tk.Label(root1,text=str(counter)+'.',anchor=tk.W).grid(row=counter3,column=2,sticky=tk.W+tk.N,padx=3,pady=2)
                tk.Label(root1,text=str(counter)+'.',anchor=tk.W).grid(row=counter3,column=3,sticky=tk.W+tk.N,padx=3,pady=2)
                self.entry_anzahl=tk.Entry(root1,width=6)
                self.entry_anzahl['textvariable'] = self.myList[counter5]
                self.entry_anzahl.grid(row = counter3 , column=2,sticky=tk.E+tk.N,pady=2)
                self.merker_dict[mystring_anzahl]=self.entry_anzahl
                counter5 +=1
                self.entry_laenge=tk.Entry(root1,width=6)
                self.entry_laenge['textvariable'] = self.myList[counter5]
                self.entry_laenge.grid(row = counter3 , column=3,sticky=tk.E+tk.N,pady=2)
                self.merker_dict[mystring_laenge]=self.entry_laenge
                mystring_anzahl='Rohr_Anzahl_'
                mystring_laenge = 'Rohr_Laenge_'
                if counter == 21 :
                    tk.Label(root1,bg='Khaki',relief=tk.SOLID,text=' Nr.   Anzahl ',anchor=tk.W).grid(row=1,column=2,sticky=tk.W+tk.N+tk.E+tk.S,pady=2,padx=2)
                    tk.Label(root1,bg='Khaki',relief=tk.SOLID,text=' Nr.   Laenge ',anchor=tk.W).grid(row=1,column=3,sticky=tk.W+tk.N+tk.E+tk.S,pady=2,padx=2)
                else:
                    pass
                    
            elif row >= 41 and row < 61  :
                myint = myint +1
                mystring_laenge +=str(myint)
                mystring_anzahl += str(myint)
                counter4 += 1
                tk.Label(root1,text=str(counter)+'.',anchor=tk.W).grid(row=counter4,column=4,sticky=tk.W+tk.N,padx=3,pady=2)
                tk.Label(root1,text=str(counter)+'.',anchor=tk.W).grid(row=counter4,column=5,sticky=tk.W+tk.N,padx=3,pady=2) 
                self.entry_anzahl=tk.Entry(root1,width=6)
                self.entry_anzahl['textvariable'] = self.myList[counter5]
                self.entry_anzahl.grid(row = counter4 , column=4,sticky=tk.E+tk.N,pady=2)
                self.merker_dict[mystring_anzahl]=self.entry_anzahl 
                counter5 += 1
                self.entry_laenge=tk.Entry(root1,width=6)
                self.entry_laenge['textvariable'] = self.myList[counter5]
                self.entry_laenge.grid(row = counter4 , column=5,sticky=tk.E+tk.N,pady=2)
                self.merker_dict[mystring_laenge]=self.entry_laenge
                mystring_anzahl='Rohr_Anzahl_'
                mystring_laenge = 'Rohr_Laenge_'
                if counter == 41 :
                    tk.Label(root1,bg='Khaki',relief=tk.SOLID,text=' Nr.   Anzahl ',anchor=tk.W).grid(row=1,column=4,sticky=tk.W+tk.N+tk.E+tk.S,pady=2,padx=2)
                    tk.Label(root1,bg='Khaki',relief=tk.SOLID,text=' Nr.   Laenge ',anchor=tk.W).grid(row=1,column=5,sticky=tk.W+tk.N+tk.E+tk.S,pady=2,padx=2)
                else:
                    pass
            
            elif row == 61 :
                 break
        
        counter = 0
        counter2=6    
        
        
        root1.mainloop()    
    def Hilfe(self):
        print(help(tk.Label))

    def Auswertung(self):
        merker_dict = {}
        fertige_Rohre_dict = {}
        anzahl_haendler_rohre = 0
        rest_rohre = list()
        fertige_Rohre_liste=list()
        rest_gesamt = {}
        switch = False
        fertige_Rohre = 0
        rohr='Rohr_'
        schwund = 5
        mystring_anzahl= 'Rohr_Anzahl_'
        mystring_laenge='Rohr_Laenge_'
        arbeitsdurchgang='Arbeitsdurchgang_'
        fertiges_Rohr ='Rohr_'
        myint=0
        myint1=0
        myint_letzter=0
        theorethische_Rohranzahl = 0
       # try:
            
        for val in range (1,self.auftragsposition,1):
            myint = myint +1
            mystring_laenge +=str(myint)
            mystring_anzahl += str(myint)
            var_anzahl = self.merker_dict[mystring_anzahl]
            merker_dict[mystring_anzahl] =int(var_anzahl.get())
            var_laenge = self.merker_dict[mystring_laenge]
            merker_dict[mystring_laenge]=int(var_laenge.get())
            theorethische_Rohranzahl = theorethische_Rohranzahl + (merker_dict[mystring_anzahl]*merker_dict[mystring_laenge])
            mystring_anzahl= 'Rohr_Anzahl_'
            mystring_laenge='Rohr_Laenge_'
            fertiges_Rohr='Rohr_'
        
            
        myint=0         
        val=0
            
        # Hier werden die Radiobuttons ausgeweretet
        if self.v.get() == 6000 :
            haendler_laenge = float(6000)   
        elif self.v.get() == 6500 :
            haendler_laenge = float(6500) 
        elif self.v.get() == 7000 :
            haendler_laenge = float(7000) 
        elif self.v.get() == 8000:
            haendler_laenge = float(8000) 
            
        bearbeitungslaenge = haendler_laenge - ((float(self.spinbox.get()))+ ((float(self.spinbox.get()))*(schwund/100)))
        theorethische_Rohranzahl = theorethische_Rohranzahl/haendler_laenge    
        
        for laenge in merker_dict.values():
            if laenge > haendler_laenge:
                print('FEHLER : Das Rohr mit der Laenge ' + str(laenge) + ' ist groeser als das Haendlerrohr')
                ok = False
                break
            else:
                ok = True
        myint_letzter = self.auftragsposition - 1
        
        for val in range(1,self.auftragsposition-1,1):
            
            fertige_Rohre=0
            myint = myint +1
            mystring_laenge +=str(myint)
            mystring_anzahl += str(myint)
            arbeitsdurchgang +=str(myint)
            fertiges_Rohr +=str(myint)       
            jolo = True
            fertige_Rohre_dict.setdefault(fertiges_Rohr)  
            if fertige_Rohre_dict[fertiges_Rohr] == None:
                fertige_Rohre_dict[fertiges_Rohr] = 0
            else:
                pass    
            while merker_dict[mystring_anzahl] >= 0 and ok is True   :#Rohr (x) wird abgefragt auf laenge und anzahl.
                if jolo != True:
                    mystring_anzahl='Rohr_Anzahl_'
                    mystring_laenge='Rohr_Laenge_'
                    fertiges_Rohr='Rohr_'
                    arbeitsdurchgang='Arbeitsdurchgang_'
                    break
                elif bearbeitungslaenge > merker_dict[mystring_laenge] and merker_dict[mystring_anzahl]>0 and merker_dict[mystring_laenge] > 0 :
                    
                    bearbeitungslaenge = bearbeitungslaenge - merker_dict[mystring_laenge] 
                    
                    fertige_Rohre_dict[fertiges_Rohr] += 1
                    merker_dict[mystring_anzahl] = merker_dict[mystring_anzahl] - 1
                
                elif bearbeitungslaenge <= merker_dict[mystring_laenge] and merker_dict[mystring_anzahl]>0:#Ruecksetzten der Haendlerlaenge sobald Rohr(x) zu klein wird
                    anzahl_haendler_rohre = anzahl_haendler_rohre + 1
                    rest_rohre.append(bearbeitungslaenge)                    
                    bearbeitungslaenge = haendler_laenge - ((float(self.spinbox.get())) + ((float(self.spinbox.get()))*(schwund/100)))
                    
                elif merker_dict[mystring_anzahl] == 0 and switch is not True :#Nach bearbeitung des letzten rohres wird ein neues haendlerrohr genommen und der Rest in die reste liste gelegt
                 
                    rest = bearbeitungslaenge 
                    switch = True
                    anzahl_haendler_rohre = anzahl_haendler_rohre+1
                    rest_rohre.append(rest)
                    
                    bearbeitungslaenge = haendler_laenge - ((float(self.spinbox.get())) + ((float(self.spinbox.get()))*(schwund/100)))
                    rest = 0
                    
                    
                elif merker_dict[mystring_anzahl] == 0 and switch is  True :
                    
                    mystring_anzahl_schluss= 'Rohr_Anzahl_'
                    mystring_laenge_schluss='Rohr_Laenge_'
                    fertiges_Rohr_schluss ='Rohr_'
                    fertige_Rohre = 0
                    mystring_anzahl_schluss+=str(myint_letzter)
                    mystring_laenge_schluss+=str(myint_letzter)
                    fertiges_Rohr_schluss+=str(myint_letzter)                  
                    if merker_dict[mystring_anzahl_schluss]>0:
                        pass
                    else:
                        mystring_anzahl_schluss= 'Rohr_Anzahl_'
                        mystring_laenge_schluss='Rohr_Laenge_'
                        fertiges_Rohr_schluss ='Rohr_'
                        myint_letzter-=1
                        mystring_anzahl_schluss+=str(myint_letzter)
                        mystring_laenge_schluss+=str(myint_letzter)
                        fertiges_Rohr_schluss+=str(myint_letzter)  
                        
                    fertige_Rohre_dict.setdefault(fertiges_Rohr_schluss)  
                    if fertige_Rohre_dict[fertiges_Rohr_schluss] == None:
                        fertige_Rohre_dict[fertiges_Rohr_schluss] = 0
                    else:
                        pass    
                      
                    while max(rest_rohre) >= merker_dict[mystring_laenge_schluss] or max(rest_rohre) < merker_dict[mystring_laenge_schluss] and merker_dict[mystring_anzahl_schluss] >= 0 :
                        
    
                        if  max(rest_rohre) >= merker_dict[mystring_laenge_schluss] and merker_dict[mystring_anzahl_schluss] > 0:                                   
                            rest_rohre.append (int(max(rest_rohre)) - merker_dict[mystring_laenge_schluss])
                            rest_rohre.remove(max(rest_rohre))
                            merker_dict[mystring_anzahl_schluss]=merker_dict[mystring_anzahl_schluss] - 1   
                            fertige_Rohre = 1 +fertige_Rohre_dict[fertiges_Rohr_schluss]
                            fertige_Rohre_dict[fertiges_Rohr_schluss] = fertige_Rohre
                        
                        elif max(rest_rohre)<merker_dict[mystring_laenge_schluss] or merker_dict[mystring_anzahl_schluss] == 0 :
                            switch = False
                            rest_gesamt[arbeitsdurchgang]=copy.deepcopy(rest_rohre)
                            rest_rohre.clear()
                            jolo=False
                            
                            break
        print(merker_dict)
        print(rest_gesamt)
        print(fertige_Rohre_dict)
        print(anzahl_haendler_rohre) 
        print(theorethische_Rohranzahl)       
        
                   
    def Version (self):
        print('aktuelle Version : Alpha 0.6')   
    def oeffnen (self,master=None):
        pass
                     
    def schliesen(self):
        MyApp.quit(self)
        
    def Berechnen(self):
        pass        
      
    def auto_resize(self,root):
        index = 0
        for index in range (0,10,1):
            
            tk.Grid.rowconfigure(root,index,weight=1)
            tk.Grid.columnconfigure(root,index,weight=1)
            
            index = index + 1
    
def main():
    root = tk.Tk()
    root.title('*****')
    
   
    app = MyApp(root)
    root.mainloop()
   
if __name__ =="__main__":
    main()
Bitte hängt euch nicht gleich auf wenn ihr das seht , das ist mein erster versuch was anständiges zu programmieren.
LG Psijic
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Hui... also erst einmal solltest Du Dich noch stärker an PEP8 halten; maximal 80 Zeichen pro Zeile! Zudem sind Deine Methodennamen auch eher C#-Style als Python.

Die Methode ``Auswertung`` ist definitiv zu lang und macht zu viel! Die solltest Du irgend wie sinnvoll unterteilen.

Ich habe mir das Programm an sich nicht angeguckt, aber so weit ich das überblickt habe, fehlt eine klare Trennung zwischen GUI und Domänenlogik (z.B. ``Auswertung``).
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Schorlem
User
Beiträge: 40
Registriert: Dienstag 3. Juni 2014, 16:37

'n paar Anmerkungen:

Statt ständig "tearoff = False" zu schreiben, nehme ich lieber einmal

Code: Alles auswählen

self.parent.option_add('*tearOff', 0)
Ist zwar nicht unbedingt nötig und auch eine Zeile mehr, mMn. aber eleganter.

Statt den ganzen "tk.N+tk.W+tk.O+tk.S" schreibe ich meist einfach ' "nwes" ' (als String). Damit werden allerdings nicht die Tkinter-Konstanten verwendet.

Die ganzen "padx"- und "pady"-Parameter können durch einmaliges Übergeben dieser bei Erstellung des Frames direkt gesetzt werden.

Bei einigen Widgets, beispielsweise deinen Radiobuttons, bietet sich die Erstellung dieser in Schleifen an.

Von Zeile 95 bis Zeile 167 stehen dreimal fast genau dieselben Codeblöcke im Programm.

Du solltest die "Tk"-Instanz deinem Objekt als Attribut hinzufügen (oder vielleicht auch davon erben). Damit kannst du bspw. in der "schliessen"-Methode direkt darauf zugreifen, ohne es als Parameter übergeben zu müssen.

Wie du vielleicht selbst gemerkt hast, schließt die "schliessen"-Methode das Fenster nicht. Das liegt daran, dass du die Methode nicht von "root" aufruftst, sondern von deinem Frame. Allerdings würde das noch nicht das Fenster schließen, dazu brauchst du "destroy()".

In den Variablennamen sollte der Typ nicht enthalten sein, also kein "merker_dict" oder "fertige_Rohre_liste".

Einige Variablen benutzt du nicht einmal, was wahrscheinlich auch mit der Unübersichtlichkeit zusammenhängt: "counter", "counter1", "index" und "counter2" werden nicht benutzt.

In der "range"-Funktion ist es obsolet, "0" als Start und "1" als Schrittweite anzugeben.

Ansonsten, wie Hyperion bereits gesagt hat, PEP8 durchlesen, da vor allem die Namensgebung und Leerzeichensetzung inkonsistent sind.
Diese Nachricht wurde maschinell erstellt und ist daher ohne Unterschrift gültig.
BlackJack

@Psijic: Ja, also mir ist auch `Auswertung()` als erstes aufgefallen. Das versteht doch kein mensch was da passiert. :-) Da ich's nicht verstehen weiss ich nicht ob's gerechtfertigt ist das zu sagen, aber Listen mit `remove()` und `deepcopy()` sieht komisch aus. ``rest_rohre.clear()`` wird nicht funktionieren — Listen haben solch eine Methode nicht. An der Stelle hätte ich auch eher eine Zuweisung einer leeren Liste erwartet.

Konkrete Datentypen in Namen wurde ja schon erwähnt. Unnütze Präfixe wie `my` oder das Nummerieren von Namen sollte man auch sein lassen. `myint` und `myint1` zum Beispiel: Das verrät dem Leser rein gar nichts über die *Bedeutung* dieser Werte.

Über die erste Schleife hinaus habe ich mir das dann nicht weiter angeschaut, weil die dermassen unsinnig formuliert ist, das ich mir den Rest nicht antun wollte. Die Werte beziehungsweise Schlüssel die dort in `merker_dict` lassen auch Böses ahnen, nämlich das dort durchnummerierte Namen als Schlüssel für Werte verwendet werden die eigentlich zusammen in einen Datensatz und dann in eine Liste gehören.
Psijic
User
Beiträge: 5
Registriert: Dienstag 16. September 2014, 07:55
Wohnort: Gotha

Guten Morgen,
erstmal danke für die raschen Antworten von euch.
@Hyperion :
Meinst du mit klarer trennung das ich die domänen logik und GUI jeweils in einem eigen modul laufen lassen sollte ?
PeP8 werde ich mir heute noch durchlesen.

@Schorlem :
Die "schliesen" Methode greift auf keine tkinter methode zurück sondern soll nur die Klasse "myApp" beenden. Da "myApp" nichts mit tkinter zu tun hatt gibt es ".destroy()" auch nicht. Den tipp mit den Radiobuttons werde ich gleich umsetzen ,da kann ich gleich wieder ein paar zeilen sparen :D.
Der Range wert in den for schleifen muss 1 sein weil sonst die schleife bei 0 beginnt aber ich will das die ab 1 losläuft.
Schorlem hat geschrieben:Einige Variablen benutzt du nicht einmal, was wahrscheinlich auch mit der Unübersichtlichkeit zusammenhängt: "counter", "counter1", "index" und "counter2" werden nicht benutzt.
Ähm doch die werden alle zwischen Zeile 80 bis 167 benutzt . Aber ihr habt recht mit der unübersichtlichkeit,da muss ich noch was dran machen.

@BlackJack:
BlackJack hat geschrieben: ``rest_rohre.clear()`` wird nicht funktionieren — Listen haben solch eine Methode nicht. An der Stelle hätte ich auch eher eine Zuweisung einer leeren Liste erwartet.
Doch die Methode funktioniert auch bei Listen.Kann es sein das dass bei Python 2.x noch nicht funktionierte ? Weil ich mit Python 3.x arbeite.

Code: Alles auswählen

liste = [1,2,3,4,5,6,7,8,9,10]
print(liste)
liste.clear()
print(liste)
Zu dem ``merker_dict`` war meine idee das je nachdem wie viele positionen ich habe automatisch dazu die keys generiert werden ohne sie vorher fest zu speichern .Sonst müsste ich ja in das ``merker_dict`` mit maximal 120 keys reinschreiben. :shock:
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Psijic hat geschrieben: @Hyperion :
Meinst du mit klarer trennung das ich die domänen logik und GUI jeweils in einem eigen modul laufen lassen sollte ?
Nee, das *kann* eine Option sein, aber eine Trennung kannst Du auch schon in einem Modul erreichen. Eine GUI sollte keinen Code enthalten, der Domänenlogik abbildet. Deine "Auswertung" ist doch vermutlich nichts, was eine GUI benötigt bzw. ist etwas, das man mit den entsprechenden Parametern auch vollkommen separat aufrufen könnte.

Es ist nicht leicht zu erklären, aber betrachte Deine GUI als etwas, was wirklich nur das Aufrufen von spezieller Funktionalität erleichtert, die Du auch ohne GUI durchführen könntest.

Lies Dir doch mal diesen Thread durch. Da gebe ich und BlackJack ein simples Beispiel dafür :-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Psijic
User
Beiträge: 5
Registriert: Dienstag 16. September 2014, 07:55
Wohnort: Gotha

Ok danke Hyperion jetzt hatt es ``klick`` gemacht.
Ich konnte mit deinem tipp erstmal nichts anfangen, nachdem ich deinen thread durchgelesen habe ist aber einiges klarer geworden. Da werd ich wohl erstmal meine skills in der oop verbessern müssen bevor ich mit meinem projekt weitermache. so wie ich das jetzt verstanden habe ist meine methode ``auswertung`` ohne gui totaler quatsch und funktioniert keinen meter weit -.-' . Wäre es da jetzt besser ``auswertung`` als eigenständige funktion auserhalb der klasse laufen zu lassen ? Oder besser ``auswertung`` als child klasse vom parent ``class myAPP`` mit vererbten parametern zu benutzen?
LG
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Wenn du von myApp erbst und darin die Logik implementierst, dann kann diese wieder nur mit der GUI laufen. Daher ist das keine Option. Je noch Komplexität bieten sich für die Logik eine eigene Klasse an oder einfach nur Funktionen. Das hängt davon ab, ob du Zustand hast oder nicht.
Das Leben ist wie ein Tennisball.
BlackJack

@Psijic: Natürlich hat `MyApp` etwas mit Tkinter zu tun und hat auch eine `destroy()`-Methode. Die Klasse erbt doch von `Tkinter.Frame`. In der `schliessen()`-Methode solltest Du also nicht über das Klassenobjekt gehen, sondern direkt die Methoden auf sich selbst aufrufen.

Es hat niemand gesagt Du sollst die 1 als Startwert weglassen. Sondern die 0 als Start oder die 1 als *Schrittweite* sind nicht nötig.

In `entrys()` wird `counter1` nicht benutzt. Also tatsächlich nicht einmal verwendet nachdem der initiale Wert zugewiesen wurde.

`counter` wird verwendet, sollte aber nicht verwendet werden. Der hat in der Methode immer den selben Wert wie die Schleifenvariable `row`. Die hat wenigstens einen vernünftigen Namen, allerdings weiss ich nicht ob der sinnvoll ist, denn offensichtlich wird an dem `row`-Wert auch festgemacht in welcher *Spalte* Widgets landen, was vielleicht ein wenig verwirrend ist. Die `counter2`, `counter3`, und `counter4`, sowie `counter5` könnte man auch alle aus dem `row`-Wert ableiten. Die sollte man deshalb nicht unabhängig davon manuell verwalten.

Der initial an `index` zugewiesene Wert wird nirgends verwendet, diese Zuweisung kann also entfallen. Und auch das Hochzählen am Ende der Schleife macht keinen Sinn, weil es keinen Effekt hat, da im nächsten Schleifendurchlauf sowieso der nächste Wert aus dem `range`-Objekt zugewiesen wird. Ich verstehe auch nicht so recht was dieses Zuweisen von Gewichten bringen soll. Das macht bei keinem der beiden Gridlayouts wo Du das machst, wirklich Sinn.

In der Methode steckt auch ein dicker Fehler: Es darf immer nur ein `Tk`-Objekt zur gleichen Zeit existieren, sonst kann es zu sehr komischen Verhalten bis hin zu harten Abstürzen kommen. Ein `Tk`-Exemplar repräsentiert *das* Hauptfenster. Zusätzliche Fenster muss man mit `Toplevel` erzeugen.

Die `list.clear()`-Methode gibt es in Python 2 tatsächlich nicht. Mal sehen ob ich mir das merken kann. :-)

Beim `merker_dict` ist nicht die Anzahl der Schlüssel bzw. Einträge das Problem, sondern diese eigenartige Konstruktion überhaupt. Das sieht aus wie eine Vermischung von globalen Variablen, die dynamisch erzeugt und durchnummeriert werden und Werte zu unterschiedlichen Namen mit gleicher angehängter Nummer eigentlich zusammen gehören. Also gleich drei Sachen die Programme unübersichtlich bis unwartbar machen, auf einmal.

Was mich an der ganze Sache auch verwirrt ist das Du hier ein 300+ Zeilenprogramm ablieferst und nicht nur aus dem Code nicht einfach ersichtlich ist was das überhaupt macht. Meine Erfahrung mit der GUI war, dass ich erst mal auf `Uebernehmen` geklickt habe und ein Fenster aufging wo einfach nur eine Schaltfläche mit der Aufschrift 'Ich bin ein Test o.O' drin ist — sonst nichts.

Dann habe ich in 'Auftragspositions Nummer' mal etwas anderes als 0 eingetragen, und beim nächsten Übernehmen war dann ein bisschen mehr in dem Fenster zu sehen. Da ein paar Zahlen eingetragen (ohne wirklich zu wissen was die bedeuten sollen) und auf die Schaltfläche geklickt: ``UnboundLocalError: local variable 'haendler_laenge' referenced before assignment``. Im Quelltext gesucht woran das liegen mag → man muss aus den Optionen im ersten Fenster offenbar eine Rohrlänge auswählen.

Es wäre vielleicht sinnvoll wenn das zweite Fenster gar nicht erst angezeigt wird, wenn die Voraussetzungen das auch benutzen zu können, nicht erfüllt sind.

Nun ja, dann war ich an dem Punkt wo ich das Programm ”benutzen” konnte, und bekam folgendes Ergebnis:

Code: Alles auswählen

{'Rohr_Laenge_2': 4, 'Rohr_Anzahl_1': 0, 'Rohr_Anzahl_2': 0, 'Rohr_Laenge_1': 2}
{'Arbeitsdurchgang_1': [6466]}
{'Rohr_1': 1, 'Rohr_2': 3}
1
0.00215384615385
Was zum Henker soll mir das jetzt sagen?
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

BlackJack hat geschrieben:Was zum Henker soll mir das jetzt sagen?
Ist doch ganz offensichtlich. Du bestellst von den 2-Meter-Rohren 0 Stück und von den 4-Meter-Rohren keins. Rohr 1 kommt dann an die zweite Position, Rohr 2 an die dritte und, wie die Zeile 4 deutlich aussagt, würde noch ein Rohr an Position zwei fehlen, wenn man denn die anderen Rohre häte.

Bei Zeile 5 musste ich auch ein wenig rätseln, ich tippe aber auf eine versteckte Nachricht, denn:

Code: Alles auswählen

>>> 1.0/0.00215384615385
464.2857142848852
>>> 0.00215384615385**0.5
0.04640954808926715
Wer hätte gedacht, dass die ersten drei Ziffern identisch sind? Also schnell eine Suche bei Google nach 464 und was erhält man:
Steamfitters & Plumbers LU 464 :shock: .
Das Leben ist wie ein Tennisball.
Psijic
User
Beiträge: 5
Registriert: Dienstag 16. September 2014, 07:55
Wohnort: Gotha

Wie schonmal vorher gesagt das programm ist bei weitem noch nich fertig.
Der Ablauf sollte so ablaufen das ich in dem ersten fenster die handelslänge des rohr zulieferers auswähle ( siehe die 4 rad.. buttons).
Danach wird eine einspannlänge gewählt zwischen 20 und 100mm.
Das entryfeld ``Auftrags Positionsnummer`` (unglücklich gewählter Name) soll mir angeben wie viele verschiedene Rohre es gibt ( was ich gesehen habe waren in einem auftrag maximal 60 stück). in einer früherren version waren alle entry's im hauptframe zu sehen. aber das hatt mir nicht gefallen... deswegen wird jetzt durch die eingabe definiert wie viele entr's generiert werden sollen . Nach bestätigen der Voraussetzungen soll sich dan das neu frame öffnen mit der voreingestellen anzahl an entry's.
Nachdem wir ja schon festgestellt haben das ``auswertung`` nicht gut durchdacht ist komme ich gleich mal zu dem kryptischen Output.
Die erste Ausgabe zeigt die übrige anzahl und die länge des Rohres an.
Die zweit Ausgabe soll den rest des gelieferten rohrs ausgeben. z.b. Arbeitsdurchgang_1 wurden 3 händlerlängen verarbeitet mit jeweils einem rest von 400 dann steht da halt {'Arbeitsdurchgang_1:[400,400,400]} quasi 3 mal rest von 400
Die dritte Ausgabe ist einfach nur ein Kontrolle ob jetzt auch wirklich Rohr_1 z.b 100mal geschnitten wurde.
Die vierte Ausgabe zeigt an wie viele Rohre ich beim Händler bestellen sollte
Die fünfte Ausgabe gibt die theorethische Rohrlänge an. Das ist das was mir der zulieferrer an rohre liefert was aber meistens zuviel ist (weswegen ich das projekt überhaupt begonnen habe)
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

@Psijic: Bei allem, was Du hier beschrieben hast, sehe ich eine Menge Logik, die man komplett ohne GUI implementieren kann. Die GUI ist dann eher Konfigurations- und Steuerhilfe. (Natürlich kann man auch beides *parallel* entwickeln, aber die Basis muss definitiv sauber funktionieren.) Eine saubere Trennung und damit einhergehend eine saubere Modellierung der benötigten Datenstrukturen und Algorithmen darauf ist bei diesem Unterfangen ein Muss!
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Psijic
User
Beiträge: 5
Registriert: Dienstag 16. September 2014, 07:55
Wohnort: Gotha

Jo das mit der Programm logik ist echt ein großes ding für mich kleinen anfänger . Aber das krieg ich hin, früher oder später ....
Jetzt mal so nebenbei hab vorhin mal n bisschen im off topic forum gewühlt und ein thread zum Buch "Python2 Das umfassende Handbuch" gefunden und darin wird gefragt ob die fortsetzung genauso schwach im OOp bereich ist wie teil 2. Ich kann dazu nur sagen " Ja ist es.... " hab es hier neben mir liegen und ich kapier rein garnichts was die da über OOP sagen....
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Psijic hat geschrieben:Ich kann dazu nur sagen " Ja ist es.... " hab es hier neben mir liegen und ich kapier rein garnichts was die da über OOP sagen....
;-) Wobei man - ohne Dir zu nahe treten zu wollen - daraus nicht uneingeschränkt ableiten kann, wie gut der Teil ist. Sofern dort keine falschen Dinge gelehrt werden, wäre es schon mal gut. Wenn das didaktisch dann schwach ist, ist es sicherlich auch nicht prickelnd, richtet aber wenigstens keinen Schaden an. Und wenn man das dann immer noch nicht leicht versteht, so kann es auch am Lernenden liegen...

Ich würde an Deiner Stelle erst einmal die Anforderungen klar (textuell! evtl. mit Flussdiagrammen o.ä. ergänzt) aufschreiben und daraus versuchen Datenstrukturen (es müssen nicht alles Klassen sein!) zu entwickeln und Funktionen, die diese ver- oder bearbeiten können.

Vergiss dabei zunächst die GUI! (Nutze höchstens Mockups, die Dir helfen, Funktionalität in der Domäne aufzudecken)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Antworten