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

已解决:Tkinter中可滚动Canvas的卡片滚动实现

问题进展更新:基于Tkinter实现可滚动卡片Canvas

尽管实现方式可能并非最优,但我已通过以下Tkinter程序完成了带垂直滚动功能的卡片Canvas:

from tkinter import *
from tkinter import ttk
from PIL import Image, ImageTk
MainWindow = Tk()
MainWindow.config(bg="green")
MainWindow.geometry("1350x680")
MainWindow.title("Canasta")


class Card:
    def __init__(self, cardText):
        self.__cardText = cardText
        self.__cardImage = ResizeCard(f"CardImages/{cardText}.png")

    def GetCardText(self):
        return self.__cardText

    def GetCardImage(self):
        return self.__cardImage


def ResizeCard(cardImage):
    cardInDeckImg = Image.open(cardImage)

    cardInDeckResizedImg = cardInDeckImg.resize((120, 200))

    # 输出处理后的卡片
    cardInDeckImg = ImageTk.PhotoImage(cardInDeckResizedImg)

    return cardInDeckImg


def DisplayMeld(Meld, rowNo, meldNo, verticalPos, MeldFrame):
    if len(Meld) > 0:
        columnNo = 0

        Label(MeldFrame, text=f"{meldNo}. ", font=(
            'Helvetica 16 bold'), bg="green").place(x=horizontalPos, y=verticalPos)

        firstColumnFilled = False
        noOfCardsInRow = 0

        for card in Meld:
            if firstColumnFilled == False:
                Label(MeldFrame, text="                                                                                                                     ", bg="green").grid(
                    row=rowNo, column=columnNo)
                firstColumnFilled = True
            columnNo += 1

            if noOfCardsInRow == 5:
                rowNo += 1
                columnNo = 1
                verticalPos += 215
                noOfCardsInRow = 0

            Label(MeldFrame, image=card.GetCardImage()).grid(
                row=rowNo, column=columnNo, padx=(10, 0), pady=(0, 10))

            noOfCardsInRow += 1

        rowNoAndVerticalPos = [rowNo, verticalPos]
        return rowNoAndVerticalPos


card1 = Card("AS")
card2 = Card("AS")
card3 = Card("AD")

redThree = Card("3H")

RoundFrame = Frame(MainWindow, bg="green")
RoundFrame.pack(fill=BOTH, expand=1)

canvas = Canvas(RoundFrame, bg="green")

canvas.pack(side=LEFT, fill=BOTH, expand=1)

scrollBar = ttk.Scrollbar(RoundFrame, orient=VERTICAL, command=canvas.yview)
scrollBar.pack(side=RIGHT, fill=Y)

canvas.configure(yscrollcommand=scrollBar.set)
canvas.bind('<Configure>', lambda e: canvas.configure(
    scrollregion=canvas.bbox("all")))

MeldFrame = Frame(canvas, bg="green")

# 将Frame锚定在画布左上角
canvas.create_window((0, 0), window=MeldFrame, anchor="nw")

# 牌堆顶部卡片UI
stockPileCoverImg = ResizeCard(f'CardImages/stockPileCover.png')

Label(RoundFrame, image=stockPileCoverImg).place(x=10, y=10)
Label(RoundFrame, text="Stock Pile", font=('Helvetica 16 bold'),
      bg="green").place(x=15, y=215)

# 弃牌堆顶部卡片UI
topCardOfDiscardPile = Card("7D")

Label(RoundFrame, image=topCardOfDiscardPile.GetCardImage()).place(x=1203, y=10)
Label(RoundFrame, text="Discard Pile", font=('Helvetica 16 bold'),
      bg="green").place(x=1201, y=215)

Meld1 = [card1, card2, card3, card1, card2,
         card3, card1, card2, card3, card1, card2]
Meld2 = [redThree]

Melds = [Meld1, Meld2]

Label(MeldFrame, text="The following are your melds:", font=(
    'Helvetica 18 bold'), bg="green").place(x=505, y=15)
Label(MeldFrame, text="                            ",
      bg="green").grid(row=0, column=0, pady=(0, 40))

rowNo = 1
horizontalPos = 445
verticalPos = 62
meldNo = 1
for Meld in Melds:
    rowNoAndVerticalPos = DisplayMeld(
        Meld, rowNo, meldNo, verticalPos, MeldFrame)
    returnedRowNo = rowNoAndVerticalPos[0]
    returnedVerticalPos = rowNoAndVerticalPos[1]

    rowNo = returnedRowNo + 1
    verticalPos = returnedVerticalPos + 215
    meldNo += 1

MainWindow.mainloop()

程序运行效果如下:
程序运行效果

在此感谢所有提供帮助的人,谢谢你们的建议。


内容的提问来源于stack exchange,提问作者نظامی گنجوی

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 22:32:42