2017-07-02 31 views
2

我想在tkinter中使用网格方法来显示我在数据库中的一些数据。当我定义__init__方法时,我必须设置特定数量的行,它们彼此相似。但是,由于行的值将来自数据库,因此我无法准确定义我需要的行数。tkinter网格中的行

到目前为止,我唯一的解决方案是在__init__方法中设置最大行数,我可以控制该方法。但是这个解决方案并没有显示屏幕上的所有信息。任何帮助将受到欢迎。

#!/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() 
+0

你在喜欢你的'__init__'获得DB数据在这里做过? – TrakJohnson

+1

你是否真的需要保持对所有这些标签的引用?如果是这样,你应该将它们保存在某种集合中,例如列表的列表中,而不是为每个标签赋予一个单独的名称。 –

+1

我认为@PM2Ring为创建显示的每一行和列的属性(比如'self.r1c0','self.r1c1'等)提供了一个很好的观点。如果代码的其他部分会变得多少,那么代码的其余部分如何知道它们是什么?在博客文章中提醒我一些建议[** _将数据保留在变量名称_ **之外](https://nedbatchelder.com/blog/201112/keep_data_out_of_your_variable_names.html)。 – martineau

回答

1

内置enumerate功能让您遍历序列,并同时获得序列项和顺序索引号。默认情况下,索引从零开始,但您可以提供备用的起始索引。

为了使代码更易于阅读,我已将标签创建和打包代码放入单独的方法中。

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() 
+0

谢谢。这就是我一直在寻找的东西。现在我必须执行它。谢谢 – ogeretal

1

显示在GUI tkinter可变数目的东西通常用Scrollbar,其可附接至ListboxCanvasText,或Entry窗口小部件来处理。在这种情况下,Listbox似乎是适当所以这里是使用它的一个例子:

__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() 

这是什么样子:

screenshot of listbox

+0

谢谢,我没有想到滚动条,因为它只显示一定数量的行。但它表明我有一条路要走。 – ogeretal