Verwenden von globalen Variablen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
KlaRo18
User
Beiträge: 1
Registriert: Samstag 6. Oktober 2018, 22:16

Hallo zusammen,

ich habe mir in mühevoller Kleinarbeit mein Programm am für den Raspberry zusammengestoppelt, jetzt hänge ich aber leider.
Ich möchte meine programmierte Anzeigetafel mit globalen Variablen versehen, damit ich diese dann auf einer 7-Segmentanzeige ausgeben kann. Aber irgendwie blick ich bei der Definition der Variablen nicht durch, bzw. weiß ich nicht wie und wo ich diese richtig definiere.
Hier mal mein Programm:
# -*- coding: cp1252 -*-
from Tkinter import *
import time
from datetime import datetime

from luma.led_matrix.device import max7219
from luma.core.interface.serial import spi, noop
from luma.core.virtual import viewport, sevensegment

class StopWatch(Frame):
""" Implements a stop watch frame widget. """
def __init__(self, parent=None, **kw):
Frame.__init__(self, parent, kw)
self._start = 0.0
self._elapsedtime = 0.0
self._running = 0
self.timestr = StringVar()
self.makeWidgets()

def makeWidgets(self):
""" Make the time label. """
l = Label(self, textvariable=self.timestr)
self._setTime(self._elapsedtime)
l.config(fg='Red', font=('Arial',100))
l.pack(fill=X, expand=NO, pady=2, padx=2)

def _update(self):
""" Update the label with elapsed time. """
self._elapsedtime = time.time() - self._start
self._setTime(self._elapsedtime)
self._timer = self.after(50, self._update)

def _setTime(self, elap):
""" Set the time string to Minutes:Seconds:Hundreths """
minutes = int(elap/60)
seconds = int(elap - minutes*60.0)
hseconds = int((elap - minutes*60.0 - seconds)*100)
self.timestr.set('%02d:%02d' % (minutes, seconds))

def Start(self):
""" Start the stopwatch, ignore if running. """
if not self._running:
self._start = time.time() - self._elapsedtime
self._update()
self._running = 1

def Stop(self):
""" Stop the stopwatch, ignore if stopped. """
if self._running:
self.after_cancel(self._timer)
self._elapsedtime = time.time() - self._start
self._setTime(self._elapsedtime)
self._running = 0

def Halbzeit(self):
""" Stop the stopwatch, ignore if stopped. """
self._start = time.time()
self._elapsedtime = 2700.00
self._setTime(self._elapsedtime)

def Reset(self):
""" Reset the stopwatch. """
self._start = time.time()
self._elapsedtime = 0.0
self._setTime(self._elapsedtime)



class CounterHome(Frame):
def __init__(self, parent=None, **kw):
Frame.__init__(self, parent, kw)
self.counterh = 0
self.counter_label = Label(self, font="Arial 100 bold", fg="RED")
self.counter_label.pack()
Button(self, font=('Arial',30), width=10, text='Heim +', command=self.count_up).pack()
Button(self, font=('Arial',30), width=10, text='Heim -', command=self.count_down).pack()
self._update_counter()

def _update_counter(self):
self.counter_label['text'] = str(self.counterh)


def count_up(self):
self.counterh += 1
if self.counterh > 99 : self.counterh = 0
self._update_counter()

def count_down(self):
self.counterh -= 1
if self.counterh < 0 : self.counterh = 0
self._update_counter()

class CounterAway(Frame):
def __init__(self, parent=None, **kw):
Frame.__init__(self, parent, kw)
self.countera = 0
self.counter_label = Label(self, font="Arial 100 bold", fg="RED")
self.counter_label.pack()
Button(self, font=('Arial',30), width=10, text='Auswaerts +', command=self.count_up).pack()
Button(self, font=('Arial',30), width=10, text='Auswaerts -', command=self.count_down).pack()
self._update_counter()

def _update_counter(self):
self.counter_label['text'] = str(self.countera)


def count_up(self):
self.countera += 1
if self.countera > 99 : self.countera = 0
self._update_counter()

def count_down(self):
self.countera -= 1
if self.countera < 0 : self.countera = 0
self._update_counter()


