2

I'm making a barcode generator. I need the input in class GUI to be read by class Barcode so it can print the lines on the canvas.

from tkinter import *
class GUI(Frame):
    def __init__(self, master=None):
    ...
        self.code_input = Entry(master)
        self.code_input.pack()
        self.code = self.code_input.get()
    ...
        self.barcode = Barcode(master, height=250, width=200)
        self.barcode.pack()
        self.barcode.draw()
    ....

class Barcode(Canvas):
    def draw(self):
        self.ean = GUI.code

If I reference directly like the above it says AttributeError: type object 'GUI' has no attribute 'code'

If I do inheritance method (based on https://stackoverflow.com/a/19993844/10618936),class Barcode(Canvas, GUI) it says the same as the previous

If I use setter and getter methods:

class GUI(Frame)
    def __init__(self, master=None):
    ...
        @property
        def code(self):
            return self.__code

        @code.setter
        def code(self, code):
            self.__code = code

then self.ean = GUI.code, it won't run the program and say TypeError: 'property' object is not subscriptable instead

how do I fix this problem? Is the structure of my program really bad? I'm really not good at programming at all... I just want the variable in GUI to be transferred to class Barcode so it can compute and return the result back to GUI to display the barcode

AngryWeeb
  • 65
  • 1
  • 9
  • Update: Now I'm trying out another structure, class Barcode will be gone and its functions moved into class GUI. My marks for the OOP criteria might decrease, but its fine. I just need to get the program running. But I'd still like to know the various ways of using a class' variable in another class, it's more difficult than I expected – AngryWeeb Nov 30 '18 at 09:12
  • `.code` is a member variable, you can't access it without first creating a `GUI` object. (side note: I don't use tkinter) – TrebledJ Nov 30 '18 at 09:13
  • Take a look at my answer [here](https://stackoverflow.com/questions/52592922/retrieving-variable-from-another-class/52594161#52594161) with several simple examples to explain various related concepts. – progmatico Dec 03 '18 at 22:52

2 Answers2

2

You need to create an instance of the GUI, otherwise you are just referencing to the static class for which code is not defined. You could access it like in this example

class A():
    def __init__(self):
        self.code = "A"

class B():
    def __init__(self):
        self.code = "B"
    def foo(self):
        print(self.code + A().code)

b = B()
b.foo() # Outputs "BA"

Otherwise, to access it like an static variable within the class you need to define it inside the class root level

class A():
    code = "C"
    def __init__(self):
        self.code = "A"

class B():
    def __init__(self):
        self.code = "B"
    def foo(self):
        print(self.code + A.code)

b = B()
b.foo() # Outputs "BC"
b-fg
  • 3,959
  • 2
  • 28
  • 44
  • While these code snippets are correct, is think creating a new object every time as in the first and having a static code as in the second are both not the intended behavior. – fhdrsdg Nov 30 '18 at 10:24
  • The OP seemed confused about how to do this in first place, regardless the test case here. I care for the OP to understand the basics first, so she/he can extrapolate them to for the specific case to be solved here. This is a double win for the OP in my opinion. – b-fg Nov 30 '18 at 10:37
  • I understand, but you still did not include the option that seems most logical to me in this case, which is making an instance of class A and passing the reference to that as a parameter to class B. – fhdrsdg Nov 30 '18 at 10:40
  • I do not disagree. There are many ways to pass it, yours is another one. Still my example tackles the exact bug the OP had in the original code. That's all. – b-fg Nov 30 '18 at 10:46
1

You should pass the GUI object to the Barcode class, which at the point you create the Barcode instance is self. If you want the Barcode to be inside the GUI frame, you can also directly use it as the Canvas master.
Another thing to notice is that with the way you have it now, self.code will be and remain an empty string, since you only define it right after you've created the Entry widget, at which point it is empty. You should use get on the Entry at the time you want to do something with the contents at that point.

from tkinter import *

class GUI(Frame):
    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.code_input = Entry(self)
        self.code_input.pack()

        self.barcode = Barcode(self, height=250, width=200)
        self.barcode.pack()

        Button(self, text="Update Barcode", command=self.barcode.draw).pack()


class Barcode(Canvas):
    def __init__(self, master, height, width):
        Canvas.__init__(self, master, height=height, width=width)
        self.master = master
        self.text = self.create_text((100,100))

    def draw(self):
        self.itemconfig(self.text, text=self.master.code_input.get())        

root = Tk()
gui = GUI(root)
gui.pack()
root.mainloop()

For illustration purposes I create a text object on the canvas and update that with the current value of the Entry on a Button click.

fhdrsdg
  • 10,297
  • 2
  • 41
  • 62