kleines Rechenprogramm

Fragen zu Tkinter.
mathi
User
Beiträge: 314
Registriert: Dienstag 27. November 2007, 14:30

Hallo allerseits,
ich habe mich die letzten Jahre nur mit non-GUI programmen begnügt, und bitte um hilfe beim Umstieg:
nachdem die Grenzen erreicht sind:
http://www.python-forum.de/topic-16449.html

möchte ich als Einstieg mein kleines Interpolationsprogramm mit einer GUI versehen:

Code: Alles auswählen

from Tkinter import *

root = Tk()

textfenster = Text(root)
textfenster.pack()
def hole():
    textfenster.insert(END, '\n' + eingabe.get())
    
textfenster.insert(END,u'gegeben: x | gesucht: y ')
X1=u'Wert X1 mit X1<x: '
lab=Label(root,text=X1)
# ... hier fehlt etwas damit der eingabewert der Variablen X1 zugewiesen wird und im oberen Fenster erscheint
X2=u'Wert X2 mit X2>x: '
lab=Label(root,text=X1)
# ... hier fehlt etwas
Y1=u'Wert Y1 mit y=?: '
lab=Label(root,text=Y1)
# ... hier fehlt etwas
Y2=u'Wert Y2 mit y=?: '
lab=Label(root,text=Y2)
# ... hier fehlt etwas
x=u'Wert x: '
lab=Label(root,text=x)

lab.pack(side = LEFT)

eingabe = Entry(root,width=60)
eingabe.pack(side=LEFT)


    
but = Button(root,text='Hole', command = hole)
but.pack(side = LEFT)
root.mainloop()

#y=(x-X1)*(Y2-Y1)/(X2-X1)+Y1
#print u'Ergebnis y= ',y

Das ist nmein bisheriges Ergebnis, ich möchte oben alle Infos sammeln und unten Eingaben machen, wobei immer die aktuell gefragte Variable als Label erscheint, daneben der zugehörige Wert eingegeben wird,
nach Enter sollte dann im oberen Fenster als bestätigung erscheinen z.B.
gegeben: x | gesucht: y
X1= 15
X2=20
Y1=10
Y2=50
x=17
Ergebnis: y= ...

Nur sieht man ja, dass ich es erst mal zum Gerüst geschaft habe und jetzt bitte ich um Denkanstöße, denn ich stehe im Momment ein bissel auf dem Schlauch :-(
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Zum Verstehen von Tkinter empfehle ich folgende Lektüre:
http://www.ferg.org/thinking_in_tkinter ... grams.html

Leider ein Sch* Layout, aber inhaltlich wirklich hilfreich, um zu verstehen, wie es grundsätzlich funktioniert. Dein Code und deine Probleme damit zeigen, dass du das noch nicht verstanden hast.

Danach helfen dann:
http://effbot.org/tkinterbook/tkinter-i ... troduction
http://infohost.nmt.edu/tcc/help/pubs/tkinter/

Ich denke, wenn du dir etwas Zeit für die Lektüre genommen hast, bekommst du deinen GUI-Aufbau samt Funktionalität - vielleicht bis auf etwas Kosmetik - selbst hin.
mathi
User
Beiträge: 314
Registriert: Dienstag 27. November 2007, 14:30

numerix hat geschrieben:Dein Code und deine Probleme damit zeigen, dass du das noch nicht verstanden hast.
Die Vermutung stimmt.
numerix hat geschrieben: Ich denke, wenn du dir etwas Zeit für die Lektüre genommen hast, bekommst du deinen GUI-Aufbau samt Funktionalität - vielleicht bis auf etwas Kosmetik - selbst hin.
Danke erstmal,
das werde ich tun.

Aber eine Frage sei gestattet: Generell ist es möglich, mit erträglichem Aufwand, meine Vorstellung umzusetzen??
yipyip
User
Beiträge: 418
Registriert: Samstag 12. Juli 2008, 01:18

Da ich grad' die passenden Bausteine zur
Hand hatte, war der Aufwand in der Tat ertraeglich.
:)

Wenn Du willst, kannst Du hier mal gucken.

