2

I'm doing a large project at the moment to help me learn my first programming language (Python) and I've run into some unknown territory. I am aware that it's generally bad to use global variables and there are better solutions, but I can't figure it out for my situation.

I've made the code below as a simple example of what I want to achieve. What's the best way to do this instead of using the global variable?

Also, are there any general errors I've made in my code below?

Thanks in advance

from tkinter import *

root = Tk()

display_number = 5


class NumberBox():
    def __init__(self):
        global display_number
        self.number_label = Label(root, text=display_number)
        self.number_label.pack()
        self.engine()

    def engine(self):
        self.number_label.config(text=display_number)
        root.after(10, self.engine)


def change_number(operation):
    global display_number
    if operation == "add":
        display_number += 1
    if operation == "subtract":
        display_number -= 1

Button(root, text="Add Class", command=lambda: NumberBox()).pack()
Button(root, text="Number UP", command=lambda: change_number("add")).pack()
Button(root, text="Number DOWN", command=lambda: change_number("subtract")).pack()

for _ in range(5):
    NumberBox()

root.mainloop()
Cryptik
  • 25
  • 3
  • See [here](http://stackoverflow.com/questions/17466561/best-way-to-structure-a-tkinter-application) and [here](http://programmers.stackexchange.com/questions/213935/why-use-classes-when-programming-a-tkinter-gui-in-python) for lots of information and examples. – TigerhawkT3 Jul 31 '15 at 08:55

2 Answers2

1

like this:

from tkinter import *

root = Tk()

class NumberBox():
    display_number = 5
    def __init__(self):
        self.number_label = Label(root, text=self.display_number)
        self.number_label.pack()
        self.engine()

    def engine(self):
        self.number_label.config(text=self.display_number)
        root.after(10, self.engine)


def change_number(operation):
    if operation == "add":
        NumberBox.display_number += 1
    if operation == "subtract":
        NumberBox.display_number -= 1

Button(root, text="Add Class", command=lambda: NumberBox()).pack()
Button(root, text="Number UP", command=lambda: change_number("add")).pack()
Button(root, text="Number DOWN", command=lambda: change_number("subtract")).pack()

for _ in range(5):
    NumberBox()

root.mainloop()

by defining the variable in the class (but outside the __init__ it becomes owned by all instances of the class as a single variable, so changing it in one affects all instances

James Kent
  • 5,763
  • 26
  • 50
1

I made several changes:

  1. Create a new class NumberBoxesList to avoid global variables and make program's logic more visible
  2. Remove root.after method: this method should not be used for updates immediately following user's actions
  3. Use import tkinter as tk : import * is bad practice

Result:

import tkinter as tk

class NumberBox():
    def __init__(self, root,  display_number):
        self.number_label = tk.Label(root, text=display_number)
        self.number_label.pack()

    def changeNumber(self, display_number):
        self.number_label.config(text=display_number)

class NumberBoxesList():    
    def __init__(self, root,  start_number = 5):
        self.number = start_number
        self.root = root
        self.boxes = []
        tk.Button(root, text="Add Class", command= self.addBox).pack()
        tk.Button(root, text="Number UP", command=lambda: self.change_number("add")).pack()
        tk.Button(root, text="Number DOWN", command=lambda: self.change_number("subtract")).pack()

    def addBox(self):
        self.boxes.append(NumberBox(self.root,  self.number))

    def change_number(self,  operation):
        if operation == "add":
            self.number += 1
        if operation == "subtract":
            self.number -= 1
        for box in self.boxes:
            box.changeNumber(self.number)

root = tk.Tk()
boxList = NumberBoxesList(root)

for _ in range(5):
    boxList.addBox()

root.mainloop()
Eric Levieil
  • 3,554
  • 2
  • 13
  • 18