Tkinter - 在 canvas 上使用相对偏移对齐图像

Tkinter - Align images using relative offsett on canvas

我正在创建我自己的 Crazy Eights 版本。该应用程序背后的所有逻辑都很好,但我在将卡片放入 canvas 时遇到了问题。实际上,当我为主 windows/canvas (800x800) 设置特定尺寸时,我的应用程序运行良好。但是,我希望我的应用程序获取设备的屏幕大小 运行 并调整主 window 的大小。我通过添加以下行实现了这一点:

w, h = root.winfo_screenwidth(), root.winfo_screenheight()
root.geometry("%dx%d+0+0" % (w, h))

在此之前一切都很好,但后来我在尝试水平和垂直重新居中(对齐)我的卡片时遇到了一些麻烦。例如:一方面,所有牌都使用绝对偏移量(x,700)放置;其中 x 将增加以给出卡片之间的距离,700 是 y 坐标中的位置。但是只有当 window 大小固定时,使用绝对偏移才有效。因此,我想使用像 rely 和 relx (放置几何)这样的相对偏移,但我不知道该怎么做。在这里,我 post 一张图片让您了解发生了什么以及我想要什么。

这是我的脚本:

import tkinter as tk

class start_gui(tk.Frame):
def __init__(self, parent, *args, **kwargs):
    tk.Frame.__init__(self,parent, *args, **kwargs)
    self.hand = dict()
    # create canvas
    self.w, self.h = parent.winfo_screenwidth(), parent.winfo_screenheight()
    self.canvas = tk.Canvas(parent, width=self.w, height=self.h, background="red")

    self.x = 280
    self.playerHand = self.gethand()
    # display for south
    for Card in playerHand:
        self.hand[(self.canvas.create_image(self.x, 700, image=self.getImage(Card[0], Card[1]), tags='p1'))] = [
            Card[0], Card[1], sel.x, 700]
        self.x += 20
        # print(str(Card.suit))

def gethand(self):
    # here goes some script to get player card hand
    # return a list of lists

def getImage(self, num, suit):
    # return image item

if __name__ == "__main__":
root = tk.Tk()
w, h = root.winfo_screenwidth(), root.winfo_screenheight()
root.geometry("%dx%d+0+0" % (w, h))
start_gui(root)
root.mainloop()

另外,我想创建一个函数,在点击事件后重新居中(对齐)我的卡片。我 post 另一张图片给你一个想法。

从上图中,如果我们点击一​​个方块。所选方块将放置在 canvas 的中间,其他卡片将水平对齐,保持卡片之间的初始 space。如果我们再次点击,就会发生之前的事件,依此类推。

有人可以帮我解决这个问题吗?提前谢谢你。

关于使 window 成为设备屏幕的大小,我建议使用 root 的属性功能使其全屏显示,并扩展 canvas 以填充window.

这看起来像:

root = Tk()
root.attributes("-fullscreen", True) #Makes the window fullscreen.

...

self.canvas = Canvas(self.root, bg="red", highlightthickness=0)
    #Highlight thickness makes the canvas have no border in fullscreen mode.
self.canvas.pack(fill=BOTH, expand=True) #Use pack to make canvas take up full window.

这样做的目的是让您的 canvas 占据整个屏幕。 在调用主循环或使用 root.update() 之后,您可以通过使用 self.canvas.winfo_width()self.canvas.winfo_height() 获得 canvas/window 的完整大小(现在相同)。

现在有了您想要的全屏 canvas,您可以在屏幕宽度正确的位置生成卡片,如前所述。使用一个表示卡片的变量,第二个变量充当每张卡片之间的缓冲区大小,您可以按照

start_pos = screen_width/2 - (buffer_width*card_width)*num_of_cards/2 #Gets first x coord
y_pos = [screen_height-card_height*2, screen_height-card_height]      #makes 2 y coords
for i in range(num_of_cards):
    self.canvas.create_rectangle(start_pos+(i*(card_width+buffer_width)), y_pos[0], start_pos+card_width+buffer_width+(i*(card_width+buffer_width)), y_pos[1], fill = card_colours[i]) #Make list of card colours in order

(抱歉最后一行太长了!)

这只是一小段代码,用于演示您可以使用宽度来创建以中间为中心的卡片的方法,而不管有多少张卡片。您可能需要稍微修改一下才能按照自己的意愿使用它。

希望对您有所帮助,祝您好运!