首页 > 解决方案 > 如何使用 for 循环在 tkinter 中用空白帧填充屏幕设计的其余部分?

问题描述

我正在尝试制作一个受购物启发的自动售货机 UI。目标是使用 for 循环和 2D 列表用框架填充我的框架,然后将按钮和标签打包到上面。代码如下:

    frames = []
    frame_order = []
    num = 0

    for x in range(5):
        frames.append([])
        for y in range(5):
            frames[x].append(5)

    for x in range(5):
        for y in range(5):
            frames[x][y] = Frame(store_canvas, width=1520 / 5, height=1030 / 5, bd = 2, relief = SOLID)
            frames[x][y].grid(row=y, column=x)
            frames[x][y].pack_propagate(False)
            frame_order.append(frames[x][y])

这将重新运行一个 SQL 查询数据库,该数据库将返回一个项目列表作为list[].然后填充 2D 内的框架list

retrieve_tiem() 

我还在有其他过滤器的一侧设置了另一个框架。问题是,如果过滤器查询 SQL 并返回item list小于网格大小(5x5,总共 25 个项目),那么for循环将不会运行,因为它无法填充。为避免这种情况,我尝试使用TryExcept但循环只会用按钮填充剩余空间。

for frame in frame_order:
    try:
        Button(frame, anchor='nw', height = 9, width = 35, font = 20).pack()
        Label(frame, text=str(Item_list[num]), anchor='nw', font = 20, width = 35, bg = 'darkgreen', fg = 'yellow' ).pack()
        num += 1
    except:
        pass

有没有办法避免这种情况?就像在项目列表用完项目或填充列表的其余部分'*blank*'直到列表达到框架可以容纳的项目总量时不创建按钮?如果可行,我也对其他方法持开放态度。感谢所有答案,请放轻松,因为我仍在学习 python 和 SQL :)

标签: pythonsqlitetkinter

解决方案


您实际上可以使用一维列表而不是二维列表。以下是基于您的代码的示例:

from tkinter import *
import random

root = Tk()

store_canvas = Frame(root)
store_canvas.pack()

# create the 25 frames
ROWS = COLS = 5
MAX_ITEMS = ROWS * COLS
frames = []
for i in range(MAX_ITEMS):
    frames.append(Frame(store_canvas, width=1520/COLS, height=1030/ROWS, bd=2, relief=SOLID))
    frames[-1].grid(row=i//COLS, column=i%COLS)
    frames[-1].pack_propagate(False)

# function to simulate retrieving data from database table
def retrieve_tiem():
    return [f"Item #{i+1}" for i in range(random.randint(1,MAX_ITEMS))]

# function to show the retrieved items
def update_list():
    Item_list = retrieve_tiem()
    label_font = ("Arial", 20)
    for i, frame in enumerate(frames):
        for w in frame.winfo_children():
            w.destroy()
        if i < len(Item_list):
            item = Item_list[i]
            Button(frame).pack(fill="both", expand=1)
            Label(frame, text=item, font=label_font, bg="darkgreen", fg="yellow").pack(fill="x")

update_list()
root.bind("<F5>", lambda e: update_list())
root.mainloop()

推荐阅读