def main():
root = Tk()
w, h = root.winfo_screenwidth(), root.winfo_screenheight()
"""root.geometry("%dx%d+0+0" % (w, h))"""
root.geometry('1000x1000')
sw = StopWatch(root)
sw.pack(side=TOP)
counterhome = CounterHome(root)
counterhome.place(x=200, y=300)
counteraway = CounterAway(root)
counteraway.place(x=450, y=300)


Button(root, width=7, font=('Arial',30), text='Start', command=sw.Start).place(x=50, y=200)
Button(root, width=7, font=('Arial',30), text='Stop', command=sw.Stop).place(x=300, y=200)
Button(root, width=7, font=('Arial',30), text='Halbzeit', command=sw.Halbzeit).place(x=800, y=200)
Button(root, width=7, font=('Arial',30), text='Reset', command=sw.Reset).place(x=550, y=200)
Button(root, width=10, font=('Arial',30), text='Quit', command=root.destroy).place(x=10, y=10)

"""
print home
print away
print time
hier sollte man die von oben aktuellen Werte als globale Variable zur Verfügung haben
"""

root.mainloop()

if __name__ == '__main__':
main()

Es macht nichts anderes als eine Uhr zu starten, stoppen, reseten und wenn man möchte auf Halbzeit zu springen.
Des weiteren kann der Spielstand auf- und abgezählt werden.

Damit ich diese Werte jetzt mit einem MAX7219 auf eine 8x7 Segmentanzeige schieben kann, bräuchte ich diese Werte global.
Kann mir vielleicht jemand einen Denkanstoss geben, wie und wo ich das definieren muss, damit das funzt?

Vielen Dank schon mal im Voraus,
Gruß Robert
Benutzeravatar
sls
User
Beiträge: 480
Registriert: Mittwoch 13. Mai 2015, 23:52
Wohnort: Country country = new Zealand();

Nächstes Mal den Quellcode bitte entsprechend mit den </>-Tags formatieren, sonst ist dieser unbrauchbar, da Einrückungen verloren gehen usw. (Ja, das ist wichtig.)

Ich weiß zwar nicht, ob du die GUI-Logik durch ein IDE-Plugin o.ä. generiert hast, was die wilden Bezeichner erklären würde, aber dennoch:

Funktionen, Methoden und Variablen werden in Python klein_mit_unterstrich geschrieben. Man sollte keine *-Importe machen, weil man sich so den Namespace mit Modulen / Klassen zumüllt, die man vielleicht nie benötigt, außerdem kann es zu Namenskonflikten verschiedener Module kommen. Außerdem sieht man als "Fremder" immer, "woher" denn nun diese oder jene Klasse usw. kommt.

`w`, `h` sind keine aussagekräftigen Bezeichner. Man kann das noch relativ erraten, man hat durch die Abkürzung aber nichts gewonnen. Im Gegenteil. `hseconds` wurde deklariert aber nie verwendet.

CounterHome und CounterAway sind fast identisch, sie machen im prinzip das selbe, nur unterscheiden sie sich darin dass es ein Heim- oder Auswärtsspiel ist. Hier gilt "don't repeat yourself".

Zu deinem Problem: auf die jeweiligen Zählerstände (ich nehme an du meinst die Attribute `countera` usw.?) zu zugreifen ist kein Problem. Dafür braucht man auch keine globale Variable. Falls du wirklich *die* globalen Variablen aus Python meinst, vergiss gleich wieder dass es sie gibt. Sie zu verwenden ist in den meisten fällen falsch. In deinem Beispiel kannst du über das Objekt der Klasse auf das Attribut zugreifen. Z.B. "counteraway.countera", ich würde nur zusehen, dass ich die GUI-Logik deines Programms von der LED-Matrix entkopple und das nicht in der main-Methode deines GUI-Programms zusammen nagle.

PS: bitte nächstes mal deine Frage im richtigen Unterforum platzieren. IMO gehört das eher in das GUI-Subforum: Python GUI-Toolkits
When we say computer, we mean the electronic computer.
Sirius3
User
Beiträge: 17738
Registriert: Sonntag 21. Oktober 2012, 17:20

Hier das ganze mal etwas aufgeräumt:

Code: Alles auswählen

# -*- coding: cp1252 -*-
import Tkinter as tk
import time

