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

Tkinter鼠标移出绘图边界触发IndexError的修复方法咨询

修复Tkinter绘图代码的IndexError错误

问题场景

运行一段Tkinter绘图代码时,鼠标移出预先绘制的边界区域时,程序触发IndexError: list assignment index out of range错误。

报错信息

Exception in Tkinter callback
Traceback (most recent call last):
  File "c:\Users\My PC\AppData\Local\Programs\Python\Python312\Lib\tkinter\__init__.py", line 1962, in __call__
    return self.func(*args)
           ^^^^^^^^^^^^^^^^
  File "c:\Windows\System32\awdkhjgeuyfsbiufhefse.py", line 4, in <lambda>   
    K=__import__('tkinter');m=K.Tk();R,C,z,p=50,50,10,0;l=[[0]*C for _ in range(R)];c=K.Canvas(m,w=C*z,he=R*z,bg='#0c0c0c');c.pack();[c.create_line(0,i*z,C*z,i*z,fill='#1a1a1a')for i in range(R)];[c.create_line(j*z,0,j*z,R*z,fill='#1a1a1a')for j in range(C)];c.bind("<B1-Motion>",lambda e:d(e.x//z,e.y//z));m.bind("<space>",t);m.mainloop()
                                                                                                     
                                                                                                     
                                                                                      ^^^^^^^^^^^^^^^^
  File "c:\Windows\System32\awdkhjgeuyfsbiufhefse.py", line 1, in d
    def d(x,y):global l;l[y][x]=1;c.create_rectangle(x*z,y*z,(x+1)*z,(y+1)*z,fill='#fff',outline='') 
                        ~~~~^^^
IndexError: list assignment index out of range

完整代码

def d(x,y):global l;l[y][x]=1;c.create_rectangle(x*z,y*z,(x+1)*z,(y+1)*z,fill='#fff',outline='')
def t(_=None):global p;p^=1;['',u()][p]
def u():global l,K;l=[[1 if(l[y][x]==1 and sum(l[y+dy][x+dx]for dx,dy in((dx,dy)for dx in(-1,0,1)for dy in(-1,0,1)if(dx,dy)!=(0,0))if 0<=x+dx<C and 0<=y+dy<R)in(2,3))or(l[y][x]==0 and sum(l[y+dy][x+dx]for dx,dy in((dx,dy)for dx in(-1,0,1)for dy in(-1,0,1)if(dx,dy)!=(0,0))if 0<=x+dx<C and 0<=y+dy<R)==3)else 0 for x in range(C)]for y in range(R)];K=__import__('tkinter');c.delete("all");[c.create_line(0,i*z,C*z,i*z,fill='#1a1a1a')for i in range(R+1)];[c.create_line(j*z,0,j*z,R*z,fill='#1a1a1a')for j in range(C+1)];[[c.create_rectangle(x*z,y*z,(x+1)*z,(y+1)*z,fill='white',outline='')for x in range(C)if l[y][x]]for y in range(R)];m.after(100,u) if p else None
K=__import__('tkinter');m=K.Tk();R,C,z,p=50,50,10,0;l=[[0]*C for _ in range(R)];c=K.Canvas(m,w=C*z,he=R*z,bg='#0c0c0c');c.pack();[c.create_line(0,i*z,C*z,i*z,fill='#1a1a1a')for i in range(R)];[c.create_line(j*z,0,j*z,R*z,fill='#1a1a1a')for j in range(C)];c.bind("<B1-Motion>",lambda e:d(e.x//z,e.y//z));m.bind("<space>",t);m.mainloop()

错误原因

当鼠标移出Canvas区域时,e.x或e.y会变为负数,或者超出Canvas的宽高范围,导致e.x//z或e.y//z计算出的x、y值超出了二维列表l的索引边界(l是50行50列,合法索引为x∈[0,49],y∈[0,49]),触发索引越界错误。

修复方案

方案1:修改d函数,增加边界检查

在访问列表l之前,先判断x、y是否在合法范围内,仅在合法时执行赋值和绘图操作:

def d(x,y):
    global l
    # 检查坐标是否在合法索引范围内
    if 0 <= x < C and 0 <= y < R:
        l[y][x] = 1
        c.create_rectangle(x*z, y*z, (x+1)*z, (y+1)*z, fill='#fff', outline='')

方案2:修改事件绑定的lambda表达式,提前过滤非法坐标

在调用d函数前先判断坐标是否合法,非法时不执行函数:

c.bind("<B1-Motion>", lambda e: d(e.x//z, e.y//z) if 0 <= e.x//z < C and 0 <= e.y//z < R else None)

两种方案任选其一即可,都能避免鼠标移出边界时触发索引越界错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 05:18:13