http://paste.pocoo.org/show/88994/
(Als Anregung)

:wink:
yipyip
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

mathi hat geschrieben:Aber eine Frage sei gestattet: Generell ist es möglich, mit erträglichem Aufwand, meine Vorstellung umzusetzen??
Absolut, ist keine große Sache.
Wenn du mal die Anleitung von Ferg (erster Link oben) durchgehst, wirst du schon auf den ersten Seiten einige Aha-Erlebnisse haben und dein Programm alleine schreiben können. Bis auf die ein oder andere kosmetische Feinheit vielleicht - aber das ist für den Anfang nicht so wichtig. Gegenüber deiner Konsolenfassung wird es auf jeden Fall ein optischer Fortschritt sein .. :wink:
mathi
User
Beiträge: 314
Registriert: Dienstag 27. November 2007, 14:30

Hallo allerseits,
vielen Dank für Eure Hilfe, aber irgendwie finde ich keinen Zugang. ich bin schon ein Stück weiter:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

from Tkinter import *
   
root = Tk()
root.wm_title(u'Bemessung')
menuobj=Menu(root) # Menükonstruktor
root.config(menu=menuobj)
progmenu=Menu(menuobj)

menuobj.add_cascade(label=u'Programm', menu=progmenu)

def interpol():
    root.wm_title(u'Interpolation')
    textfenster.insert(END,u'\ngegeben: x | gesucht: y ')
    eingabe.focus_force()
    
    #lab('Wert X1 mit X1<x: ')
    
    #def X1(*event):
        #X1=eingabe.get()
        #print X1
        #textfenster.insert(END, '\n X1 ='+eingabe.get())
        
    #X2=u'Wert X2 mit X2>x: '

    #Y1=u'Wert Y1 mit y=?: '

    #Y2=u'Wert Y2 mit y=?: '

    #x=u'Wert x: '

    #y=(x-X1)*(Y2-Y1)/(X2-X1)+Y1
    #print u'Ergebnis y= ',y
    
progmenu.add_command(label=u'Interpolation',command=interpol)
progmenu.add_separator()

textfenster = Text(root)
textfenster.pack()

labeltext=Label(root,text=u'Programmhinweise')
labeltext.pack()

variable=u'variable= '

lab=Label(root,text=variable)
lab.pack(side = LEFT)
def Ok(*event):
    xGet=eingabe.get()
    #if xGet==0:
    #    interpol()
    print xGet
    textfenster.insert(END, '\n' +variable+ eingabe.get())
eingabe = Entry(root,width=60)
eingabe.pack(side=LEFT)
eingabe.bind("<Return>", Ok)
eingabe.focus_force()

but = Button(root,text=u'Ok', command = Ok)
but.pack(side = LEFT)

root.mainloop()
aber: wenn ich das Programm starte, kann ich oben das Programm "Interpolation" auswählen, dann erscheint im Textfenster eine Info, ich kann nun unten eine Variable eingeben und ENTER: der Wert wird xGet zugewiesen und oben als variable=... ausgegeben.

Was ich möchte ist: das Label "Programmhinweise" während der Laufzeit des Programms "Interpolation" ändern, und die "variable" nach jeder eingabe durch die nächste erforderliche ändern, sodass als Anzeige im textfeld:

gegeben: x | gesucht: y
X1= 15
X2=20
Y1=10
Y2=50
x=17
Ergebnis: y= ...

erscheint. Wie kann ich die Label ändern?

nebenbei:
MUß ich wirklich Objektorientiert arbeiten, denn ich begreife den Sinn auch nach lektüre o.g. Links für speziell dieses Progamm nicht.
BlackJack

IMHO ist OOP für GUI-Programmierung wichtig, ohne bekommt man schnell unübersichtliche Programme.

Mir scheint auch, Du willst immer noch den linearen Programmierstil von dem Konsolenprogramm erzwingen -- das ist keine gute Idee. Präentiere dem Benutzer alle Eingabefelder auf einmal. Die kann er dann ausfüllen und beim Druck auf einen 'Ok'- oder 'Berechnen'-Knopf werden dann die Werte ausgelesen und die Berechnung durch geführt.

