Search code examples
python-3.xsqlitefor-looptreeviewttk

How to identify the name of sqlite database table which ttk.Treeview loads data from?


I have a tkinter application written in python3. It has one main tk.Frame. Using for loop I build there two ttk.LabelFrames, then each frame gets its ttk.Treeview. Each of those treeviews loads its data from different table (named aliens1 and aliens2):

class Application:
    def __init__(self, master):
        self.master = master
        
        self.database = Database(self.master, self)
        self.turns_frame = TurnsFrame(self.master, self)

class TurnsFrame:
    def __init__(self, master, app):
        self.master = master
        self.app = app
        self.frame = tk.Frame(self.master, bd=2)
        
        # Create LabelFrames and their Treeviews
        for i in range(3):
            ap_frame = tk.LabelFrame(self.frame, text="Alien Player {}".format(str(i+1)))
            ap_frame.grid(row=0, column=i)

            tv = tk.ttk.Treeview(ap_frame,
                                 columns=tuple(range(1, 12)),
                                 show="headings",
                                 height=30)
            tv.pack()

            ... creating columns ...

            # Create rows
            with self.app.database.db:
                self.app.database.cursor.execute("SELECT turn, econ_rolls, econ_rolls_extra, cp_fleet, "
                                             "cp_tech, cp_def, fleet_launch, roll_econ, roll_fleet, "
                                             "roll_tech, roll_def FROM aliens{}".format(str(i+1)))
                rows = self.app.database.cursor.fetchall()

                for r in rows:
                    tv.insert("", "end", values=r)

            # Bind row double-click
            tv.bind("<Double-1>", self.get_turn_number)

    def get_turn_number(self, event):
        item_id = event.widget.focus()
        item = event.widget.item(item_id)
        values = item["values"]
        turn_id = values[0]

        print("Turn: ", turn_id)
        return turn_id

class Database:
    def __init__(self, master, app):
        self.master = master
        self.app = app
        self.folder = os.path.dirname(os.path.abspath(__file__))

        self.db = self.create_connection(self.folder)
        self.cursor = self.db.cursor()

    def create_connection(self, f):
        db = None
        try:
            db = sqlite3.connect(os.path.join(f, "aliens.db"))
        except sqlite3.Error as e:
            print(e)

        return db

    def initialize_tables(self, nr):
    # SOME OTHER FRAME CALLS THIS FUNCTION AND GIVES THE VARIABLE 'nr'
        with self.db:
            for i in range(1, nr+1):
                # print("Creating table aliens{}".format(str(i)))
                self.cursor.execute("CREATE TABLE aliens{}(".format(i) +
                                    "turn INTEGER PRIMARY KEY,"
                                    "econ_rolls INTEGER,"
                                    "econ_rolls_extra INTEGER,"
                                    "cp_fleet INTEGER,"
                                    "cp_tech INTEGER,"
                                    "cp_def INTEGER,"
                                    "fleet_launch STRING,"
                                    "roll_econ STRING,"
                                    "roll_fleet STRING,"
                                    "roll_tech STRING,"
                                    "roll_def STRING)")

def main():
    root = tk.Tk()
    main_app = Application(root)
    root.mainloop()

if __name__ == "__main__":
    main()

It looks fine and is working fine, looks like this application.

Now I can double-click on any row and it executes self.get_turn_number. Great. For further work I need to get the database table name which it loads its rows from (depending on which treeview I double-clicked - first one Alien player 1 or the second one Alien player 2). Alien player 1 loads its data from table alien1 and player 2 from aliens2.

I searched the documentation but found nothing regarding this stuck in ttk.Treeview. It also seems that no one had had this problem before. Is there a way to accomplish this?


Solution

  • Well I just noticed the for loop you are on. What you could do is pass the number on to the function and then run it out, like:

    .... # Same code
        tv.bind("<Double-1>", lambda e,num=i: self.calculate_econ_phase(num)
    
    def calculate_econ_phase(self,num):
        print(f'Alien{num}')
    

    Posting as answer because too long for comments.