0

I made a GUI in tkinter and I want the checkbox (there are actually several, the figure is just an example) next to velocity to deactivate both the second value of velocity and the number of steps. To do that I have defined two different methods int he class, double_entry and single_entry. The problem I am facing is it seems I cannot call the attribute entry_c from outside the method single_entry. When I click on any checkbox I got the following error:

    self.entry_c.configure(state='normal')
AttributeError: 'CreateEntry' object has no attribute 'entry_c'

enter image description here

here is how I call the class from the main (importing the file modules as md:

import modules as md
import tkinter as tk

if __name__ == '__main__':

    root = tk.Tk()
    dictionary = md.create_input_dictionary()

    for index, (key, values) in enumerate(dictionary.items()):
        obj = md.CreateEntry(root, values, index)
        if md.arenumbers(values[-2]) and md.arenumbers(values[-1]):
            obj.double_entry()
        elif not md.arenumbers(values[-2]) and md.arenumbers(values[-1]):
            obj.single_entry()
        else:
            pass

    root.mainloop()

and here is the class:

import tkinter as tk


def create_input_dictionary():
    out = {'Header geometry': ['GEOMETRY DATA', 'Min', 'Max'],
           'k1': ['unit_1', 'mm', '25', '25'],
           'k2': ['unit_2', 'mm', '19', '19'],
           'k3': ['unit_3', '0']
           }
    return out


def arefloats(*numbers):
    try:
        return all(arefloats(*n) if isinstance(n, list) else [float(n)]
                   for n in numbers)
    except (ValueError, TypeError):
        return False


def areintegers(*numbers):
    try:
        return all(areintegers(*n) if isinstance(n, list) else [int(n)]
                   for n in numbers)
    except (ValueError, TypeError):
        return False


def arenumbers(*numbers):
    return areintegers(*numbers) or arefloats(*numbers)


class CreateEntry(tk.Frame):
    def __init__(self, parent, values, row, bg=None, **kwargs):
        if bg is None:
            bg = parent['bg']
        super().__init__(parent, bg=bg, **kwargs)
        self.parent = parent
        self.values = values
        self.row = row

    def double_entry(self):
        self.nac = tk.IntVar(self.parent)

        self.variable1 = tk.StringVar(self.parent, value=self.values[-2])
        self.variable2 = tk.StringVar(self.parent, value=self.values[-1])

        tk.Checkbutton(self.parent, variable=self.nac, command=lambda: self.naccheck()). \
            grid(row=self.row, column=0, sticky='ns')

        label = self.values[0] + ' (' + self.values[1] + ') '
        tk.Label(self.parent, text=label, padx=10, pady=5). \
            grid(row=self.row, column=1, sticky='nw')

        self.entry_c1 = tk.Entry(self.parent, textvariable=self.variable1, width=10, state='normal')
        self.entry_c1.grid(row=self.row, column=2)

        self.entry_c2 = tk.Entry(self.parent, textvariable=self.variable2, width=10, state='disabled')
        self.entry_c2.grid(row=self.row, column=3)

        self.entry_c1.bind("<KeyRelease>", self._accept)
        self.entry_c2.bind("<KeyRelease>", self._accept)

    def single_entry(self):
        variable = tk.StringVar(self.parent, value=self.values[-1])
        self.variable = variable

        entry_c = tk.Entry(self.parent, textvariable=self.variable, width=10, state='disabled')
        self.entry_c = entry_c
        self.entry_c.grid(row=self.row + 1, column=2, columnspan=2)
        self.entry_c.bind("<KeyRelease>", self._accept)

        tk.Label(self.parent, text='SIMULATION PARAMETERS', padx=10, pady=5).grid(row=self.row, columnspan=4,
                                                                                  sticky='ns')
        tk.Label(self.parent, text=self.values[0], padx=10, pady=5).grid(row=self.row + 1, column=0, columnspan=2,
                                                                         sticky='ns')

    def labels_entry(self):
        tk.Label(self.parent, text=self.values[0], padx=10, pady=5).grid(row=self.row, column=1, sticky='ns')
        tk.Label(self.parent, text=self.values[1], padx=10, pady=5).grid(row=self.row, column=2, sticky='ns')
        tk.Label(self.parent, text=self.values[2], padx=10, pady=5).grid(row=self.row, column=3, sticky='ns')

    def naccheck(self):
        if self.nac.get() == 0:
            self.variable2.set(self.variable1.get())
            self.entry_c2.configure(state='disabled')
            self.variable.set('0')
            self.entry_c.configure(state='disabled')
        else:
            self.entry_c2.configure(state='normal')
            self.entry_c.configure(state='normal')

    def _accept(self, event):
        """Accept value change when a key is released"""
        if self.nac.get() == 0:
            self.values[-1] = self.entry_c1.get()
        else:
            self.values[-1] = self.entry_c2.get()
drSlump
  • 307
  • 4
  • 16
  • Write a getter function for that property. – Wimanicesir Nov 18 '21 at 10:40
  • could you give me an example? – drSlump Nov 18 '21 at 10:41
  • https://stackoverflow.com/questions/2627002/whats-the-pythonic-way-to-use-getters-and-setters – Wimanicesir Nov 18 '21 at 10:42
  • @Wimanicesir could you provide me an example of the coding in my class. I do not get how it works. – drSlump Nov 18 '21 at 11:10
  • You can access `self.entry_c` as long as `single_entry()` is executed. – acw1668 Nov 18 '21 at 11:28
  • I can't figutr it out. If you can give me code example. I'd appreaciate it, thanks – drSlump Nov 18 '21 at 15:26
  • You've left the definition of the class' `_accept()` method out of your code this time. Actually what you need to do is provide a *runnable* [mre]. – martineau Nov 18 '21 at 19:03
  • Your object will only have an `entry_c` value if you have called `single_entry`. For those where you call `double_entry`, there is no `entry_c` value at all. – Tim Roberts Nov 18 '21 at 22:33
  • some example in my code would be useful – drSlump Nov 18 '21 at 22:53
  • what if I give the last instance of single_entry (n. of steps) as input to the class CreateEntry(tk.Frame) (is it possible?) to control directly its attribute? – drSlump Nov 19 '21 at 17:53
  • `self.entry_c` only exists if `single_entry()` has been called — so you can't assume it does anywhere else. You can check whether it's there or not via `if hasattr(self, 'entry_c'): ...then do things'. – martineau Nov 19 '21 at 21:32

0 Answers0