Mainloop Interrupt

Fragen zu Tkinter.
Antworten
DMD
User
Beiträge: 123
Registriert: Sonntag 17. Mai 2015, 03:34

hey,
ich habe in meinem code:

Code: Alles auswählen

# -*- coding: cp1252 -*-
#!/usr/bin/env python

from Tkinter import *
import tkMessageBox

datetum = [['01.09.2015']]
liste = [[u'15', u'45', 9, 9]]
ueber = [[0]]
istSum = 9
sollSum = 9
ueberSum = 0

try:
    root.destroy()
except:
    pass

rootWin = Tk()
rootWin.title('GUI-VERWALTUNG')
rootWin.geometry('+500+50')

label_0 = Label(rootWin, text=("' UEBERSICHT '"),font=('Arial', 12, 'bold underline'), height=3, width=18, fg="#000000000", justify='left')
label_0.grid(row=0, column=1, columnspan=2)

label_1 = Label(rootWin, height=3,width=18, fg="#000000000", justify='center')
label_1.grid(row=2, column=0)

label_2 = Label(rootWin, height=2,width=18, fg="#000000000", justify='center')
label_2.grid(row=7, column=0)

label_3 = Label(rootWin, height=3,width=18, fg="#000000000", justify='center')
label_3.grid(row=10, column=0)

entries = []
datList = []
dateSum = []

for row, items in enumerate(datetum):
    for column, item in enumerate(items):
        label_4 = Label(rootWin,text=(item),font=('Arial', 9, 'bold'), width=18, relief="raised",bg='#cdc8b1', fg="#000000000", justify='center')
        label_4.grid(row=row+10, column=column)
        ruben = []
        ruben.append(item)
        dateSum.append(item)
        datList.append(ruben)

for row, items in enumerate(liste):
    for column, item in enumerate(items):
        v = StringVar()
        v.set(item)
        en = Entry(rootWin, textvariable = v, width=18, relief="raised",font=('Arial', 9, 'bold'),  bg='#eeeee0', fg="#000000000", justify='center')
        en.grid(row=row+10, column=column+1)
        entries.append(en)

for row, items in enumerate(ueber):
    for column, item in enumerate(items):
        label_5 = Label(rootWin,text=(item),font=('Arial', 9, 'bold'), width=18, relief="raised", bg='#cdc8b1',fg="#000000000", justify='center')
        label_5.grid(row=row+10, column=column+5)

label_6=Label(rootWin, text=('Summe:'), width=18, relief="ridge", font=('Arial', 9, 'bold'), bg='#eecbad', fg="#000000000", justify='center').grid(column=0, row=row+11)
label_7=Label(rootWin, text='---', width=18, relief="ridge",font=('Arial', 9, 'bold'),  bg='#eecbad', fg="#000000000", justify='center').grid(column=1, row=row+11)
label_8=Label(rootWin, text='---', width=18, relief="ridge",font=('Arial', 9, 'bold'),  bg='#eecbad', fg="#000000000", justify='center').grid(column=2, row=row+11)
label_9=Label(rootWin, text=(istSum), width=18, relief="ridge",font=('Arial', 9, 'bold'),  bg='#eecbad', fg="#000000000", justify='center').grid(column=3, row=row+11)
label_10=Label(rootWin, text=(sollSum), width=18, relief="ridge",font=('Arial', 9, 'bold'),  bg='#eecbad', fg="#000000000", justify='center').grid(column=4, row=row+11)
label_11=Label(rootWin, text=(ueberSum), width=18, relief="ridge",font=('Arial', 9, 'bold'),  bg='#eecbad', fg="#000000000", justify='center').grid(column=5, row=row+11)

def aktuellUeber(entries):

    aktueller = []

    for entry in entries:
        aktueller.append(entry.get())
    try:
        for kaunt in aktueller:
           a = float(kaunt)
        print a
    except:
        import Tkinter
        window = Tkinter.Tk()
        window.wm_withdraw()
        window.geometry("1x1+200+200")
        tkMessageBox.showerror(title="GUI-VERWALTUNG",message="EINGABEFEHLER:\n\nBitte gib eine nichtnegativen ganze Zahl als Kontonummer ein!",parent=window)

b_a2 = Button(rootWin, text = ' Aktualisieren ', command=lambda: aktuellUeber(entries))
b_a2.grid(row=4, column=5)

def zurueckTable():
    rootWin.destroy()

b_a3 = Button(rootWin, text = '  Zurueck   ', command = zurueckTable)
b_a3.grid(row=7, column=5)

