首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在Python3/Tkinter中创建随机大小正方形的对称网格

在Python3/Tkinter中创建随机大小正方形的对称网格
EN

Stack Overflow用户
提问于 2018-07-28 05:19:14
回答 2查看 739关注 0票数 0

我有一个问题,围绕着在tkinter-canvas上的对称不可见网格上放置随机大小的正方形的可行方法。我将非常彻底地解释它,因为这是一个专有的问题。

到目前为止,我主要是尝试用数学方法来解决这个问题。但我发现这是一个相当复杂的问题,而且似乎有一种比我尝试过的更好的方法来解决它。

在其最基本的形式中,代码如下所示:

代码语言:javascript
复制
while x_len > canvas_width:
                xpos = x_len + margin
                squares[i].place(x=xpos, y=ypos)
                x_len += square_size + space
                i += 1

x_len是给定行上所有正方形的总宽度,并在退出while循环时重置(例如,当x_len > window width时),其中包含xpos (X上的位置),以及改变Y轴以创建新行。

当放置相同大小的方块时,它看起来像这样:

到目前一切尚好。

然而,当正方形是随机大小时,它看起来像这样(最好):

核心问题,除此之外,布局可能是相当不可预测的,是正方形没有居中到“看不见的网格”-因为没有。

因此,为了解决这个问题,我尝试了一种方法,其中我使用固定距离和基于每个给定方块的相对距离。这会在第一行的Y轴上产生令人满意的结果,但不会在X轴上产生满意的结果,也不会在Y上产生令人满意的结果。

请参见示例(其中第一行在Y上居中,但后面的行在Y上居中,而X不在Y上):

所以在这个方法中,我在Y轴和X轴上都使用了每平方的改变,基于我从一个包含所有生成的正方形宽度的列表中获取的变量。

总的来说,它看起来像这样(尽管它还在开发中,所以没有得到很好的优化):

代码语言:javascript
复制
square_widths = [60, 75, 75, 45...]

space = square_size*0.5
margin = (square_size+space)/2
xmax = frame_width - margin - square_size
xmin = -1 + margin

def iterate(ypos, xpos, x_len):
    y = ypos
    x = xpos
    z = x_len
    i=0
    m_ypos = 0
    extra_x = 0

    while len(squares) <= 100:
        n=-1
        # row_ypos alters y for every new row
        row_ypos += 200-square_widths[n]/2

        # this if-statement is not relevant to the question
        if x < 0:
            n=0
            xpos = x
            extra_x = x
            x_len = z
            while x_len < xmax:
                ypos = row_ypos
                extra_x += 100
                ypos = row_ypos + (200-square_widths[n])/2
                xpos = extra_x + (200-square_widths[n])/2
                squares[i].place(x=xpos, y=ypos)
                x_len = extra_x + 200
                i += 1
                n += 1

这里最相关的是row_ypos,它改变每一行的Y,以及ypos,它改变每个正方形的Y(我还没有关于X的有效计算)。我想要实现的是在第一行的Y轴上得到类似的结果;在所有的行和列上(例如,X和Y)。创建具有不同大小的正方形的对称网格。

所以我的问题是:这真的是解决这个问题的最佳实践吗?如果是这样的话--你有什么好的计算技巧吗?如果不是,你会怎么做呢?

附带说明的是,它必须“手动”完成,我不能使用tkinter的内置函数来解决它。

EN

回答 2

Stack Overflow用户

发布于 2018-07-28 06:28:09

为什么不直接使用grid几何管理器呢?

代码语言:javascript
复制
COLUMNS = 5
ROWS = 5

for i in range(COLUMNS*ROWS):
    row, col = divmod(i, COLUMNS)
    l = tk.Label(self, text=i, font=('', randint(10,50)))
    l.grid(row=row, column=col)

这将使所有内容排列在一起,但随机性可能会使行和列的大小不同。您可以使用row- and can columnconfigure函数对其进行调整:

代码语言:javascript
复制
import tkinter as tk
from random import randint

COLUMNS = 10
ROWS = 5
class GUI(tk.Frame):
    def __init__(self, master=None, **kwargs):
        tk.Frame.__init__(self, master, **kwargs)

        labels = []
        for i in range(COLUMNS*ROWS):
            row, col = divmod(i, COLUMNS)
            l = tk.Label(self, text=i, font=('', randint(10,50)))
            l.grid(row=row, column=col)
            labels.append(l)

        self.update() # draw everything
        max_width = max(w.winfo_width() for w in labels)
        max_height = max(w.winfo_height() for w in labels)
        for column in range(self.grid_size()[0]):
            self.columnconfigure(col, minsize=max_width) # set all columns to the max width
        for row in range(self.grid_size()[1]):
            self.rowconfigure(row, minsize=max_height) # set all rows to the max height

def main():
    root = tk.Tk()
    win = GUI(root)
    win.pack()
    root.mainloop()

if __name__ == "__main__":
    main()
票数 1
EN

Stack Overflow用户

发布于 2018-07-28 09:32:12

我找到了导致结果不符合预期的罪魁祸首,这不是由于计算。相反,事实证明我创建的列表没有将方块按正确的顺序排列(这一点我在前面就应该知道了)。

因此,我从原始数据本身获取宽度,这比创建列表更有意义。

这个函数现在看起来像这样(同样,它还在改进中,但我只是想发布这篇文章,这样人们就不会浪费时间去想出一个已经解决的问题的解决方案:):

代码语言:javascript
复制
def iterate(ypos, xpos, x_len):
    y = ypos
    x = xpos
    z = x_len
    i=0

    while len(squares) <= 100:
        n=0
        if y > 1:
            ypos -= max1 + 10
        if y < 0:
            if ypos < 0:
                ypos=10
            else:
                ypos += max1 + 10 #+ (max1-min1)/2

        if x < 0:
            n=0
            xc=0
            xpos = x
            x_len = z

            while x_len < xmax:
                yc = ypos + (max1-squares[i].winfo_width())/2
                if xpos <= 0:
                    xpos = 10
                else:
                    xpos += max1 + 10
                xc = xpos + (max1-squares[i].winfo_width())/2
                squares[i].place(x=xc, y=yc)
                x_len += max1 + 10
                print (x_len)
                i += 1
                n += 1
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51565707

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档