You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Tkinter中卡片图片下半部分被截断的问题求助

问题解决方法

核心问题分析

  1. 卡片纵向截断: Canvas 未根据内部卡片高度自动调整自身高度,且外层 LabelFrame 未允许纵向扩展。
  2. LabelFrame 边框间隙: LabelFrame 默认带有内边距,导致背景色从间隙透出。

具体修复步骤

1. 移除 LabelFrame 内边距

创建 player_hand 等 LabelFrame 时,添加 padx=0, pady=0 参数,消除边框与内容的间隙:

player_hand = LabelFrame(frame, text='Hand', padx=0, pady=0)
play_area = LabelFrame(midframe, text='Play', padx=0, pady=0)
discard = LabelFrame(midframe, text='discard', padx=0, pady=0)

2. 允许 LabelFrame 纵向扩展

修改 player_hand 的 pack 参数,将 fill=X 改为 fill=BOTH,使其能随内容纵向拉伸:

player_hand.pack(side=BOTTOM, fill=BOTH, expand=1)

3. 绑定 Canvas 与内部 Frame 的尺寸同步

添加绑定事件,当内部卡片 Frame 尺寸变化时,自动更新 Canvas 的滚动区域和自身高度:

def on_frame_configure(event):
    # 更新 Canvas 滚动区域以匹配内部 Frame 尺寸
    scroll_field.config(scrollregion=scroll_field.bbox("all"))
    # 调整 Canvas 高度以适配内部 Frame 高度
    scroll_field.config(height=event.widget.winfo_height())

inside_frame.bind("<Configure>", on_frame_configure)

4. 优化图片加载与垃圾回收

将图片对象存储在 Card 实例中,替代全局列表,更优雅地避免垃圾回收:

class Card:
    def __init__(self, file):
        self.image_path = file
        img = ResizeImage(file)
        self.photo = ImageTk.PhotoImage(img)
        self.label = Label(inside_frame, image=self.photo)

5. 移除冗余的更新循环

删除 logic 函数及重复的 after 调用,依赖绑定事件即可自动更新尺寸,无需手动循环刷新。

完整修正代码

from tkinter import *
from PIL import Image, ImageTk
from pathlib import Path

filedirectory = Path.cwd()

## Image handling
def ResizeImage(image, new_size=(300, 500)):
    tempImage = Image.open(image)
    return tempImage.resize(new_size)

## Window Management
root = Tk()
root.title("Frederick's Custom Dominion Game")
icon = filedirectory.joinpath('img/icon.ico')
root.iconbitmap(icon)
root.geometry("1800x1000")
root.configure(background="green")

frame = Frame(root, bg="green")
frame.pack(side=BOTTOM, fill=BOTH, expand=1)

midframe = Frame(frame, bg="green")
midframe.pack(side=BOTTOM, fill=BOTH, expand=1)

# 移除 LabelFrame 内边距
player_hand = LabelFrame(frame, text='Hand', padx=0, pady=0)
play_area = LabelFrame(midframe, text='Play', padx=0, pady=0)
discard = LabelFrame(midframe, text='discard', padx=0, pady=0)

# 允许 player_hand 纵向扩展
player_hand.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)
scroll_field = Canvas(player_hand, xscrollcommand=scroll_bar.set, highlightthickness=0)
scroll_bar.configure(command=scroll_field.xview)

inside_frame = Frame(scroll_field, bg='blue')

# 绑定尺寸同步事件
def on_frame_configure(event):
    scroll_field.config(scrollregion=scroll_field.bbox("all"))
    scroll_field.config(height=event.widget.winfo_height())

inside_frame.bind("<Configure>", on_frame_configure)

scroll_bar.pack(side=BOTTOM, fill=X)
scroll_field.create_window(0, 0, window=inside_frame, anchor=NW)
scroll_field.pack(fill=BOTH, expand=TRUE)

# 加载卡片
class Card:
    def __init__(self, file):
        self.image_path = file
        img = ResizeImage(file)
        self.photo = ImageTk.PhotoImage(img)
        self.label = Label(inside_frame, image=self.photo)

AllCards = []
flist = [f for f in Path(filedirectory.joinpath('img/Cards')).iterdir() if f.is_file()]
for f in flist:
    AllCards.append(Card(f))

for card in AllCards[:15]:
    card.label.pack(side=LEFT, expand=1, fill=Y)

root.mainloop()

效果说明

  • 卡片将完整显示,Canvas 会自动适配卡片高度
  • LabelFrame 边框与内容紧密贴合,无绿色间隙
  • 横向滚动功能保持正常,且无需手动刷新循环

内容的提问来源于stack exchange,提问作者nope noper

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 07:45:54