为什么我的卡片图像的下半部分在 tkinter 中被切断?

问题描述 投票:0回答:1

我正在编写纸牌游戏 Dominion 的数字版本,以便与一些朋友一起玩。这只是我第二次使用 tkinter 进行窗口管理,总体来说我对 python 不是很熟练。无论如何:

程序目前如下所示:

A hand of cards all in a line in a scroll-enabled labelframe, with the bottom half of each card cut off

我最困惑的是,为什么画布内滚动框架中的卡片(可能)导致框架的可见部分根据需要拉伸到屏幕的两端,但不是使整个整体拉伸得足够高,以使卡片文本可见。我也很困惑为什么标签框和它们应该包装的边框之间存在间隙(例如手部区域下方的绿色线令人困惑),但我不知道这个问题是否相关。

我的代码变得越来越混乱,因为我尝试了在线教程中的各种方法来修复它,对此我深表歉意。现在是这样:

from tkinter import *
from PIL import Image, ImageTk

from pathlib import Path
filedirectory = Path.cwd() #sets filedirectory to the current program's location


##Image handling
def ResizeImage(image,new_size=(300,500)):
    tempImage=Image.open(image)
    card=tempImage.resize(new_size)  #Don't re-use variable for somereason, and do in extra lines?  Test later.
    return card #should probably do PhotoImage conversion here



##Window Management
root=Tk() #create a window
root.title("Frederick's Custom Dominion Game") #set the title of the window, which is displayed on window bar among other places.
icon = filedirectory.joinpath('img/icon.ico') #uses relative pathing to get the icon file

root.iconbitmap(icon) #sets the icon to the desired image I made

root.geometry("1800x1000") #set window size
root.configure(background="green") #like windows solitaire

frame = Frame(root,bg="green") #Creates a frame, which is a graphic that's generally designed to be identical to the background of the window and the same size as it for some reason.
frame.pack(side=BOTTOM, fill=BOTH,expand=1) 

midframe=Frame(frame,bg="green") #use so we can pack the other way with the play and discard

player_hand=LabelFrame(frame,text='Hand',height=520,width=1520) #set up three labelFrames (which just draw a square and put a text label in the corner, but look nice)
play_area=LabelFrame(midframe,text='Play',height=520,width=1520) #height and width don't do anything without pack_propagate(0), but that's okay because we shouldn't be using them
discard=LabelFrame(midframe,text='discard',height=520,width=320)


player_hand.pack(side=BOTTOM,fill=X,expand=1) #This should be putting the hand across the entire bottom of the screen, but it's not
player_hand.update() #didn't work, didn't hurt

midframe.pack(side=BOTTOM,fill=BOTH,expand=1)
play_area.pack(side=LEFT,fill=X,expand=1)
discard.pack(side=RIGHT,expand=1)

scroll_bar = Scrollbar(player_hand,orient=HORIZONTAL) #place next to, not in, canvas.  Linking is via configure *on both*

scroll_field=Canvas(player_hand,xscrollcommand=scroll_bar.set,highlightthickness=0)
scroll_field.config(scrollregion=scroll_field.bbox('all')) #bbox=bounding box, target self not inset Frame
scroll_bar.configure(orient=HORIZONTAL, command=scroll_field.xview) #target Canvas, not Frame

inside_frame=Frame(scroll_field, bg='blue') #this should grow to fit its contents, but it doesn't.  Can't pack it, because that breaks scrolling.


###scroll code?

def updateScrollRegion():
    scroll_field.update_idletasks()
    scroll_field.config(scrollregion=scroll_field.bbox('all'))
    root.update()

scroll_bar.pack( side = BOTTOM, fill = X,expand=1 )
scroll_field.create_window(0, 0, window=inside_frame, anchor=NW)
scroll_field.pack(fill=BOTH,side=LEFT,expand=TRUE) #Fill set to BOTH but still not growing vertically


root.after(1000,updateScrollRegion)

###
#deck logic
FuckGarbageCollection=[] #Why the heck are graphics garbage collected while still used in a Label?
flist = []
for f in Path(filedirectory.joinpath('img/Cards')).iterdir():
    if f.is_file():
        print(f)
        flist.append(f)

class Card:
    def __init__(self,file):
        self.image=file
        print(file)
        FuckGarbageCollection.append(ImageTk.PhotoImage(ResizeImage(file))) #should move image processing from here to top of file
        self.label=Label(inside_frame,image=FuckGarbageCollection[-1])
        print("image complete")

AllCards=[]
for i in flist:
   AllCards.append(Card(i))

for i in AllCards[:15]:
    i.label.pack(side=LEFT,expand=1,fill=Y) #Does put cards in the box.  Doesn't make the box fit.
root.update()
scroll_field.configure(scrollregion = scroll_field.bbox("all"))
updateScrollRegion()





def logic():
    root.update()
    player_hand.update()
    scroll_field.update()
    inside_frame.update()
    updateScrollRegion()
    root.after(1000,logic)
    for i in inside_frame.children.values():  #no dice
        i.update() 





root.after(1000,logic)
root.mainloop()# spin forever?

我知道当我将整个卡牌列表(AllCards 而不是 AllCards[:15])放入手中时,我已经达到了坐标限制,但即使没有这个问题仍然存在。

我尝试过在 root.mainloop() 之前或通过 after() 在 root.mainloop() 中更新各种内容。我尝试过明确地告诉不同的事情来填充各个方向或两个方向的空间。我尝试通过禁用包传播来明确强制 Labelframes 具有正确的大小,其工作原理是它会更改它们的大小以填充我想要的任何内容,但仍然在奇怪的位置和带有它们的内容(例如卡片图像和滚动条)卡片图像被切断并显示额外的灰色背景。强制大小似乎也是一种不好的学习习惯,所以我宁愿避免它,尽管我可以暂时使我的计算机/显示器上的一切正常工作,专门通过 place() (或者可能只是传播禁用,但在这一点上我只使用 place())。

我尝试阅读 github 上的一些 tkinter 文件,但它基本上超出了我的技能水平,所以我非常确定没有明显的答案/语法错误/缺少参数,但我不会感到惊讶学习其他方式。

我期望的是小部件会扩展以适合其内容,因此卡片应该全部显示,以达到屏幕/窗口大小和坐标限制的限制。

python tkinter python-imaging-library scrollbar tkinter-canvas
1个回答
0
投票

您没有指定画布的高度,因此默认高度小于这些卡片的高度。

请注意,使用

.create_window()
将小部件放入画布不会影响画布的大小。

因此将画布的高度指定为 500 将解决该问题:

scroll_field=Canvas(player_hand,xscrollcommand=scroll_bar.set,highlightthickness=0,height=500)
© www.soinside.com 2019 - 2024. All rights reserved.