rootWin.mainloop()
folgendes problem:
wenn man nach dem starten in einem (oder mehreren der label) einen buchstaben eingibt,
zeigt das programm das richtigerweise an, allerdings drückt man dann auf 'zurück' werden nur
die fenster geschlossen, das programm bleibt aber im mainloop!
versteh ich nicht? abhilfe?
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Dein Problem hättest du nicht wenn du beim schreiben des Codes auch nur versuchen würdest ein Minimum an Codequalität zu erreichen. Du hast über 100 Posts da kannst du dich bei diesem Code auch nicht mehr damit Entschuldigen dass du Anfänger bist, da du sicherlich schon aus anderen Threads vertraut bist mit den Problemen die dein Code aufweist.

Versuch mal deinen Code sinnvoll zu strukturieren und lesbar zu gestalten, dann findet man auch solche Probleme leichter oder hat sie erst gar nicht.
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

DasIch hat geschrieben:Du hast über 100 Posts da kannst du dich bei diesem Code auch nicht mehr damit Entschuldigen dass du Anfänger bist, [...]
Wer nach 100 Beiträgen nicht mal das richtige Unterforum für seine Frage findet ... :evil:
BlackJack

Moment, ich verschiebe…
DMD
User
Beiträge: 123
Registriert: Sonntag 17. Mai 2015, 03:34

sorry:

Code: Alles auswählen

# -*- coding: cp1252 -*-
#!/usr/bin/env python

from Tkinter import *
import tkMessageBox

liste = [[u'15', u'45', 9, 9]]
ueber = [[0]]
istSum = 9
sollSum = 9
ueberSum = 0

rootWin = Tk()
rootWin.title('GUI-VERWALTUNG')
rootWin.geometry('+500+50')

def aktuellUeber(entries):

    aktueller = []

    for entry in entries:
        aktueller.append(entry.get())
    try:
        for kaunt in aktueller:
            a = float(kaunt)
            print a
    except:
        import Tkinter
        window = Tkinter.Tk()
        window.wm_withdraw()
        window.geometry("1x1+200+200")
        tkMessageBox.showerror(title="GUI-VERWALTUNG",message="NO INTEGER OR FLOAT!",parent=window)

def backTable():
    rootWin.destroy()

entries = []
for row, items in enumerate(liste):
    for column, item in enumerate(items):
        v = StringVar()
        v.set(item)
        en = Entry(rootWin, textvariable = v, width=18, relief="raised",font=('Arial', 9, 'bold'),  bg='#eeeee0', fg="#000000000", justify='center')
        en.grid(row=row+10, column=column+1)
        entries.append(en)

b_a2 = Button(rootWin, text = ' Aktualisieren ', command=lambda: aktuellUeber(entries))
b_a2.grid(row=4, column=5)

b_a3 = Button(rootWin, text = '  Zurueck   ', command = backTable)
b_a3.grid(row=7, column=5)

rootWin.mainloop()
besser?
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Ich würde sagen, werfe bloss die Zeilen 28 bis 31 raus. was soll denn der Unsinn nochmals tkinter zu importieren und aufzumachen?

Code: Alles auswählen

		import Tkinter
		window = Tkinter.Tk()
		window.wm_withdraw()
		window.geometry("1x1+200+200")
Wahrscheinlich rennst Du da in diesen wm_withdraw hinein und siehst dann das Fenster nicht mehr.
BlackJack

@DMD: Nicht wirklich besser weil immer noch nicht sauber strukturiert, und es gibt auch noch ein paar andere Sachen die sicher schon öfter gesagt wurden, zum Beispiel Namensschreibweisen und Leerzeichensetzung die nicht dem Style Guide for Python Code ensprechen.

Sternchenimport wurde sicher schon erwähnt: Nicht machen, schon gar nicht bei einem Modul wie `Tkinter` welches so verdammt viele Namen enthält.

Auf Modulebene gehören Definitionen von Konstanten, Funktionen, und Klassen. *Keine* Variablen und kein Hauptprogramm und schon gar nicht Hauptprogramm und Definitionen von Funktionen abwechselnd. Unübersichtlicher geht's auf dieser Ebene kaum. Das Hauptprogramm gehört in eine Funktion. Die heisst üblicherweise `main()`.

Namen sollen dem Leser vermitteln was die Werte die an sie gebunden sind im Programm bedeuten. Nicht das es sich um eine Liste handelt, sondern was diese Werte in der Liste für eine Bedeutung haben. Und auch keine Namen mit kryptischen Abkürzungen oder welche die nur eine Abkürzung sind oder gar ein- oder zweibuchstabige Namen. Ausnahmen sind allgemein bekannte Abkürzungen und wenn der Gültigkeitsbereich sehr eingeschränkt ist, beispielsweise in anonymen Funktionen, „list comprehensions“, oder Generatorausdrücken.