from luma.led_matrix.device import max7219
from luma.core.interface.serial import spi, noop
from luma.core.virtual import viewport, sevensegment

class StopWatch(tk.Frame):      
    """ Implements a stop watch frame widget. """                                                                
    def __init__(self, parent=None):        
        tk.Frame.__init__(self, parent)
        self._start = 0.0        
        self._elapsedtime = 0.0
        self._timer = None
        self.timestr = tk.StringVar()               
        l = tk.Label(self, textvariable=self.timestr)
        l.config(fg='Red', font=('Arial',100))
        l.pack(fill=tk.X, expand=tk.NO, pady=2, padx=2)                      
        self._update_time()
    
    def _update(self): 
        """ Update the label with elapsed time. """
        self._elapsedtime = time.time() - self._start
        self._update_time()
        self._timer = self.after(50, self._update)
    
    def _update_time(self):
        """ Set the time string to Minutes:Seconds:Hundreths """
        minutes, seconds = divmod(self._elapsedtime, 60)
        self.timestr.set('%02d:%02.0f' % (minutes, seconds))
        
    def start(self):                                                     
        """ Start the stopwatch, ignore if running. """
        if self._timer is None:
            self._start = time.time() - self._elapsedtime
            self._update()
    
    def stop(self):                                    
        """ Stop the stopwatch, ignore if stopped. """
        if self._timer is not None:
            self.after_cancel(self._timer)
            self._timer = None

    def halbzeit(self):                                    
        """ Stop the stopwatch, ignore if stopped. """
        self.stop()       
        self._elapsedtime = 2700.00  
        self._update_time()
    
    def reset(self):                                  
        """ Reset the stopwatch. """
        self.stop()
        self._elapsedtime = 0.0    
        self._update_time()


class Counter(tk.Frame):
    def __init__(self, parent=None, text='Heim'):        
        tk.Frame.__init__(self, parent)
        self.counter = 0
        self.counter_label = tk.Label(self, font="Arial 100 bold", fg="RED")
        self.counter_label.pack()
        tk.Button(self, font=('Arial',30), width=10, text='%s +' % text, command=self.count_up).pack()
        tk.Button(self, font=('Arial',30), width=10, text='%s -' % text, command=self.count_down).pack()
        self._update_counter()

    def _update_counter(self):
        self.counter_label['text'] = str(self.counter)
        
    def count_up(self):
        self.counter += 1
        if self.counter > 99:
            self.counter = 0
        self._update_counter()

    def count_down(self):
        self.counter -= 1
        if self.counter < 0:
            self.counter = 0
        self._update_counter()

        
def main():
    root = tk.Tk()
    # w, h = root.winfo_screenwidth(), root.winfo_screenheight()
    # root.geometry("%dx%d+0+0" % (w, h))
    root.geometry('1000x1000') 
    stopwatch = StopWatch(root)
    stopwatch.pack(side=tk.TOP)
    counterhome = Counter(root, "Heim")
    counterhome.place(x=200, y=300)
    counteraway = Counter(root, "Auswaerts")
    counteraway.place(x=450, y=300)
    
    tk.Button(root, width=7, font=('Arial',30), text='Start', command=stopwatch.start).place(x=50, y=200)
    tk.Button(root, width=7, font=('Arial',30), text='Stop', command=stopwatch.stop).place(x=300, y=200)
    tk.Button(root, width=7, font=('Arial',30), text='Halbzeit', command=stopwatch.halbzeit).place(x=800, y=200)  
    tk.Button(root, width=7, font=('Arial',30), text='Reset', command=stopwatch.reset).place(x=550, y=200)
    tk.Button(root, width=10, font=('Arial',30), text='Quit', command=root.destroy).place(x=10, y=10)

    root.mainloop()

if __name__ == '__main__':
    main()
An der Stelle mit "hier..." bringen Dir die Werte ja gar nichts, weil Du jedesmal, wenn sich die Labels ändern auch die LED-Matrix ändern muß. Du mußt also die LED dann ändern, wenn Du auch die Labels ändern würdest. Am besten schreibst Du dafür eine eigene Klasse, deren Exemplar an Stopwatch und Counter übergeben wird.
Antworten