Variable mit Label verknüpfen

Fragen zu Tkinter.
Antworten
tobi1324
User
Beiträge: 4
Registriert: Freitag 11. Juni 2010, 23:11

Hallo, ich habe folgendes Problem:
Ich habe ein normales Fenster, in dem ich ein Label platziert habe. Ich möchte aber, dass das Label den Text einer Variablen anzeigt und keinen starren Text. Mein Ansatz sieht folgendermaßen aus:

Code: Alles auswählen

def update():
    v.set(andere_variable)

v=StringVar()
text1=Label(root,textvariable=v)
text1.pack()


#Im verlauf des Programms wird die Variable "andere_variable" geändert.
#Wenn ich dann update() ausführe, sollte das Label seinen Text entsprechend
#der Variable ändern.
Aber leider gibt mir idle eine Fehlermeldung raus.
Kann mir jemand sagen was ich falsch gemacht habe oder wie ich es sonst hinkriegen kann, eine Variable mit einem Label zu verknüpfen?
Viele Grüße
Tobi

PS: Ich bitte um Verzeihung falls ich der 100. bin der dieses Problem hat bzw, falls ich einen ähnlichen Thread übersehen habe :)
Zuletzt geändert von Anonymous am Freitag 11. Juni 2010, 23:46, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Code-Tags gesetzt.
BlackJack

@tobi1324: Welche Fehlermeldung gibt IDLE denn aus?
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Dann zeig doch mal die Fehlermeldung.

Besser ist es aber dein Problem in einer Klasse zu loesen, so hast du jede menge globale Variablen.
tobi1324
User
Beiträge: 4
Registriert: Freitag 11. Juni 2010, 23:11

achso, sorry, habe ich vergessen:

Code: Alles auswählen

Traceback (most recent call last):
  File "/home/tobias/abi_gui.py", line 51, in <module>
    v1 = StringVar()
  File "/usr/lib/python2.6/lib-tk/Tkinter.py", line 254, in __init__
    Variable.__init__(self, master, value, name)
  File "/usr/lib/python2.6/lib-tk/Tkinter.py", line 185, in __init__
    self._tk = master.tk
AttributeError: 'NoneType' object has no attribute 'tk'
würde es helfen wenn ich den ganzen Code mal poste?
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Ja, Code hilft immer. Hast du es auch schon ausserhalb von IDLE ausgefuehrt?
tobi1324
User
Beiträge: 4
Registriert: Freitag 11. Juni 2010, 23:11

ne, ich arbeite im Moment nur mit IDLE. Wie mache ich das denn? Programme ohne GUI/Tkinter führe ich auch direkt in der Konsole(gnome-terminal) aus...
Naja, hier erstmal der Code:
(Bitte nicht schimpfen, ich weiß der ist hässlich, aber das ist halt mein erstes Projekt mit Tkinter und eine der ersten Projekte mit Python überhaupt)

Code: Alles auswählen

#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys
from Tkinter import *
import tkMessageBox
def close():
    root.destroy()
def zeig():
    punkte=float((noten[0]*12)+(noten[1]*12)+(noten[2]*8)+(noten[3]*8)\
                    +(noten[4]*4)+(noten[5]*4)+(noten[6]*4)+(noten[7]*4))
    punkte=round(punkte,1)
    pschnitt=float((punkte/56.0))
    pschnitt=round(pschnitt,2)
    nc=float(((-(1/3.0)*pschnitt)+(17.0/3)))
    nc=round(nc,2)
    #print punkte, pschnitt, nc

    v1.set(punkte)
    v2.set(pschnitt)
    v3.set(nc)
    
def calc():
    noten[0]=float(feld1.get())
    noten[1]=float(feld2.get())
    noten[2]=float(feld3.get())
    noten[3]=float(feld4.get())
    noten[4]=float(feld5.get())
    noten[5]=float(feld6.get())
    noten[6]=float(feld7.get())
    noten[7]=float(feld8.get())
    error=0
    for i in range(0,8):
        if noten[i] < 1:
            tkMessageBox.showerror("Error","Die eingegebene Punktzahl muss \
            mindestens 1 betragen.")
            error=1
        elif noten[i] > 15:
            tkMessageBox.showerror("Error","Die eingegebene Punktzahl darf \
            maximal 15 betragen.")

            error=1
    if error==0:
        zeig()

