Reputation: 521
I want to use the grid method in tkinter
to show some data I have in a database. When I define the __init__
method I have to set up a specific number of rows, which are similar to each other. But, as the value of the rows will be taken from a database, I can not define precisely the number of rows I will need.
Until now, my only solution is too set a maximum number of rows in the __init__
method, which I can control. But this solution does not show all the information on the screen. Any help will be welcome.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#------------------------------------------------------------
__title__= 'Control'
__date__ = '02/07/2017'
__version__ = '0.0.1'
from tkinter import *
from tkinter import ttk
class Panel():
def __init__(self):
self.root = Tk()
self.root. title('Control V' + __version__)
self.root.geometry('500x400')
self.root.configure(bg='beige')
self.root.minsize(400,300)
self.window = ttk.Frame(self.root, borderwidth=2, relief="raised",
padding=(10,10) )
self.window.grid(column=0, row=0)
self.window.option_add("*Font", "Helvetica 12")
# Row 0
self.r0c0 = ttk.Label(self.window, text="Header", padding=(1,1))
self.r0c0.grid(row=0, column=0, columnspan=3)
# Row 1
counter = 1
# From db : o = {'Name': 'Zara', 'Age': 7, 'Class': 'First'}
o = {'Name': 'Zara', 'Age': 7, 'Class': 'First'}
self.r1c0 = ttk.Label(self.window, text=o['Name'], padding=(1,1))
self.r1c0.grid(row=1, column=0)
self.r1c1 = ttk.Label(self.window, text=o['Age'], padding=(1,1))
self.r1c1.grid(row=1, column=1)
self.r1c2 = ttk.Label(self.window, text=o['Class'], padding=(1,1))
self.r1c2.grid(row=1, column=2)
# Row 2, Row 3, ... All are similar to Row 1
counter = 2
# From db : o = {'Name': 'Ezra', 'Age': 5, 'Class': 'First'}
o = {'Name': 'Ezra', 'Age': 5, 'Class': 'First'}
self.r2c0 = ttk.Label(self.window, text=o['Name'], padding=(1,1))
self.r2c0.grid(row=2, column=0)
self.r2c1 = ttk.Label(self.window, text=o['Age'], padding=(1,1))
self.r2c1.grid(row=2, column=1)
self.r2c2 = ttk.Label(self.window, text=o['Class'], padding=(1,1))
self.r2c2.grid(row=2, column=2)
# Row 3, Row 4, ... All are similar to Row 1 & 2.
# Can I make a loop where n is unknown at definition
# All set
self.root.mainloop()
def main():
my_panel = Panel()
return 0
if __name__ == '__main__':
main()
Upvotes: 2
Views: 2307
Reputation: 123393
Displaying a variable number of things in a tkinter
GUI is usually handled with Scrollbar
which can be attached to Listbox
, Canvas
, Text
, or Entry
widgets. In this case a Listbox
seems appropriate so here's an example of using it:
__title__= 'Control'
__date__ = '02/07/2017'
__version__ = '0.0.1'
from itertools import cycle
from tkinter import *
from tkinter import ttk
# Some test data
db = [
{'Name': 'Zara', 'Age': 7, 'Class': 'First'},
{'Name': 'Ezra', 'Age': 5, 'Class': 'First'},
{'Name': 'Bob', 'Age': 8, 'Class': 'Third'},
{'Name': 'Mary', 'Age': 6, 'Class': 'Second'},
]
class Panel():
def __init__(self):
self.root = Tk()
self.root. title('Control V' + __version__)
self.root.geometry('500x400')
self.root.configure(bg='beige')
self.root.minsize(400,300)
self.window = ttk.Frame(self.root, borderwidth=2, relief="raised",
padding=(10,10))
self.window.grid(column=0, row=0)
self.window.option_add("*Font", "Helvetica 12")
self.listbox = Listbox(self.window)
self.listbox.grid(row=0, column=0, sticky=N+E+S+W)
self.scrollbar = Scrollbar(self.window)
self.scrollbar.grid(row=0, column=1, sticky=N+S)
self.listbox.config(yscrollcommand=self.scrollbar.set)
self.scrollbar.config(command=self.listbox.yview)
# Row 0
self.listbox.insert(END, "Header")
# Simulate getting many rows from database by repeating them
endless_data = cycle(db)
for i in range(20):
row = next(endless_data)
line = '{Name:5} {Age:2} {Class}'.format(**row)
self.listbox.insert(END, line)
# All set
self.root.mainloop()
def main():
my_panel = Panel()
if __name__ == '__main__':
main()
This is what it looks like:
Upvotes: 1
Reputation: 55469
The built-in enumerate
function lets you loop over a sequence and get both the sequence item and a sequential index number. By default, the indices start at zero, but you can supply an alternate starting index.
To make the code easier to read, I've put the Label creation and packing code into a separate method.
import tkinter as tk
from tkinter import ttk
class Panel:
def __init__(self, field_names, database):
self.root = tk.Tk()
self.window = ttk.Frame(self.root, borderwidth=2,
relief="raised", padding=(10,10))
self.window.grid()
# Create the header row
for col, field_name in enumerate(field_names):
self.add_field(field_name, 0, col, background='#ccf')
# Create the data rows
for row, record in enumerate(database, 1):
for col, field_name in enumerate(field_names):
self.add_field(record[field_name], row, col)
self.root.mainloop()
def add_field(self, value, row, col, background=''):
label = ttk.Label(self.window, text=value, background=background,
borderwidth=1, relief="raised", padding=(1,1))
label.grid(row=row, column=col, sticky='ew')
def main():
field_names = ('Name', 'Age', 'Class')
database = [
{'Name': 'Zara', 'Age': 7, 'Class': 'First'},
{'Name': 'Ezra', 'Age': 5, 'Class': 'First'},
{'Name': 'Amy', 'Age': 6, 'Class': 'Second'},
{'Name': 'David', 'Age': 10, 'Class': 'Third'},
]
my_panel = Panel(field_names, database)
if __name__ == '__main__':
main()
Upvotes: 1