1
\$\begingroup\$

I am using a code similar to the following example to create a table with tkinter using Python 3:

  • Each cell is individually created as a ttk.Label and displayed using .grid(row, column)

  • Some of my values get updated while the program is running with tk.StringVar().set()

  • Each value is unique and has it's own variable name count1 count2

This example seems short, but in my program I have a few more rows being displayed and each row has 2 StringVar() that I need to keep updated. Overall, it's a very large for loop because it has to check if it's in the correct row & column combination (row 1 column 0 or row 2 column 0) before creating a StringVar().

  • Any suggestions on how to reduce the size of my for loop?
  • Are there better ways of creating tables that need a few values consistently updated?

Thank you for your time and Happy Holidays!

import time
import tkinter as tk
import tkinter.ttk as ttk
from threading import Thread

gui = tk.Tk()
gui.geometry('360x270')
gui.configure(bg='white')

style = ttk.Style()
style.theme_create('custom', settings={
    'header.TLabel': {'configure': {
        'background': 'white',
        'foreground': 'dark green',
        'font': 'Times 16 bold',
        'padding': (10, 0)}},
    'TLabel': {'configure': {'background': 'white', 'font': 'Times 12'}},
    'TFrame': {'configure': {'background': 'white'}}})
style.theme_use('custom')

table_frame = ttk.Frame(gui)
table_frame.pack(pady=(36, 0))

values = [('Count', 'Date', 'Time', 'Phrase'),
          ('5', '12/12/10', '03:15', 'blue car'),
          ('13', '09/09/98', '16:20', 'red door')]

total_rows = len(values)
total_columns = len(values[0])

for i in range(total_rows):
    for j in range(total_columns):
        if i == 0:
            label = ttk.Label(table_frame, text=values[i][j], style='header.TLabel')
            label.grid(row=i, column=j)
        elif i == 1:
            if j == 0:
                count1 = tk.StringVar()
                count1.set(values[i][j])
                label = ttk.Label(table_frame, textvariable=count1)
                label.grid(row=i, column=j)
            else:
                label = ttk.Label(table_frame, text=values[i][j])
                label.grid(row=i, column=j)
        elif i == 2:
            if j == 0:
                count2 = tk.StringVar()
                count2.set(values[i][j])
                label = ttk.Label(table_frame, textvariable=count2)
                label.grid(row=i, column=j)
            else:
                label = ttk.Label(table_frame, text=values[i][j])
                label.grid(row=i, column=j)


def increment_count():
    increment_count.status = 'run'

    while increment_count.status == 'run':
        new_minute1 = int(count1.get()) + 1
        count1.set(str(new_minute1))

        new_minute2 = int(count2.get()) - 1
        count2.set(str(new_minute2))

        time.sleep(1)


Thread(target=increment_count).start()

gui.mainloop()
increment_count.status = 'exit'
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

As I suspected, there's already a thing for this - a TreeView. Strongly prefer built-in widgets that get the job done, leaving the construction of individual elements as a last resort if the built-in widget doesn't at all meet your needs.

There's plenty of examples on how to use this as a table, but if I were you I'd start with the reference documentation.

Remove the first row of your values and use it as a dedicated heading, instead. Break your i/j loop into two halves - a heading half, and a body half.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Thanks a lot! I didn't even know you could use TreeView like that, I thought it was just for dropdown menus. \$\endgroup\$ Commented Jan 4, 2021 at 17:19

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.