简体   繁体   中英

How Do I Make Python Tkinter Widgets Created in a Loop Independant?

I've tried putting the widgets into lists via appending with no luck. I created everything in a for-loop, but I want each month's listbox to have it's own scrollbar. Currently only the last listbox works correctly and moving other months scrollbars moves the listbox for December.

Eventually each day with be clickable and open another window for adding daily transactions.

在此处输入图像描述

    mainFrame = tk.Frame(tkRoot)
    mainFrame.config(bd=2, relief='groove')
    mainFrame.grid(row=0, column=0, padx=60)

    trxLabel = tk.Label(mainFrame, text='Transactions ' + str(year), font='courierNew 20 bold')
    trxLabel.grid(row=0, columnspan=12, pady=(20, 0))

    # Hold each month frame
    self.monthFrame = []
    self.dayList = []
    self.endBalList = []
    self.vScroll = []

    for i in range(12):
        monthLabel = tk.Label(mainFrame, text=month[i][0], font='courierNew 12 bold')
        monthLabel.grid(row=1, column=i, pady=(20, 0))

        self.monthFrame.append(tk.Frame(mainFrame))
        self.monthFrame[i].config(bd=2, relief='groove')
        self.monthFrame[i].grid(row=2, column=i, sticky=tk.W)

        self.dayList.append(tk.Listbox(self.monthFrame[i], width=3))
        self.dayList[i].config(bd=2, relief='sunken')
        self.dayList[i].grid(row=0, column=0, sticky=tk.W)

        self.endBalList.append(tk.Listbox(self.monthFrame[i], width=16))
        self.endBalList[i].config(bd=2, relief='raised', background='LIGHT GRAY')
        self.endBalList[i].grid(row=0, column=1, sticky=tk.W)

        self.vScroll.append(tk.Scrollbar(self.monthFrame[i], orient='vertical'))
        self.vScroll[i].grid(row=0, column=2, sticky=(tk.N, tk.S, tk.E))

        # Insert data
        for j in range(month[i][1]):
            self.dayList[i].insert(tk.END, 1 + j)
            self.endBalList[i].insert(tk.END, '999,999,999.99')

            self.getFrame(idx=i)

def getFrame(self, idx):
    self.dayList[idx].config(yscrollcommand=self.vScroll[idx].set)
    self.endBalList[idx].config(yscrollcommand=self.vScroll[idx].set)
    self.scrollAll(idx)

def scrollAll(self, idx):
    self.dayList[idx].yview(idx)
    self.endBalList[idx].yview(idx)

As the same set of widgets will be repeatedly created, it would be better to embed them in a class:

import tkinter as tk

class BalanceLog(tk.Frame):
    months = [
        ['January', 31],
        ['February', 28],  # Check for leap year
        ['March', 31],
        ['April', 30],
        ['May', 31],
        ['June', 30],
        ['July', 31],
        ['August', 31],
        ['September', 30],
        ['October', 31],
        ['November', 30],
        ['December', 31]
    ]
    def __init__(self, parent, month):
        super().__init__(parent)

        tk.Label(self, text=self.months[month-1][0], font='CourierNew 12 bold').grid(row=0, column=0, columnspan=3)
        tk.Label(self, text='Day', bd=1, relief='raised').grid(row=1, column=0, sticky='ew')
        tk.Label(self, text='Ending Balance', bd=1, relief='raised', anchor='e').grid(row=1, column=1, sticky='ew')

        sb = tk.Scrollbar(self, orient='vertical', command=self.on_scroll)
        sb.grid(row=2, column=2, sticky='ns')

        self.day_list = tk.Listbox(self, width=3, activestyle='none', exportselection=0, yscrollcommand=sb.set)
        self.day_list.grid(row=2, column=0, sticky='ew')
        self.day_list.bind('<<ListboxSelect>>', self.on_select)

        self.balance_list = tk.Listbox(self, width=16, activestyle='none', exportselection=0, justify='right', yscrollcommand=sb.set)
        self.balance_list.grid(row=2, column=1, sticky='ew')
        self.balance_list.bind('<<ListboxSelect>>', self.on_select)

        # fill the listboxes
        for day in range(1, self.months[month-1][1]+1):
            self.day_list.insert('end', day)
            self.balance_list.insert('end', str(day)+',999,999.99')

    def on_scroll(self, *args):
        self.day_list.yview(*args)
        self.balance_list.yview(*args)

    def on_select(self, event):
        selected = event.widget.curselection()[0]
        # update selection of another listbox
        another = self.balance_list if event.widget is self.day_list else self.day_list
        another.selection_clear(0, 'end')
        another.selection_set(selected)
        another.see(selected)

Then create the required items using the class:

root = tk.Tk()
for month in range(1, 13):
    BalanceLog(root, month).pack(side='left')
root.mainloop()

在此处输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM