Frage zu columnspan TkInter

Fragen zu Tkinter.
Antworten
cougartrader
User
Beiträge: 11
Registriert: Sonntag 11. August 2013, 15:12

Hallo,

ich hab meine erste GUI mit TkInter erstellt, so zum üben einen einfachen Pivotrechner für den Aktienmarkt,
den es zwar überall gibt, aber darum geht es ja nicht. Der soll zudem noch erweitert werden... dennoch, ich bin erst sehr kurz dabei
und finde den Rechner bis hierhin nicht schlecht.

Allerdings bin ich auf eine Hürde gestossen, ich hab das ganze per grid eingeteilt, als nächstes versuche ich mal etwas mit frames,
aber jetzt erstmal grid.

Meine Eingabefelder in column1 sind mir zu breit, ich hab versucht, das mit columnspan einzustellen, aber vermutlich
nicht richtig (Zeile 45-49). In die Eingabefelder kommen nur 4-stellige Zahlen und die Ausgabe ab row6 geben auch nur 4-stellig zurück, evtl.
änder ich das noch in 2 Nachkommastellen, die sind aber dennoch viel zu breit.
Wo liegt mein Fehler? Hier mal das komplette script, vielleicht kann ja mal jemand draufschauen:

Code: Alles auswählen

import Tkinter

def ende():
    main.destroy()
  
# Funktion zum Berechnen 
def pivot():
    eingabe = e.get()
    eingabe1 = e1.get()
    eingabe2 = e2.get()
    eingabe3 = e3.get()
    eingabe4 = e4.get()
    try:
        zahl = int(eingabe)
        zahl1 = int(eingabe1)
        zahl2 = int(eingabe2)
        zahl3 = int(eingabe3)
        zahl4 = int(eingabe4)
        #Berechnung Pivotpunkte
        lb["text"] = "      ""Pivot:" + str((zahl1 + zahl2 + zahl3)/3)
        lb6["text"] = "      ""R1:  " + str(((((zahl1 + zahl2 + zahl3)/3)+(zahl1 + zahl2 + zahl3)/3)-zahl2))
        lb7["text"] = "     ""R2:  " + str(((zahl1 + zahl2 + zahl3)/3)+(zahl1-zahl2))
        lb8["text"] = "     ""R3:  " + str(((((zahl1 + zahl2 + zahl3)/3)-zahl2)*2)+zahl1)
        lb9["text"] = "     ""S1:  " + str((((zahl1 + zahl2 + zahl3)/3)+(zahl1 + zahl2 + zahl3)/3)-zahl1)
        lb10["text"] = "     ""S2:  " + str(((zahl1 + zahl2 + zahl3)/3)-(zahl1-zahl2))
        lb11["text"] = "     ""S3:  " + str(((((zahl1+zahl2+zahl3)/3)-zahl1)*2)+zahl2)
    except:
        lb["text"] = "Eingabe pruefen"

main = Tkinter.Tk()

# Anordnung der Vorgabefelder
lb1 = Tkinter.Label(main, text="Open").grid(row=0)
lb2 = Tkinter.Label(main, text="High").grid(row=1)
lb3 = Tkinter.Label(main, text="Low").grid(row=2)
lb4 = Tkinter.Label(main, text="Close").grid(row=3)
lb5 = Tkinter.Label(main, text="Open heute").grid(row=4)

e = Tkinter.Entry(main)
e1 = Tkinter.Entry(main)
e2 = Tkinter.Entry(main)
e3 = Tkinter.Entry(main)
e4 = Tkinter.Entry(main)

e.grid(row=0, column=1,  columnspan=2,)
e1.grid(row=1, column=1,  columnspan=2)
e2.grid(row=2, column=1,  columnspan=2)
e3.grid(row=3, column=1,  columnspan=2)
e4.grid(row=4, column=1,  columnspan=2)

# Button zur Berechnung und Ausgabe
bpivot = Tkinter.Button(main,
           text = "Berechnen", command = pivot)
bpivot.grid(row=15,  column=2)

# Anordnung der Vorgabefelder Pivotpunkte
lb = Tkinter.Label(main, text = "")
lb.grid(row=5,  column=0)
lb = Tkinter.Label(main, text = "Pivot:")
lb.grid(row=6,  column=0)
lb6 = Tkinter.Label(main, text = "R1  :")
lb6.grid(row=7,  column=0)
lb7 = Tkinter.Label(main, text = "R2  :")
lb7.grid(row=8,  column=0)
lb8 = Tkinter.Label(main, text = "R3  :")
lb8.grid(row=9,  column=0)
lb9 = Tkinter.Label(main, text = "S1  :")
lb9.grid(row=10,  column=0)
lb10 = Tkinter.Label(main, text = "S2  :")
lb10.grid(row=11,  column=0)
lb11 = Tkinter.Label(main, text = "S3  :")
lb11.grid(row=12,  column=0)


bende = Tkinter.Button(main, text = "Ende",
                       command = ende)
bende.grid(row=15,  column=3)

main.mainloop()
LG
Holger
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hi cougartrader

Hatte keine Lust dein Skript zu beschreiben und abzuändern. Bevorzugte ein neues zu schreiben. Vielleicht kannst du davon etwas gebrauchen. Für die Pivot-Rechnerei übernehme ich Grantie :-)

Code: Alles auswählen

try:
    #~~ For Python 2.x
    import Tkinter as tk
except ImportError:
    #~~ For Python 3.x
    import tkinter as tk

APP_WIN_XPOS = 50
APP_WIN_YPOS = 50

# Entry item
ENTRY_OPEN = "Open"
ENTRY_HIGH = "High"
ENTRY_LOW = "Low"
ENTRY_CLOSE = "Close"
ENTRY_OPEN_TODAY = "Open heute"

ENTRY_ITEMS = [
    ENTRY_OPEN, ENTRY_HIGH, ENTRY_LOW, ENTRY_CLOSE, ENTRY_OPEN_TODAY]
    
# Output items
OUTPUT_PIVOT = "Pivot:"
OUTPUT_R1 = "R1"
OUTPUT_R2 = "R2"
OUTPUT_R3 = "R3"
OUTPUT_S1 = "S1"
OUTPUT_S2 = "S2"
OUTPUT_S3 = "S3"

OUTPUT_ITEMS = [
    OUTPUT_PIVOT, OUTPUT_R1, OUTPUT_R2, OUTPUT_R3, OUTPUT_S1, OUTPUT_S2,
    OUTPUT_S3]

COLOR_HEADER = 'steelblue'
ERROR_PIVOT_CALC = "Eingabe pruefen"
ENTRY_WIDTH = 4
OUTPUT_WIDTH = 6

class App(object):
    
    def __init__(self, app_title=''):
        self.win = tk.Tk()
        self.win.title(app_title)
        self.win.geometry('+{0}+{1}'.format(APP_WIN_XPOS, APP_WIN_YPOS))
        self.win.protocol("WM_DELETE_WINDOW", self.close)

        self.data = dict()
        for item in ENTRY_ITEMS:
           self.data[item]= dict()

        for item in OUTPUT_ITEMS:
           self.data[item]= dict()
        
        self.build_app_gui()
        
    def build_app_gui(self):
        
        main_frame = tk.Frame(self.win)
        main_frame.pack(expand=True, padx=10, pady=10)

        entry_frame = tk.Frame(main_frame)
        entry_frame.grid(row=0, column=0, sticky='wesn')
        
        # Setup entry fields 
        row_ptr = 0
        tk.Label(entry_frame, text='Eingabe:', font=('Helvetica', 12, 'bold',
            'underline'), fg=COLOR_HEADER).grid(
                row=row_ptr, column=0, columnspan=2, sticky='w', pady=(0,5))
            
        for entry_item in ENTRY_ITEMS:
            row_ptr += 1
            var = tk.StringVar()
            var.set('0')
            self.data[entry_item]['value'] = var
            
            tk.Label(entry_frame, text="{0}: ".format(entry_item)).grid(
                row=row_ptr, column=0, sticky='e', pady=(0,2))
                
            tk.Entry(entry_frame, textvariable=var, highlightthickness=0,
                bg='white', width=ENTRY_WIDTH ).grid(
                    row=row_ptr, column=1, sticky='w', pady=(0,2))

        row_ptr += 1
        tk.Label(entry_frame, text='Ausgabe', font=('Helvetica', 12, 'bold',
            'underline'), fg=COLOR_HEADER).grid(
                row=row_ptr, column=0, columnspan=2, sticky='w', pady=(10,5))

        # Setup output fields    
        for output_item in OUTPUT_ITEMS:
            row_ptr += 1
            var = tk.StringVar()
            var.set('?')
            self.data[output_item]['value'] = var

            tk.Label(entry_frame, text="{0}: ".format(output_item)).grid(
                row=row_ptr, column=0, sticky='e', pady=(0,2))
            
            if output_item == OUTPUT_PIVOT:
                width = len(ERROR_PIVOT_CALC)
            else:
                width = OUTPUT_WIDTH
                
            tk.Label(entry_frame, textvariable=var, bg='gray80', width=width,
                anchor='w').grid(row=row_ptr, column=1, sticky='w', pady=(0,2))

        button_clac_pivot = tk.Button(main_frame, text = "Berechnen",
            command = self.calc_pivot)
        button_clac_pivot.grid(row=1, column=0, pady=(10,0))

        button_end = tk.Button(main_frame, text = "Ende", command=self.close)
        button_end.grid(row=1, column=1, pady=(10,0))
        
    def calc_pivot(self):
        try:
            open = int(self.data[ENTRY_OPEN]['value'].get())
            high = int(self.data[ENTRY_HIGH]['value'].get())
            low = int(self.data[ENTRY_LOW]['value'].get())
            close = int(self.data[ENTRY_CLOSE]['value'].get())
            open_today = int(self.data[ENTRY_OPEN_TODAY]['value'].get())

            pivot = (high + low + close) // 3
            r1 = pivot + pivot - low
            r2 = pivot + (high - low)
            r3 = ((pivot - low) * 2) + high
            s1 = (pivot + pivot) - high
            s2 = pivot - (high - low)
            s3 = ((pivot - high) * 2) + low        
            
            self.data[OUTPUT_PIVOT]['value'].set(pivot)
            self.data[OUTPUT_R1]['value'].set(r1)
            self.data[OUTPUT_R2]['value'].set(r2)
            self.data[OUTPUT_R3]['value'].set(r3)
            self.data[OUTPUT_S1]['value'].set(s1)
            self.data[OUTPUT_S2]['value'].set(s2)
            self.data[OUTPUT_S3]['value'].set(s3)
        except:
            self.data[OUTPUT_PIVOT]['value'].set(ERROR_PIVOT_CALC)
        
    def run(self):
        self.win.mainloop()
    
    def close(self):
        print("Do something before shutdown")
        self.win.destroy()
            