Hast Du Dir die Lösung mit EasyGui mal angeschaut?
mathi
User
Beiträge: 314
Registriert: Dienstag 27. November 2007, 14:30

BlackJack hat geschrieben:
Mir scheint auch, Du willst immer noch den linearen Programmierstil von dem Konsolenprogramm erzwingen -- das ist keine gute Idee. Präentiere dem Benutzer alle Eingabefelder auf einmal. Die kann er dann ausfüllen und beim Druck auf einen 'Ok'- oder 'Berechnen'-Knopf werden dann die Werte ausgelesen und die Berechnung durch geführt.
Das Prinzip meines Programmes ist es, ALLES nur mit dem Numpad einzugeben also nur Zahlen und ENTER. Da ich möglichst schnell zu einem verwertbaren Ergebnis kommen möchte. Des Weiteren die Textausgabe um per copy and paste die Ausgabe weiterzuverwenden (-> mit griechischen Buchstaben :-))
Das ist eine Grundbedingung des Programmes. Alle Eingabefelder auf einmal scheidet aus.
BlackJack hat geschrieben:Hast Du Dir die Lösung mit EasyGui mal angeschaut?
Ja, aber ich möchte nicht alle Eingabefelder auf einmal und wollte mich bei der Gelegenheit ein wenig in TKInter einarbeiten. Die o.g. GUI ist für meine Zwecke richtig, wenn ich das noch richtig einbauen könnte.

Über diese GUI sind dann am Ende 16 Programme lauffähig, die alle dem selben Prinzip folgen, das Programm "Interpolation" ist nur zur Erarbeitung des Prinzips.
BlackJack

Die Numpad-Eingabe und Anzeige aller Eingabefelder schliessen sich ja nicht gegenseitig aus. Du kannst die Eingabetaste ja an die `Entry`-Exemplare binden und mit "gehe zum nächsten `Entry`" belegen.

Wenn da 16 einzelne Berechnungsprogramme unter einer GUI zusammen gefasst werden sollen, spricht das übrigens auch für OOP.
mathi
User
Beiträge: 314
Registriert: Dienstag 27. November 2007, 14:30

ich würde gerne diesen linearen Verlauf beibehalten, wenn das irgendwie geht, nur bin ich da ohne ein wenig Hilfe (zur Selbsthilfe) aufgeschmissen.
Im grunde haben alle Programme gemeinsam:
1. gib eine Zahl ein
2. reche etwas, vergleiche etwas
3. gib einen Hinweis aus
4. gib noch eine Zahl ein
5. gib das Ergebnis aus

Ich werde also erst einmal schauen, das obige Programm auf OOP umzuschreiben und mich dann wieder melden??
mathi
User
Beiträge: 314
Registriert: Dienstag 27. November 2007, 14:30

ich frage einfach hier weiter weil es dazugehört:

Wie kann ich den Labeltext

Code: Alles auswählen

labeltext=tk.Label(root,text=u'Programmhinweise')
labeltext.pack()
nachträglich, also im laufenden Programm ändern?

gefunden: label.config(text='...')
abgdf

Hi,
Wie kann ich den Labeltext nachträglich, also im laufenden Programm ändern?
Dazu habe ich mal geschrieben:
6. Changes of Variable-Values at Application-Runtime and the "Tkinter.Variable"-Object

Some widgets like "Tkinter.Label" accept a "textvariable"-argument instead of the "text"-argument.
With it, the displayed text can be changed while the main-loop of the program is running.

While you can pass an ordinary Python-string with the "text"-argument like in

text = "Hello"

this isn't enough for "textvariable".

For this a special object called "Tkinter.Variable" is needed.

This object isn't difficult to use, but you have to know, when you need it.

If a Tkinter-main-window is already defined, you can get an instance of a "Tkinter.Variable" just like this:

mytkvar = Tkinter.Variable()

Then its value can be set with:

mytkvar.set("Hello")

Then, the label can be defined with the "textvariable"-argument and the "Tkinter.Variable"-object:

label = Tkinter.Label(mainwindow, textvariable = mytkvar)

