You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Python3 Tkinter为Pyramid游戏GUI添加全局滚动条问题求助

Fixing Tkinter Canvas Scrollbar Issue for Pyramid Card Game GUI

Hey there! I see you're trying to add a global scrollbar to your Pyramid card game GUI but ran into issues where your cards stopped showing up after switching to the Canvas+Frame structure. Let's break down what went wrong and fix it step by step.

Key Issues in Your Attempt

  1. Missing Weight Configuration: Your root and main frames weren't set to expand with the window, so the canvas didn't get the space it needed to display content.
  2. Incorrect Scrollregion Setup: You tried setting the scrollregion before the widgets in frame_pyramid had fully rendered, so Tkinter couldn't calculate their actual dimensions.
  3. Unnecessary Frame Sizing: Manually setting frame_pyramid's width/height using pyramid_levels didn't align with the actual content size—you need to let the frame auto-size based on its widgets.

Fixed Code with Explanations

Here's the corrected version, with comments pointing out critical changes:

from tkinter import *
from PIL import ImageTk, Image
import itertools
import random

root = Tk()
root.title('Pyramid')
root.configure(bg='#0a6c03')
# Make root window expand with resizing
root.grid_rowconfigure(0, weight=1)
root.grid_columnconfigure(0, weight=1)

# Main Frame - holds top content and scrollable canvas area
frame_main = Frame(root, bg='#0a6c03')
frame_main.grid(sticky='nsew')
# Configure rows: top content stays fixed, scrollable area expands
frame_main.grid_rowconfigure(0, weight=0)
frame_main.grid_rowconfigure(1, weight=1)
frame_main.grid_columnconfigure(0, weight=1)

# --- Add your top content here (e.g., game title, player info) ---
top_frame = Frame(frame_main, bg='#0a6c03', pady=10)
top_frame.grid(row=0, column=0, sticky='ew')
Label(top_frame, text="Pyramid Card Game", fg="white", bg="#0a6c03", font="Arial 24 bold").pack()
# You can add player names, score displays, or controls here later

# Frame for Canvas and Scrollbar
frame_canvas = Frame(frame_main)
frame_canvas.grid(row=1, column=0, pady=(5, 0), sticky='nsew')
frame_canvas.grid_rowconfigure(0, weight=1)
frame_canvas.grid_columnconfigure(0, weight=1)

# Canvas setup
canvas = Canvas(frame_canvas, bg='#0a6c03')
canvas.grid(row=0, column=0, sticky="nsew")

# Vertical Scrollbar
vscrollbar = Scrollbar(frame_canvas, orient="vertical", command=canvas.yview)
vscrollbar.grid(row=0, column=1, sticky='ns')
canvas.configure(yscrollcommand=vscrollbar.set)

# Content Frame (holds your pyramid cards)
frame_pyramid = Frame(canvas, bg='#0a6c03')
canvas.create_window((0, 0), window=frame_pyramid, anchor='nw')

# --- Your Existing Game Logic ---
def Players():
    global players
    players = {}
    global labelPlayers
    labelPlayers = {}
    global player_amount
    player_amount = int(input("Amount of players: "))
    for i in range(1, player_amount+1):
        players["player" + str(i)] = input("Enter Player "+str(i)+" name: ")

def Card_amount():
    global hand_cards_amount
    hand_cards_amount = int(input("Amount of Cards for Players Hands: "))

def Deck():
    global number
    number = ["A","2","3","4","5","6","7","8","9","10","J","Q","K"]
    global suit
    suit = ["C","S","D","H"]
    global deck
    deck = list(itertools.product(number,suit))

def Deck_Shuffle(deck):
    global card
    random.shuffle(deck)
    # Optimized: no need to loop 10 times—just pick the first shuffled card
    card = deck[0][0] + deck[0][1]
    return card

def Levels():
    global pyramid_levels
    pyramid_levels = int(input("Amount of levels the pyramid will have: "))

def Game():
    Levels()
    Deck()
    hands = {}
    cards = {}
    print(pyramid_levels)
    
    for i in range(0, pyramid_levels):
        labelLevels = Label(frame_pyramid, text='Level '+ str(pyramid_levels - i), 
                            fg="white", bg="#0a6c03", font="Arial 20 bold")
        labelLevels.grid(row=i, column=0, padx=10, pady=5)
        
        hands["hand" + str(i)] = cards
        for j in range(0, i+1):
            Deck_Shuffle(deck)
            # Load and resize card image
            im = ImageTk.PhotoImage(Image.open(f"images/{card}.png").resize((100, 150), Image.ANTIALIAS))
            cards[f"card{(i*10)+j}"] = im  # Keep reference to avoid image garbage collection
            labelIm = Label(frame_pyramid, image=cards[f"card{(i*10)+j}"], bg="#0a6c03")
            labelIm.grid(row=i, column=j+1, padx=2, pady=2, columnspan=pyramid_levels - i)
    
    # Critical: Update widget sizes before setting scrollregion
    frame_pyramid.update_idletasks()
    # Set canvas scroll region to match the full content size
    canvas.config(scrollregion=canvas.bbox("all"))

Game()
root.mainloop()

What Changed?

  • Window/Frame Expansion: Added grid_rowconfigure and grid_columnconfigure to root and frame_main so the scrollable area adapts to window resizing.
  • Top Content Area: Added a dedicated top_frame where you can easily add game headers, player info, or controls above the scrollable pyramid.
  • Shuffle Optimization: Removed the unnecessary loop in Deck_Shuffle—shuffling once and picking the first card is all you need.
  • Scrollregion Fix: Called frame_pyramid.update_idletasks() to force Tkinter to calculate the actual size of all widgets before setting the canvas scrollregion.
  • Auto-Sizing Content Frame: Let frame_pyramid auto-size based on its content instead of using arbitrary dimensions.

Now your pyramid cards should display correctly, and the scrollbar will work with the full height of your game content. You can expand the top frame with any additional UI elements you need!

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

火山引擎 最新活动