noten=[" "," "," "," "," "," "," "," "]
nc=0
punkte=" "
pschnitt=" "
abi=" "

v1 = StringVar()
v2 = StringVar()
v3 = StringVar()

root=Tk()
root.title("Abirechner")

frlinks=Frame(root,width=20)
frrechts=Frame(root,width=20)
frunten=Frame(root)
frbot=Frame(root)

ergf1=Frame(frbot)
ergf2=Frame(frbot)
ergf3=Frame(frbot)

erg1=Label(ergf1,textvariable=v1)
erg2=Label(ergf2,textvariable=v2)
erg3=Label(ergf3,textvariable=v3)

ergt1=Label(ergf1,text="Punkte: ")
ergt2=Label(ergf2,text="Punktedurchschnitt: ")
ergt3=Label(ergf3,text="Numerus Clausus (NC): ")

ber=Button(frunten,text="Berechnen",command=calc)
clo=Button(frunten,text="Schließen",command=close)

f1=Frame(frlinks,pady=1)
f2=Frame(frlinks,pady=1)
f3=Frame(frlinks,pady=1)
f4=Frame(frlinks,pady=1)
f5=Frame(frlinks,pady=1)
f6=Frame(frlinks,pady=1)
f7=Frame(frlinks,pady=1)
f8=Frame(frlinks,pady=1)

feld1=Entry(frrechts,width=3)
feld2=Entry(frrechts,width=3)
feld3=Entry(frrechts,width=3)
feld4=Entry(frrechts,width=3)
feld5=Entry(frrechts,width=3)
feld6=Entry(frrechts,width=3)
feld7=Entry(frrechts,width=3)
feld8=Entry(frrechts,width=3)

lab1=Label(f1,text="1. LK (hochgestuft):")
lab2=Label(f2,text="2. LK (hochgestuft):")
lab3=Label(f3,text="3. LK (runtergestuft):")
lab4=Label(f4,text="4. GK (schriftlich):")
lab5=Label(f5,text="5. GK (mündlich):")
lab6=Label(f6,text="6. GK (mündlich):")
lab7=Label(f7,text="7. Fach:")
lab8=Label(f8,text="8. Fach:")

frbot.pack(side=BOTTOM)
frunten.pack(side=BOTTOM)
frrechts.pack(side=RIGHT,fill=Y)
frlinks.pack(side=LEFT,fill=BOTH)

ergf1.pack()
ergf2.pack()
ergf3.pack()

ergt1.pack(side=LEFT)
ergt2.pack(side=LEFT)
ergt3.pack(side=LEFT)
    
erg1.pack(side=LEFT)
erg2.pack(side=LEFT)
erg3.pack(side=LEFT)

f1.pack()
f2.pack()
f3.pack()
f4.pack()
f5.pack()
f6.pack()
f7.pack()
f8.pack()

lab1.pack()
lab2.pack()
lab3.pack()
lab4.pack()
lab5.pack()
lab6.pack()
lab7.pack()
lab8.pack()

feld1.pack()
feld2.pack()
feld3.pack()
feld4.pack()
feld5.pack()
feld6.pack()
feld7.pack()
feld8.pack()

clo.pack(side=RIGHT)
ber.pack(side=RIGHT)


root.mainloop()

Viele Grüße

Tobi
Zuletzt geändert von Anonymous am Samstag 12. Juni 2010, 08:39, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Code-Tags gesetzt.
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Es gibt auch "Python"-Codetags! -> Syntax-Highlighting.

Die Lösung deines Problems ist einfach: Du verwendest StringVar() bevor du eine Instanz von Tk() erzeugt hast. Das funktioniert nicht. Wenn du die drei Zeilen unter die beiden folgenden Zeilen packst, läuft dein Programm.

Was den Code angeht, so solltest du den noch gründlich überarbeiten. Mit dem beliebten Anfänger-Argument "das Programm funktioniert aber" solltest du dich nicht zufrieden geben. Code mit durchnummerierten Bezeichnernamen ist selten eine gute Sache.
tobi1324
User
Beiträge: 4
Registriert: Freitag 11. Juni 2010, 23:11

Cool, es funktioniert, vielen Dank :) (mein erstes selbst geschriebenes Tool :D:D)

ok, wie könnte man den Code denn sinnvoll optimieren?