Wenn man anfängt Namen zu nummerieren macht man in der Regel etwas falsch und will eigentlich eine Datenstruktur anstelle von einzelnen Namen verwenden. In der Regel ist das eine Liste.

Man sollte keine Ausnahmen behandeln die man nicht sinnvoll behandeln kann, darum ist es fast nie angebracht ein nacktes ``except:`` ohne konkrete Ausnahmen zu verwenden.

Den weiteren Import von `Tkinter` und das zusätzliche verbotene `Tk`-Objekt hat Alfons ja schon erwähnt. Ich würde mal sagen so etwas kommt zustande wenn man irgendwo Sachen abschreibt ohne verstanden zu haben was die eigentlich machen.

Das beschriebene Problem mit der Hauptschleife kann ich nicht nachvollziehen. Ein zerstören des Hauptfensters beendet bei mir auch die Hauptschleife weil am `Tk`-Exemplar der komplette Tcl/Tk-Interpreter hängt. Wobei ich hier die `Widget.quit()`-Methode verwenden würde statt gleich so richtig zerstörerisch zu werden. :-)

Hast Du im tatsächlichen Programm eventuell *noch* ein `Tk`-Exemplar? Weil die „Zurück“-Beschriftung auf der Schaltfläche so klingt als wenn es dort noch mehr GUI gäbe.

Es wäre vielleicht nett dem Benutzer das problematische Eingabefeld a) visuell hervorzuheben, und b) nach dem Fehlerdialog genau dieses Feld für den Benutzer zu aktivieren damit er den Inhalt korrigieren kann.

Ich komme dann auf so etwas:

Code: Alles auswählen

# -*- coding: cp1252 -*-
#!/usr/bin/env python
import Tkinter as tk
import tkMessageBox


APPLICATION_TITLE = 'GUI-VERWALTUNG'
ERROR_COLOR = '#ff8080'


def check_entries(entries):
    for entry in entries:
        content = entry.get()
        try:
            _ = float(content)
        except ValueError:
            old_background = entry['background']
            entry['background'] = ERROR_COLOR
            tkMessageBox.showerror(APPLICATION_TITLE, 'No integer or float!')
            entry['background'] = old_background
            entry.focus()
            break


def main():
    liste = [['15', '45', 9, 9]]
     
    root = tk.Tk()
    root.title(APPLICATION_TITLE)

    tk.Button(
        root, text='Aktualisieren', command=lambda: check_entries(entries)
    ).grid(row=0, column=4)
    tk.Button(root, text=u'Zurück', command=root.destroy).grid(row=1, column=4)

    entries = []
    for row, items in enumerate(liste, 2):
        for column, item in enumerate(items):
            entry = tk.Entry(
                root,
                width=18,
                relief=tk.RAISED,
                font=('Arial', 9, 'bold'),
                background='#eeeee0',
                justify=tk.CENTER,
            )
            entry.insert(0, item)
            entry.grid(row=row, column=column)
            entries.append(entry)
     
    root.mainloop()


if __name__ == '__main__':
    main()
Wobei das hier für dieses kleine Beispiel noch mit Funktionen geht, aber man kommt bei GUI-Programmierung nicht um objektorientierte Programmierung herum wenn das sauber werden/bleiben soll.
DMD
User
Beiträge: 123
Registriert: Sonntag 17. Mai 2015, 03:34

ok, das sind dinge die ich schon lange berücksichtige.
ich hab doch auch schon öfter gepostet, dass ich bei einem problem,
den geposteten code ziemlich schnell versuche zusammen zu schrauben.
in meinem richtigen code habe ich solch schlechten code NICHT.
ich will nur immer möglichst schnell wissen, wo der fehler ist. :)
den fehler hab ich übrigens gefunden.
das liegt natürlich daran, dass bei ansprechen des

Code: Alles auswählen

    
except:
        import Tkinter
        window = Tkinter.Tk()
        window.wm_withdraw()
        window.geometry("1x1+200+200")
        tkMessageBox.showerror(title="GUI-VERWALTUNG",message="NO INTEGER OR FLOAT!",parent=window)
 
das fenster "window" auch bei späterem beenden des programms geöffnet bleibt.
das hab i net gesehen.
danke an euch.
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Der Fehler liegt hier:
DMD hat geschrieben:ich hab doch auch schon öfter gepostet, dass ich bei einem problem,
den geposteten code ziemlich schnell versuche zusammen zu schrauben.
in meinem richtigen code habe ich solch schlechten code NICHT.

ich will nur immer möglichst schnell wissen, wo der fehler ist. :)
Es ist sinnlos Code zu posten von dem du denkst, dass er denselben Fehler hat wie du ihn eigentlich siehst. Warum? Nur wenn du weisst was der eigentliche Fehler ist, kannst du ihn in einem anderen Fall rekonstruieren.
Antworten