在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
相关产品推荐
相关产品推荐