App("Pivot-Rechner").run()
Gruß wuf :wink:
Take it easy Mates!
yipyip
User
Beiträge: 418
Registriert: Samstag 12. Juli 2008, 01:18

Sorry, aber da ist nichts, was man so stehen lassen koennte. (Ist nicht boese gemeint ;-))
Code auf Moduleebene, durchnummerierte Variablen statt Listen, keine organisatorische Struktur... Spaghetti Alarm!
Lass dir mal die Variablen lb1,...,lb5 ausgeben.
Also:
1) Listen, etc. verwenden
2) Klassen und Objekte verwenden
3) Den Unterschied zwischen Event-Driven und sequentiellem Ablauf verstehen
4) Den Effbot lesen

Als Anfang:

Code: Alles auswählen

#!/usr/local/bin/python

import Tkinter as tk

####

class Gui(object):


    def __init__(self):

        self.root = tk.Tk()
        
        self.entry_frame = tk.Frame(self.root)
        entry_texts = "Open", "High", "Low", "Close", "Open Today"
        self.entry_labels = [tk.Label(self.entry_frame,
                                      text=text) for text in entry_texts]
        self.entries = [tk.Entry(self.entry_frame,
                                 width=6) for _ in entry_texts]
        for i, (label, entry) in enumerate(zip(self.entry_labels, self.entries)):
            label.grid(row=i, column=0, pady=4, padx=4, sticky=tk.W)
            entry.grid(row=i, column=1, pady=4, padx=6, sticky=tk.W+tk.E)

        self.entry_frame.grid_columnconfigure(1, weight=1) # optional
        self.entry_frame.pack(fill=tk.X)

        self.but_frame = tk.Frame(self.root)
        actions = zip(("Calculate", "Quit"), (self.get_values, self.fin))
        self.buttons = [tk.Button(self.but_frame, text=s, width=12,
                                  command=cmd) for s, cmd in actions]
        for but in self.buttons:
            but.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        self.but_frame.pack(fill=tk.BOTH, expand=True)
        
        self.err_frame = tk.Frame(self.root)
        self.err_msg = tk.StringVar()
        self.err_label = tk.Label(self.err_frame, textvariable=self.err_msg,
                                  bg='#000000', fg='#00ff00')
        self.err_label.pack(fill=tk.X)
        self.err_frame.pack(fill=tk.X)
        
          
    def get_values(self):

        raw_values = [entry.get() for entry in self.entries]
        try:
            values = map(float, raw_values)
        except ValueError:
            self.err_msg.set("Invalid Input!")
        else:
            self.err_msg.set("")
            self.calculate(values)


    def calculate(self, values):
        
        print values
            

    def run(self):

        self.root.mainloop()


    def fin(self):

        self.root.destroy()

####

if __name__ == '__main__':

    Gui().run()
Ups, wuf ist doch da. :-)
:wink:
yipyip
cougartrader
User
Beiträge: 11
Registriert: Sonntag 11. August 2013, 15:12

Hallo

habt vielen Dank! Das wirft aber für mich weitere Fragen auf, ich kann von euren Script's vieles brauchen, allerdings
muss ich mich erstmal schlau machen, was was bedeutet usw.
Ich hab mir das Buch von T. Theis "Einstieg in Python" 3. Auflage besorgt und eins seiner dortigen script "umgebastelt"

Code: Alles auswählen

import Tkinter

