0

I am experimenting with creating a customer relationship management program using tkinter and python and would like to have buttons generated based on tables in the database.

The idea is that there is a button for each table in the database, so that the table can be viewed and edited if needed.

I want to have each button look the same and, when clicked, generate a list of table entries into the main frame of my program. To do this, I want to extend the Button() class so that I can keep some attributes concurrent while also defining the display_items function:

class TabButton(Button):

    def __init__(self, *args, **kwargs):
        super().__init__(Button)
        self['bg'] = '#a1a1a1'
        self['font'] = ('Agency', 24)

    def display_items(self, tab):
        pass
        #mycursor.execute('SELECT * FROM (%s)', tab)

This last line (above) is what selects data from the correct table in my database - I have commented it out while I figure out the rest of the class. I know what *args and **kwargs do, but I'm not sure what purpose they have in this __init__ function (I'm not very familiar with classes and copied this class from another Stack Overflow post).

To generate the buttons, I referenced a dict instance and assigned each key to a button:

tabs = {
    'Table1': '',
    'Table2': '',
    'Table3': '',
}

for tab in tabs:
    row = 0
    tabs[tab] = TabButton(side_frame, command=lambda: TabButton.display_items(tab))
    tabs[tab].grid(row=row, column=0)
    row += 1

The problem is, when I run the program I get this error:

AttributeError: type object 'Button' has no attribute 'tk'

Any and all guidance is welcome!

If you notice any other mistakes in my code, could you please point them out? I'm very new to programming and it will save me making another post on Stack Overflow. :p

Thanks, J

  • Does this answer your question? [super() in tkinter application](https://stackoverflow.com/questions/56845491/super-in-tkinter-application) – Thingamabobs Nov 23 '21 at 20:18
  • Hello @Thingamabobs , I think I've corrected the super() to super()__init__(Button), but I am now getting the new error: AttributeError: type object 'Button' has no attribute 'tk'. I definitely require a deeper understanding of what's going on here. – Jordan Regan Nov 23 '21 at 20:35
  • `super().__init__(master)` master equals side_frame. So for a minimun on changes you need to do `super().__init__(*args)` but rather do a positional argument in your init method, like: `def __init__(self,master, *args, **kwargs)` – Thingamabobs Nov 23 '21 at 20:41
  • Hey thanks but doesn't super() not require 'self' to be passed? I can run the code with super().__init__(side_frame) but the result is a little messy in the GUI. Where am I going wrong? – Jordan Regan Nov 23 '21 at 20:46
  • See my answer and let me know if there are questions to this topic. – Thingamabobs Nov 23 '21 at 21:15
  • Use `super().__init__(*args, **kwargs)` instead. – acw1668 Nov 24 '21 at 00:37

1 Answers1

0

Super returns a temporary object of that class and let you access its content. Super itself dosent accept any arguments. Also see the prupose of self in that context.

self represents the instance of the class

Often, the first argument of a method is called self. This is nothing more than a convention: the name self has absolutely no special meaning to Python. Note, however, that by not following the convention your code may be less readable to other Python programmers

Another issue is your use of lambda. Your argument tab will be overwritten (if it isnt stored) by each iteration of your loop. Another issue that you might not intent to use the class for this method you rather want to be calles by the instance, therefor I added the argument self to your method and changed your lambda to make use of the instance.

import tkinter as tk
tabs = {'Table1': '', 
        'Table2': '',
        'Table3': '',
        }

root=tk.Tk()

class TabButton(tk.Button):
    def __init__(self,master, *args, **kwargs):
        #self is a reference to the instance of that object
        super().__init__(master)#super dosent need a reference
        self['bg'] = kwargs.get('bg','#a1a1a1')
        self['font'] = kwargs.get('font',('Agency', 24))
    def display_items(self,item):
        print(f'{item} to show')
for tab in tabs:
    b = TabButton(root) #returns a reference to that object
    b.configure(command=lambda btn=b, argument=tab:btn.display_items(argument))
    b.pack()

root.mainloop()
Thingamabobs
  • 7,274
  • 5
  • 21
  • 54