Later, when the program is running, the text displayed in the label can be dynamically changed just doing:

mytkvar.set("World")

The value stored in the "Tkinter.Variable"-object can be accessed as a Python-datatype any time doing:

myPythonVariable = mytkvar.get()

(There are some flavours of "Tkinter.Variable" called "Tkinter.StringVar", "Tkinter.IntVar", "Tkinter.DoubleVar" and "Tkinter.BooleanVar".)

Basically, "Tkinter.Variable"-objects must be used in widget-arguments instead of Python-strings or -integers, when the variable-values can change dynamically at application-runtime.

This is typically the case, when

* the "textvariable"-argument,
* the Radiobutton-widget,
* the Checkbutton-widget.

is used.

There's another way of changing the resource-options of some widgets at application-runtime manually by using their ".configure()"-method.
HTH
ich würde gerne diesen linearen Verlauf beibehalten, wenn das irgendwie geht
Nein, das geht nicht: Bei

Code: Alles auswählen

root.mainloop()
ist es vorbei mit jeder Art von linearem Verlauf.
Gewöhn' Dich dran !

Gruß
mathi
User
Beiträge: 314
Registriert: Dienstag 27. November 2007, 14:30

na ok, dann sehen wir mal wo der Weg mich hinführt.

Jetzt habe ich alles objektorientiert Programmiert, leider gibt es beim Aufruf des Programmes Interpolation eine Fehlermeldung, die ich nicht beseitigen kann...
Ist mein Code sonst soweit ok??

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

#from Tkinter import *
import Tkinter as tk

class Main:
    def Ok(self,*events):
        xGet=eingabe.get()
        #if xGet==0:
        #    interpol()
        print xGet
        textfenster.insert(tk.END, '\n' +text+ eingabe.get())
        
    def __init__(self,root):
        self.myRoot=root
        
        self.menuobj=tk.Menu(root) # Menükonstruktor
        root.config(menu=self.menuobj)
        self.progmenu=tk.Menu(self.menuobj)

        self.menuobj.add_cascade(label=u'Programm', menu=self.progmenu)
        self.progmenu.add_command(label=u'Interpolation',command=interpolation)
        self.progmenu.add_separator()

        self.textfenster = tk.Text(root)
        self.textfenster.pack()

        self.labeltext=tk.Label(root,text=u'Programmhinweise')
        self.labeltext.pack()

        self.lab=tk.Label(root,text='   ')
        self.lab.pack(side = tk.LEFT)
        
        self.eingabe = tk.Entry(root,width=60)
        self.eingabe.pack(side=tk.LEFT)
        self.eingabe.bind("<Return>", self.Ok)
        self.eingabe.focus_force()

        self.but = tk.Button(root,text=u'Ok', command = self.Ok)
        self.but.pack(side = tk.LEFT)     

class interpolation:
    def __init__(self):
        root.wm_title(u'Interpolation')
        self.textfenster.insert(tk.END,u'\ngegeben: x | gesucht: y ')
        self.eingabe.focus_force()
        self.labeltext.config(text=u'Gib den Wert ein')
        self.lab.config(text=u'Wert X1 mit X1<x: ')
        text=u'X1='
        #self.Ok()
        #eingabe.insert(0,u'15')    
        #item.get_child().set_text('Spam')
        #def X1(*event):
            #X1=eingabe.get()
            #print X1
            #textfenster.insert(END, '\n X1 ='+eingabe.get())
            
        #X2=u'Wert X2 mit X2>x: '

        #Y1=u'Wert Y1 mit y=?: '

        #Y2=u'Wert Y2 mit y=?: '

        #x=u'Wert x: '

        #y=(x-X1)*(Y2-Y1)/(X2-X1)+Y1
        #print u'Ergebnis y= ',y

root = tk.Tk()
root.wm_title(u'Bemessung')

myapp=Main(root)
root.mainloop()
BlackJack

`interpolation` ist kein Programm sondern eine Klasse. Und die Fehlermeldung dürfte wahrscheinlich sein, dass es `self.textfenster` nicht gibt. Woher auch. Das ist nicht OOP, denn anscheinend hast Du das mit den Objekten noch nicht verstanden, wenn Dir nicht klar ist, warum das nicht funktioniert.

`root` wird von beiden Klassen aus direkt auf Modulebene angesprochen, ist also ein globales Objekt. Das sollte nicht sein. Am besten hat man auf Modulebene nur Konstanten, Klassen und Funktionen, dann kommt man gar nicht erst in die Versuchung so etwas zu tun.
mathi
User
Beiträge: 314
Registriert: Dienstag 27. November 2007, 14:30

ja das stimmt wohl, ich begreife das einfach nicht. Hab zwar noch ein schönes Beispiel vorliegen, aber ich steige nicht hinter den Sinn und die Funktion des Ganzen :cry:
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

mathi hat geschrieben:ja das stimmt wohl, ich begreife das einfach nicht. Hab zwar noch ein schönes Beispiel vorliegen, aber ich steige nicht hinter den Sinn und die Funktion des Ganzen :cry:
Nicht aufgeben! Das wird! Wenn man jahrelang rein prozedural/imperativ/linear programmiert hat und diese Art des Denkens verinnerlicht hat, dann kann das eine mühsame Angelegenheit sein. Jedenfalls, wenn man keinen hat, der es einem didaktisch vernünftig erklärt oder ein entsprechend gutes Buch dazu gefunden hat ... :wink:
mathi
User
Beiträge: 314
Registriert: Dienstag 27. November 2007, 14:30

Das Forum hier ist leider meine einzige Anlaufstelle
BlackJack

@mathi: Nicht ganz; es gibt auch noch das Wiki. Schau Dir mal die Liste deutschsprachiger (Online-)Literatur in der FAQ an: [wiki]FAQ#DeutschsprachigeLektrenImNetz[/wiki]

Der Text von Alan Gould zum Beispiel. Da gibt's unter fortgeschrittene Themen OOP, ereignisbasierte Programmierung, und GUI-Programmierung.

Das englische Original habe ich jedenfalls in ganz guter Erinnerung als Einsteigerlektüre.
Benutzeravatar
kaytec
User
Beiträge: 608
Registriert: Dienstag 13. Februar 2007, 21:57

Hallo mathi !

Evt. hilft dir das:

http://paste.pocoo.org/show/89294/

Ich hoffe meine Namensgebungen entsprechen hoeherer Mathematik :oops: .

gruss frank
yipyip
User
Beiträge: 418
Registriert: Samstag 12. Juli 2008, 01:18

Hallo mathi,
ich weiss, dass dieses Thema ein harter Brocken ist,
den man als Einsteiger ziemlich lange verdauen muss.

Ich persönlich bin hier immer an
Snippets interssiert, die über meinem Niveau liegen,
denn nur so lernt man etwas dazu.

Deshalb war ich auch so wagemutig, Dir
mein Verständnis vom sogenannten "Model View Controller Pattern"
zu zeigen, in der Hoffnung, dass Du (nach einiger Zeit)
etwas damit anfangen kannst.

Es geht dabei darum, ein GUI-Programm in möglichst unabhängige
Komponenten aufzuteilen, um einerseits dessen Komplexität bewältigen
zu können und andererseits einen ereignisgesteuerten
Ablauf zu ermöglichen.

Wie die Namen schon sagen:
Der "View" ist fuer die Ausgabe und das Warten auf
Ereignisse(Events) zuständig.
Im "Model" werden die eigentlichen Daten verarbeitet.
Im "Controller" laufen alle Fäden zusammen.

Der View meldet die eingetretenen Ereignisse an den
Controller. Der Controller nimmt die Daten vom View entgegen und
ruft Methoden des Models auf.
Das Model weiss gar nichts von den anderen Komponenten,
es ist nur für die Berechnungen zuständig.
Der Controller sorgt bei einem Event dafür, das der
View mit den Daten des Models aktualisiert wird.
(...bitte jetzt nicht frustriert in die Tischkante beissen...)
Keine Sorge, bald werden die ersten Aha-Momente kommen.


Fange am besten erstmal mit den Links von
Blackjack an, alles weitere ergibt sich dann.

:wink:
yipyip
Antworten