def ende():
    main.destroy()

# Funktion zum Quadrieren und Ausgeben
def quad():
    eingabe = e.get()
    try:
        zahl = float(eingabe)
        lb["text"] = "Ergebnis:" + str(zahl * zahl)
    except:
        lb["text"] = "Bitte Zahl eingeben"

main = Tkinter.Tk()

# einzeiliges Eingabefeld
e = Tkinter.Entry(main)
e.pack()

# Button zur Verarbeitung und Ausgabe
bquad = Tkinter.Button(main,
           text = "Quadrieren", command = quad)
bquad.pack()

# Ausgabe-Label
lb = Tkinter.Label(main, text = "Ergebnis:")
lb.pack()

bende = Tkinter.Button(main, text = "Ende",
                       command = ende)
bende.pack()

main.mainloop()
Ein Rechner zum quadrieren von Zahlen. Allerdings muss ich gestehen, dass ich einen vergleichbaren Code wie euren da noch nicht
entdeckt hab... der scheint manches anders anzugehen.

Also entweder muss ich schauen, woher ich etwas über TkInter zu lesen bekomme oder gleich etwas zu PyQt und den Designer... was aber
ja mit der Struktur des Berechnens wenig zu tun hat! Da muss ich mich extra drum bemühen.

Mein tägl. Brot ist der eigene Intradayhandel von Derivaten am Aktienmarkt. Dafür habe ich etwas, was mir sagt, wo die
wahrscheinlichsten Wendepunkte liegen usw., lässt sich nicht so einfach beschreiben, das Ergebnis für heute sah z.B. so aus (die
Ausgabe der Terminalversion meines Rechners):

Code: Alles auswählen

28.08.2013
--------------------------------------------
--------------------------------------------
Eingabe Open:  8388
Eingabe High:  8425
Eingabe Low:   8190
Eingabe Close: 8205
Eingabe open heute: 8221
--------------------------------------------
--------------------------------------------
Pivot:   8273
R1:      8356
R2:      8508
R3:      8591
S1:      8121
S2:      8038
S3:      7886
--------------------------------------------
--------------------------------------------
Long ab    8238                  Short ab     8203
Stop bei    8221                  Stop bei     8221
  
1. Ziel bei  8249                  1. Ziel bei 8192
2. Ziel bei  8267                  2. Ziel bei 8174
3. Ziel bei  8295                  3. Ziel bei 8146
4. Ziel bei  8318                  4. Ziel bei 8123
5. Ziel bei  8342                  5. Ziel bei 8099
6. Ziel bei  8370                  6. Ziel bei 8071
7. Ziel bei  8416                  7. Ziel bei 8025
--------------------------------------------
--------------------------------------------
Tagesrange 2.87 %
Als Beispiel, das 5. Ziel short wurde "prophezeit" bei 8099, das Tief war heute bei 8095, short ab 8203 bedeutet satte +104 Punkte bis 8099
ohne das vorher ein Stop ausgelöst wurde. Im Daxfuturehandel ist ein Punkt 25,- wert....
Es gibt sehr viele die mit Futures handeln und ich wurde schon ein paar mal nach meinen Berechnungen gefragt, allerdings geb
ich nicht so ohne weiteres raus, das würde kosten...

Und da denke ich mir, wenn schon, dann richtig als komplettes Windows-Programm mit GUI etc. Das Ziel ist es, das ganze mit einer
ansprechenden GUI auszustatten sowie einer Datenbank, die die Kursdaten abspeichert damit man sie bei Bedarf
nochmal hervorkramen kann usw., evtl. einer Sharewareversion, die läuft 'ne Woche und danach kann man ohne Registrierung nichts mehr eingeben o.ä.

Es kann natürlich auch sein, das man nur 10 Stück davon an den Mann/die Frau bringt, wer weiss das schon... abwarten.
Das ist aber zweitrangig, mir ist es rel. egal ob ich den Rechner verkaufe oder nicht, mir geht es um das Lernen um so etwas
als Programm zu erstellen.
Jetzt aber genug geplappert....!

Daher danke ich herzlich für die "Korrektur" meiner Erstversion, ich werde jetzt mal versuchen herauszufinden, was was in den Codes bedeutet, insbesondere was die Pivotberechnung angeht.

LG
Holger
BlackJack

@cougartrader: Python ist nicht wirklich gut geeignet den Benutzer an irgend etwas zu hindern. Wenn das Programm am Ende von ein paar mehr Leuten interessant gefunden wird, kann man das auch auf alle anderen Programmiersprachen erweitern. Wenn der Benutzer nicht auf alles Zugriff haben soll, darf man ihm den Code nicht geben. Fazit: Zumindest ein Teil des Programms/Systems darf nicht in die Hände des Benutzers geraten. Das läuft auf einen Webservice hinaus.
Antworten