Viele Grüße

Tobi
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Mit Listen, Dictionaries, Schleifen, Klassen und Funktionen.
Das Leben ist wie ein Tennisball.
BlackJack

Konkret würde ich als ersten Schritt den Sternchenimport durch ``import Tkinter as tk`` ersetzen, mit allen Änderungen die daraus folgen, und sämtlichen Quelltext auf Modulebene in Funktionenen verschwinden lassen. Auf Modulebene sollten möglichst nur Definitionen von Klassen, Funktionen, und Konstanten stehen, und keine Variablen oder Programmlogik.

Als zweites schreien die durchnummerierten Namen nach Listen.

Man könnte sich auch überlegen Programmlogik und GUI voneinander zu trennen.
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hallo tobi1324

Hier eine mögliche Optimierung zum herumspielen:

Code: Alles auswählen

#!/usr/bin/python
# -*- coding: utf-8 -*-

# wuf_ref: label_variable_01_02.py

import Tkinter as tk
import tkMessageBox

def close():
    root.destroy()

def zeig(noten, valuation):

    punkte = (noten[0].get()*12 + noten[1].get()*12 + noten[2].get()*8 +
        noten[3].get()*8 + noten[4].get()*4 + noten[5].get()*4 +
        noten[6].get()*4 + noten[7].get()*4)

    punkte = round(punkte,1)
    pschnitt = float((punkte/56.0))
    pschnitt = round(pschnitt,2)
    nc = float(((-(1/3.0) * pschnitt) + (17.0/3)))
    nc = round(nc,2)
    #print punkte, pschnitt, nc

    valuation[0].set(punkte)
    valuation[1].set(pschnitt)
    valuation[2].set(nc)

def calc(noten, valuation):

    error = False

    for note in noten:
        if note.get() < 1.0:
            error = True
            message = "Die eingegebene Punktzahl muss "\
                "mindestens 1 betragen."
            tkMessageBox.showwarning("Warnung", message)
            break

        elif note.get() > 15:
            error = True
            message = "Die eingegebene Punktzahl darf "\
                "maximal 15 betragen."
            tkMessageBox.showwarning("Warnung", message)
            break

    if not error:
        zeig(noten, valuation)

root=tk.Tk()
root.title("Abirechner")

frame_top = tk.Frame(root)
frame_top.pack(fill='both')

frame_buttons = tk.Frame(root)
frame_buttons.pack(fill='x', pady=5)

frame_bottom = tk.Frame(root)
frame_bottom.pack(fill='x')

entry_names = (
    "1. LK (hochgestuft):",
    "2. LK (hochgestuft):",
    "3. LK (runtergestuft):",
    "4. GK (schriftlich):",
    "5. GK (mündlich):",
    "6. GK (mündlich):",
    "7. Fach:",
    "8. Fach:"
    )
noten = [tk.DoubleVar() for note in range(len(entry_names))]
entries = list()
DEFAULT_ENTRY_VALUE = 3.0

for item in range(len(entry_names)):
    frame = tk.Frame(frame_top)
    frame.pack(fill='x', pady=1)

    label = tk.Label(frame, text=entry_names[item])
    label.pack(side='left')

    entry = tk.Entry(frame, textvariable=noten[item], width=3)
    entry.pack(side='right',padx=2)
    noten[item].set(DEFAULT_ENTRY_VALUE)
    entries.append(entry)

valuation_names = (
    "Punkte: ",
    "Punktedurchschnitt: ",
    "Numerus Clausus (NC): "
    )
valuation = [tk.DoubleVar() for index in range(len(valuation_names))]

for item in range(len(valuation_names)):
    er_frame = tk.Frame(frame_bottom)
    er_frame.pack(fill='x')

    er_gtlabel = tk.Label(er_frame, text=valuation_names[item])
    er_gtlabel.pack(side='left')

    er_glabel = tk.Label(er_frame, textvariable=valuation[item])
    er_glabel.pack(side='left')

ber=tk.Button(frame_buttons,text="Berechnen",command=lambda note=noten,
    val= valuation: calc(note, val))

ber.pack(side='left')

clo=tk.Button(frame_buttons,text="Schließen",command=close)
clo.pack(side='left')

root.mainloop()
Viel Spass beim experimentieren!

Gruß wuf :wink:
Take it easy Mates!
Antworten