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

在PyQt5网格游戏中,如何将网格坐标转换回(x,y)坐标?

嘿,刚好我对PyQt5的网格坐标转换熟得很,来给你唠唠怎么搞定这个问题!

首先咱们得先明确两个坐标的定义:

  • 网格坐标:指的是网格里的行列号(比如(row, col),从0开始计数,比如第1行第2列就是(0,1))
  • 屏幕(x,y)坐标:就是PyQt窗口里的像素坐标,咱们用来画线条、标记点的那个

根据你定义的常量GRID_ORIGINX、GRID_ORIGINY和CELL_SIZE,转换逻辑其实很直白:

1. 核心转换公式

如果要把网格坐标(row, col)转成屏幕坐标:

  • 屏幕x坐标 = 网格起始X + 列号 × 单元格大小
  • 屏幕y坐标 = 网格起始Y + 行号 × 单元格大小

如果你需要的是单元格的中心坐标(比如点击网格区域后标记中心点),就在上面的基础上加上单元格大小的一半就行。

2. 代码实现(集成到你的TribeSquares类里)

我给你写两个实用的方法,一个负责转屏幕坐标,一个还能把点击的屏幕坐标转回网格坐标(毕竟你需要先捕获用户点击的网格位置对吧):

import sys
from PyQt5.QtGui import QPainter, QColor, QPen, QBrush
from PyQt5.QtCore import Qt, QRect, QPoint
from PyQt5.QtWidgets import QWidget, QApplication

CELL_COUNT = 8
CELL_SIZE = 50
GRID_ORIGINX = 150
GRID_ORIGINY = 150
W_WIDTH = 700
W_HEIGHT = 700

class TribeSquares(QWidget):
    def __init__(self):
        super().__init__()
        self.selected_grid_points = []  # 存选中的网格坐标(row, col)
        self.setFixedSize(W_WIDTH, W_HEIGHT)
        self.setWindowTitle("Tribe Squares")

    def grid_to_screen(self, row, col, use_center=False):
        """把网格坐标(row, col)转成屏幕QPoint坐标"""
        x = GRID_ORIGINX + col * CELL_SIZE
        y = GRID_ORIGINY + row * CELL_SIZE
        if use_center:
            # 转成单元格中心坐标
            x += CELL_SIZE // 2
            y += CELL_SIZE // 2
        return QPoint(x, y)

    def screen_to_grid(self, screen_x, screen_y):
        """把屏幕坐标转成网格坐标(row, col),不在网格内返回None"""
        # 先判断点击位置是否在网格范围内
        grid_right = GRID_ORIGINX + CELL_COUNT * CELL_SIZE
        grid_bottom = GRID_ORIGINY + CELL_COUNT * CELL_SIZE
        if not (GRID_ORIGINX <= screen_x < grid_right and GRID_ORIGINY <= screen_y < grid_bottom):
            return None
        # 计算对应的行列号
        col = (screen_x - GRID_ORIGINX) // CELL_SIZE
        row = (screen_y - GRID_ORIGINY) // CELL_SIZE
        return (row, col)

    # 补充鼠标点击和重绘的逻辑,方便你测试
    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton:
            click_pos = event.pos()
            grid_pos = self.screen_to_grid(click_pos.x(), click_pos.y())
            if grid_pos and grid_pos not in self.selected_grid_points:
                self.selected_grid_points.append(grid_pos)
                # 最多保留4个选中点
                if len(self.selected_grid_points) > 4:
                    self.selected_grid_points.pop(0)
                self.update()  # 触发重绘

    def paintEvent(self, event):
        painter = QPainter(self)
        # 绘制网格线
        painter.setPen(QPen(Qt.black, 1))
        # 画横线
        for row in range(CELL_COUNT + 1):
            y = GRID_ORIGINY + row * CELL_SIZE
            painter.drawLine(GRID_ORIGINX, y, GRID_ORIGINX + CELL_COUNT*CELL_SIZE, y)
        # 画竖线
        for col in range(CELL_COUNT + 1):
            x = GRID_ORIGINX + col * CELL_SIZE
            painter.drawLine(x, GRID_ORIGINY, x, GRID_ORIGINY + CELL_COUNT*CELL_SIZE)
        
        # 绘制选中的点(用中心坐标)
        painter.setPen(QPen(Qt.red, 6))
        for row, col in self.selected_grid_points:
            center_pos = self.grid_to_screen(row, col, use_center=True)
            painter.drawPoint(center_pos)
        
        # 如果选中4个点,连接成线(这里你可以自己加正方形判断逻辑)
        if len(self.selected_grid_points) == 4:
            painter.setPen(QPen(Qt.blue, 2))
            # 把所有网格点转成屏幕坐标
            screen_points = [self.grid_to_screen(r, c, use_center=True) for r, c in self.selected_grid_points]
            # 连接成四边形
            for i in range(4):
                painter.drawLine(screen_points[i], screen_points[(i+1)%4])

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = TribeSquares()
    window.show()
    sys.exit(app.exec_())

3. 小提示

  • 代码里修正了你打错的QColo,改成了正确的QColor
  • 你可以在选中4个点后,自己补充判断这四个点是否能构成正方形的逻辑(比如判断边长相等、对角线相等),再决定是否画线

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 09:43:10