Qt象棋游戏开发实战:如何用QPainter绘制专业级棋盘(附完整代码)
如果你已经掌握了Qt的基础知识,比如信号槽、布局管理,甚至写过几个简单的桌面应用,那么你可能会开始思考:如何用Qt做出更“酷”的东西?一个拥有精美UI、流畅交互的桌面游戏,无疑是一个绝佳的练手项目。而象棋,作为国粹,其棋盘本身就蕴含着对称、比例和古典美学,用代码将其精确、优雅地绘制出来,不仅是对Qt绘图系统的一次深度探索,更是对开发者美学素养和工程能力的综合考验。市面上很多教程只告诉你“画线”,但一个真正专业、耐看的棋盘,需要考虑颜色渐变、抗锯齿、坐标计算、性能优化乃至文化元素的呈现。今天,我们就抛开那些简单的示例,深入Qt的QPainter世界,从零开始构建一个视觉效果出众、代码结构清晰、可直接复用的象棋棋盘绘制模块。你会发现,Qt绘图远不止drawLine那么简单。
1. 项目架构与核心类设计:打好地基
在动手写第一行绘制代码之前,一个好的架构设计能让你事半功倍。我们不应该把所有代码都堆在MainWindow里,而是要进行合理的职责分离。
核心思路是创建一个独立的ChessBoardWidget类,它继承自QWidget,专门负责棋盘的视觉呈现。这个类将封装所有与棋盘绘制相关的数据(如格子大小、颜色)和行为(绘制事件)。这样做的好处是显而易见的:棋盘成了一个自包含的、可重用的组件,你可以轻松地把它嵌入到任何Qt界面中,与棋子逻辑、游戏规则等其他模块清晰解耦。
首先,我们创建头文件 chessboardwidget.h:
#ifndef CHESSBOARDWIDGET_H
#define CHESSBOARDWIDGET_H
#include <QWidget>
#include <QPen>
#include <QBrush>
#include <QLinearGradient>
class ChessBoardWidget : public QWidget
{
Q_OBJECT
public:
explicit ChessBoardWidget(QWidget *parent = nullptr);
// 关键:提供设置棋盘视觉属性的接口
void setCellSize(int size); // 设置每个格子的像素大小
int cellSize() const;
void setBoardColor(const QColor &color); // 设置棋盘底色
QColor boardColor() const;
void setLineColor(const QColor &color); // 设置线条颜色
QColor lineColor() const;
void setShowCoordinates(bool show); // 是否显示坐标(如A1, B2)
bool showCoordinates() const;
protected:
// 重写此函数以实现自定义绘制
void paintEvent(QPaintEvent *event) override;
private:
// 内部私有数据成员
int m_cellSize; // 单个棋格边长(像素)
QColor m_boardColor; // 棋盘主背景色
QColor m_lineColor; // 棋盘线颜色
bool m_showCoordinates; // 显示坐标标记
// 辅助计算函数
QPointF boardToPixel(int row, int col) const; // 将棋盘行列坐标转换为像素坐标
void drawRiverArea(QPainter &painter); // 绘制“楚河汉界”区域
void drawCrossMark(QPainter &painter, int row, int col); // 绘制炮位和兵位的十字标记
};
#endif // CHESSBOARDWIDGET_H
这个头文件定义了我们的“蓝图”。m_cellSize是整个设计的核心,所有坐标计算都基于它,修改它就能轻松缩放整个棋盘。提供setter/getter函数意味着我们可以在运行时动态调整棋盘外观,为未来添加“皮肤切换”功能留出空间。
2. 绘制核心:深入paintEvent与QPainter的魔法
paintEvent是Qt控件绘制的灵魂入口。当系统认为这个部件需要重绘时(如首次显示、窗口调整大小、调用update()),就会调用这个函数。我们的所有绘制逻辑都将在这里展开。
让我们先实现构造函数和基本的属性设置,在 chessboardwidget.cpp 中:
#include "chessboardwidget.h"
#include <QPainter>
#include <QFontMetrics>
#include <QDebug>
ChessBoardWidget::ChessBoardWidget(QWidget *parent)
: QWidget(parent)
, m_cellSize(60) // 默认格子大小为60像素
, m_boardColor(QColor(0xF0, 0xE0, 0x96)) // 一种古典的米黄色
, m_lineColor(Qt::black)
, m_showCoordinates(false)
{
// 设置部件的最小尺寸,确保能完整显示棋盘
// 中国象棋棋盘是9列10行,加上外边框的偏移
setMinimumSize(m_cellSize * 11, m_c

1671

被折叠的 条评论
为什么被折叠?



