Python的包tkinter中的canvas.winfo_height()或canvas.winfo_width()返回值1的解决

问题描述

下述代码:

from tkinter import *
import random
import time

class SnakeHead:
    def __init__(self,canvas,color):
        self.canvas = canvas 
        self.id = canvas.create_oval(10,10,25,25,fill=color)
        self.canvas.move(self.id,245,100)
        self.x = -3
        self.y = -3
        self.canvas_height = self.canvas.winfo_height()
        self.canvas_width = self.canvas.winfo_width()
        self.curPos = self.canvas.coords(self.id)
        self.prePos = None 
        
    def move_ball(self):
        self.canvas.move(self.id,self.x,self.y)
        pos = self.canvas.coords(self.id)
        
        if self.curPos != pos:
            self.prePos = self.curPos 
            self.curPos = pos
        print("----------") #调试
        print(self.curPos)
        print(self.canvas.winfo_height())
        print(self.prePos)
        print("----------")
        if self.curPos[0] <= 0:
            self.x = 3
        if self.curPos[2] >= self.canvas_width:
            self.x = -3
        if self.curPos[1] <= 0:
            self.y = 3
        if self.curPos[3] >= self.canvas_height:
            self.y = -3
        self.canvas.after(100,self.move_ball)

root = Tk()
root.title("Game")
root.resizable(0,0)
root.wm_attributes("-topmost",1)
canvas = Canvas(root,width=500,height=400,bd=0,highlightthickness=0)
canvas.pack()
#print("heigt:")
#print(canvas.winfo_height())

# test 
sh = SnakeHead(canvas,'red')
sh.move_ball()

root.mainloop()

运行后,print(self.canvas.winfo_height())前2次的循环返回值为1,而不是实际的400,运行结果如下图所示,
canvas.winfo_height()错误显示
这是一个问题。若不解决,则小球的动画演示不正确,其运动会越出边界。

解决方案

通过网上查找资料,加上自己的思考,最终的问题出在Canvas在创建后一定要及时对主窗口执行update命令。具体来说:上述的canvas.pack()后添加代码:

root.update() # key code

这个问题,困扰了我断断续续2个晚上,加上我大量的思考,终于得以解决。实际上若不是动画类的程序,不及时root.update()也是可以的。

  • 8
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
class ExcelApp: def init(self, master): self.master = master master.title("Excel App") # 获取屏幕的宽度和高度 screen_width = master.winfo_screenwidth() screen_height = master.winfo_screenheight() # 将窗口的大小设置为屏幕的大小 master.geometry("%dx%d" % (screen_width, screen_height)) master.state('zoomed')#窗口最大化# 创建左侧面板 self.panel_left = tk.Frame(master, width=150, bg='lightcyan') self.panel_left.pack(side=tk.LEFT, fill=tk.Y) def load_excel(self, filename, menu_label,selected_label_text): self.la = menu_label self.workbook = xl.load_workbook(filename) self.sheet_names = self.workbook.sheetnames self.selected_label.config(text=selected_label_text) # 更新选标签文本 # 清空左侧面板 for widget in self.panel_left.winfo_children(): widget.destroy() # 添加工作表按钮 for i, sheet_name in enumerate(self.sheet_names): button = tk.Button(self.panel_left, text=sheet_name, command=lambda name=sheet_name: self.show_sheet(name)) button.grid(row=i, column=0, sticky="ew", padx=1, pady=1) # 添加一个标记,表示该按钮未被使用 button.used = False # 绑定鼠标进入事件 button.bind("<Enter>", lambda event, button=button: button.configure(bg="lightgray")) # 绑定鼠标离开事件 button.bind("<Leave>", lambda event, button=button: button.configure(bg="SystemButtonFace")) # 绑定按钮的点击事件 button.bind("<Button-1>", lambda event, button=button: mark_used(button)) def mark_used(button): if not button.used: # 将按钮的标记设置为“已使用” button.used = True # 更改按钮的背景颜色 button.configure(bg="green") # 取消按钮的绑定事件 button.unbind("<Button-1>") # 绑定鼠标离开事件,使按钮的背景颜色保持不变 button.bind("<Leave>", lambda event, button=button: button.configure(bg="green")) for child in button.master.winfo_children(): # 绑定按钮的点击事件 child.bind("<Button-1>", lambda event, button=child: mark_used(button))給這段代碼的添加哪一個滾動條防止數據未完全顯示的完整代碼
最新发布
05-27
以下是带有滚动条的完整代码: ``` import tkinter as tk from tkinter import ttk import openpyxl as xl class ExcelApp: def __init__(self, master): self.master = master master.title("Excel App") # 获取屏幕的宽度和高度 screen_width = master.winfo_screenwidth() screen_height = master.winfo_screenheight() # 将窗口的大小设置为屏幕的大小 master.geometry("%dx%d" % (screen_width, screen_height)) master.state('zoomed') # 窗口最大化 # 创建左侧面板 self.panel_left_scrollbar = ttk.Scrollbar(master) self.panel_left_scrollbar.pack(side=tk.LEFT, fill=tk.Y) self.panel_left = tk.Canvas(master, bg='lightcyan', yscrollcommand=self.panel_left_scrollbar.set) self.panel_left.pack(side=tk.LEFT, fill=tk.BOTH, expand=True) self.panel_left_scrollbar.config(command=self.panel_left.yview) def load_excel(self, filename, menu_label, selected_label_text): self.la = menu_label self.workbook = xl.load_workbook(filename) self.sheet_names = self.workbook.sheetnames self.selected_label.config(text=selected_label_text) # 更新选标签文本 # 清空左侧面板 self.panel_left.delete(tk.ALL) # 添加工作表按钮 for i, sheet_name in enumerate(self.sheet_names): button = tk.Button(self.panel_left, text=sheet_name, command=lambda name=sheet_name: self.show_sheet(name)) button.grid(row=i, column=0, sticky="ew", padx=1, pady=1) # 添加一个标记,表示该按钮未被使用 button.used = False # 绑定鼠标进入事件 button.bind("<Enter>", lambda event, button=button: button.configure(bg="lightgray")) # 绑定鼠标离开事件 button.bind("<Leave>", lambda event, button=button: button.configure(bg="SystemButtonFace")) # 绑定按钮的点击事件 button.bind("<Button-1>", lambda event, button=button: mark_used(button)) def mark_used(button): if not button.used: # 将按钮的标记设置为“已使用” button.used = True # 更改按钮的背景颜色 button.configure(bg="green") # 取消按钮的绑定事件 button.unbind("<Button-1>") # 绑定鼠标离开事件,使按钮的背景颜色保持不变 button.bind("<Leave>", lambda event, button=button: button.configure(bg="green")) for child in button.master.winfo_children(): # 绑定按钮的点击事件 child.bind("<Button-1>", lambda event, button=child: mark_used(button)) root = tk.Tk() app = ExcelApp(root) root.mainloop() ``` 注意,这里我们使用了Canvas窗口小部件来替代之前的Frame窗口小部件,并将其含在一个带有滚动条的可滚动窗口小部件。同时,我们也需要更新左侧面板的清空方式。现在,当我们加载新的Excel文件时,左侧面板的所有按钮都将被删除,并使用Canvas重新创建。希望这个完整的代码能对你有所帮助。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值