You need to enable JavaScript to run this app. 使用PyQt5开发国际象棋项目时可移动区域高亮失效的解决方法
优惠活动
大模型
产品
解决方案
定价
更多

使用PyQt5开发国际象棋项目时可移动区域高亮失效的解决方法

问题根源

你的标记完全不生效本质是两个核心问题导致的:

  • 绘制流程错位:PyQt 的窗口重绘机制是自动触发的,正常执行paintEvent时会先跑完drawRectangles逻辑,把整个棋盘的黑白格子全部绘制一遍,直接把你手动在reachable_cells里画的标记完全覆盖。而且你在reachable_cells里手动创建QPainter调用begin(self)的操作,完全绕开了Qt官方的重绘流程,绘制内容会在下一次自动重绘时被冲掉,根本留不住。
  • 变量不一致的低级bug:你在drawRectangles里用的格子尺寸是self.case,但reachable_cells里却用了self.size作为绘制尺寸,就算流程对了,坐标位置也会完全错位,根本对不齐格子。
正确实现思路

不需要单独写一个触发式的绘制函数,把所有绘制逻辑统一收敛到paintEvent流程里,通过状态驱动绘制即可:

  • 在类的初始化方法里新增一个状态变量,比如self.selected_piece_moves = [],用来存储当前选中棋子对应的所有可移动格子坐标,初始为空列表。
  • 保留你原本的drawRectangles绘制逻辑,在画完所有基础黑白棋盘格之后,紧接着遍历状态变量里存的可移动格子坐标,叠加自定义的标记效果(不管是改底色还是画图标都可以)。
  • 在鼠标点击的事件处理逻辑里,检测到用户点中己方棋子时,计算出该棋子的所有合法移动坐标,赋值给self.selected_piece_moves,然后调用self.update()触发窗口自动重绘就行,不要手动创建QPainter执行绘制。
两种标记效果的实现示例

半透明底色标记

如果想给可移动格子叠一层红色标记,不需要完全替换原本的黑白配色,用半透颜色就可以在drawRectangles走完之后追加这段绘制逻辑:

# 已完成基础棋盘绘制后追加
if self.selected_piece_moves:
    # 第四个参数是透明度,100是半透效果
    qp.setBrush(QtGui.QColor(255, 0, 0, 100))
    for col, row in self.selected_piece_moves:
        # 坐标计算完全和drawRectangles对齐,统一用self.case当格子尺寸
        qp.drawRect(100 + col * self.case, row * self.case, self.case, self.case)

叠加圆形图标标记

这种方式更直观,完全不会破坏棋盘原本的配色,实现逻辑也更简单:

if self.selected_piece_moves:
    qp.setBrush(QtGui.QColor(0, 120, 255, 180))
    for col, row in self.selected_piece_moves:
        # 计算每个格子的中心点
        cell_center_x = 100 + col * self.case + self.case / 2
        cell_center_y = row * self.case + self.case / 2
        # 在格子中心画直径为格子一半大小的实心圆
        qp.drawEllipse(
            cell_center_x - self.case / 4,
            cell_center_y - self.case / 4,
            self.case / 2,
            self.case / 2
        )
注意事项
  • 坐标偏移要和原逻辑完全对齐:你原本的drawRectangles里行坐标是从1到8遍历的,也就是第一行实际绘制位置是1*self.case,计算可移动格子坐标的时候要匹配这个偏移,别把最顶行的位置漏了。
  • 不要在paintEvent之外手动调用QPainter.begin(self):这种操作很容易引发设备上下文错乱、绘制内容不刷新的问题,所有需要更新界面的场景只要修改对应状态变量,调用self.update()即可,Qt会自动调度重绘流程。
  • 当用户取消选中棋子(比如点击空白位置、选中其他棋子)时,把self.selected_piece_moves清空,再调用一次self.update(),之前的标记就会自动消失。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.23 11:06:04