简体   繁体   English

如何使用 for 循环在 tkinter 中用空白框填充屏幕设计的 rest?

[英]How do I fill the rest of my screen design with blank frames in tkinter using for loop?

I am trying to make a shopping-inspired vending machine UI.我正在尝试制作一个受购物启发的自动售货机 UI。 The goal is to fill up my frame with frames using for loop and 2D list, then pack on buttons and labels onto it.目标是使用 for 循环和 2D 列表用框架填充我的框架,然后将按钮和标签打包到上面。 Codes are as followed:代码如下:

    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])

This will reun an SQL query database that will return with an item list as a list[] .Then fill up the frames inside the 2D list这将重新运行一个 SQL 查询数据库,该数据库将返回一个作为list[]的项目列表。然后填充 2D list的框架

retrieve_tiem() 

I have also set up another frame on the side that has other filters.我还在有其他过滤器的一侧设置了另一个框架。 the problem is that if the filter query SQL and returns with an item list less than the grid size (5x5, a total of 25 items) then the for loop won't run as it cannot populate.问题是,如果过滤器查询 SQL 并返回一个小于网格大小(5x5,总共 25 个项目)的item list ,那么for循环将不会运行,因为它无法填充。 to avoid this, I tried to use Try and Except but the loop would just fill the remaining space with buttons instead.为避免这种情况,我尝试使用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

Is there a way to avoid this?有没有办法避免这种情况? Like not creating the button when the Item list run out off item or fill the rest of the list with '*blank*' until the list reach the total amount of item that the frame can hold?就像在项目列表用完项目时不创建按钮或用'*blank*'填充列表的 rest 直到列表达到框架可以容纳的项目总数? I am also open to other methods too if it works.如果可行,我也对其他方法持开放态度。 All answer are appreciated, please go easy on me as I am still learning python and SQL:)感谢所有答案,请 go 对我轻松,因为我仍在学习 python 和 SQL :)

The problem is with your try statement.问题在于您的try语句。 Here's an example:这是一个例子:

a = 5
try:
    a += 7
    int("str") #This is just to raise an exception
except:
    pass

After running this code, the value of a will be 12, even though an error occured.运行此代码后, a的值将是 12,即使发生错误。 This is the same thing that is happening in your code.这与您的代码中发生的事情相同。 The line that creates the button is run successfully, but the creating the label raises an exception.创建按钮的行运行成功,但是创建 label 引发异常。 This is why you get buttons in the remaining space.这就是您在剩余空间中获得按钮的原因。 This can be resolved using else .这可以使用else来解决。 If we try this instead:如果我们尝试这样做:

a = 5
try:
    int("str") #This is just to raise an exception
except:
    pass
else:
    a += 7

The a += 7 line will only be run if there is not exception in the try statement, so the value will remain 5. For your code, this will be只有在try语句中没有异常时才会运行a += 7行,因此该值将保持为 5。对于您的代码,这将是

try:
    Item_list[num] #This is what causes the error
except:
    pass
else:
    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

Alternatively, you could have an if statement to check if num is larger than the length of the data returned, but there's not enough information in the question for me to be sure that will work.或者,您可以使用if语句来检查num是否大于返回的数据的长度,但问题中没有足够的信息让我确定这将起作用。

You can actually use 1-D list instead of 2-D list.您实际上可以使用一维列表而不是二维列表。 Below is an example based on your code:以下是基于您的代码的示例:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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