|
7 | 7 | #include "ui_ChessBoard.h" |
8 | 8 | #include <mutex> |
9 | 9 |
|
10 | | -ChessBoard::ChessBoard(QWidget *parent) : |
11 | | - QMainWindow(parent), |
12 | | - ui(new Ui::ChessBoard) |
13 | | -{ |
| 10 | +ChessBoard::ChessBoard(QWidget *parent) : |
| 11 | + QMainWindow(parent), |
| 12 | + ui(new Ui::ChessBoard) |
| 13 | +{ |
14 | 14 | init(); |
15 | 15 |
|
16 | 16 | //计时器部分 |
17 | 17 | m_timer = new QTimer; //初始化定时器 |
18 | 18 | m_timeRecord = new QTime(0, 0, 0); //初始化时间 |
19 | 19 | m_bIsStart = false; //初始为还未计时 |
20 | 20 | connect(m_timer,SIGNAL(timeout()),this,SLOT(updateTime())); |
21 | | - |
22 | | - m_pAbout = new AboutAuthor(); |
23 | | - |
24 | | - this->setWindowIcon(QIcon(":/images/chess.svg")); |
25 | | - ui->setupUi(this); |
26 | | -} |
| 21 | + |
| 22 | + m_pAbout = new AboutAuthor(); |
| 23 | + |
| 24 | + this->setWindowIcon(QIcon(":/images/chess.svg")); |
| 25 | + ui->setupUi(this); |
| 26 | + |
| 27 | + // 交互只依赖于 ChessBoard,自身绘制用的 QLabel 需要放行鼠标事件 |
| 28 | + if (ui->label) { |
| 29 | + ui->label->setAttribute(Qt::WA_TransparentForMouseEvents, true); |
| 30 | + } |
| 31 | +} |
27 | 32 |
|
28 | 33 | ChessBoard::~ChessBoard() |
29 | 34 | { |
@@ -183,22 +188,53 @@ QPointF ChessBoard::center(int row, int col) |
183 | 188 | } |
184 | 189 |
|
185 | 190 | //重载:坐标转换 |
186 | | -QPointF ChessBoard::center(int id) |
187 | | -{ |
188 | | - return center(m_ChessPieces[id].m_nRow, m_ChessPieces[id].m_nCol); |
189 | | -} |
190 | | - |
191 | | -void ChessBoard::paintEvent(QPaintEvent *) |
192 | | -{ |
193 | | - QPainter painter(this); |
194 | | - painter.setRenderHint(QPainter::Antialiasing, true); |
195 | | - int side = qMin(int((ui->centralwidget->width() - ui->verticalWidget->width()) / 0.9), ui->label->height()); |
196 | | - painter.scale(side / 960.0, side / 960.0); |
197 | | - |
198 | | - m_nOffSet = 60.0; //距离界面的边距 |
199 | | - m_nD = 90.0; //间距为50px |
200 | | - m_nR = m_nD/2.0; //棋子半径为d/2 |
201 | | - |
| 191 | +QPointF ChessBoard::center(int id) |
| 192 | +{ |
| 193 | + return center(m_ChessPieces[id].m_nRow, m_ChessPieces[id].m_nCol); |
| 194 | +} |
| 195 | + |
| 196 | +bool ChessBoard::boardTransform(QPointF& origin, qreal& side) const |
| 197 | +{ |
| 198 | + if (!ui || !ui->label) |
| 199 | + return false; |
| 200 | + |
| 201 | + const QPoint topLeft = ui->label->mapTo(this, QPoint(0, 0)); |
| 202 | + const QSize boardSize = ui->label->size(); |
| 203 | + if (boardSize.isEmpty()) |
| 204 | + return false; |
| 205 | + |
| 206 | + const qreal width = boardSize.width(); |
| 207 | + const qreal height = boardSize.height(); |
| 208 | + side = qMin(width, height); |
| 209 | + if (side <= 0.0) |
| 210 | + return false; |
| 211 | + |
| 212 | + origin = QPointF(topLeft); |
| 213 | + origin.rx() += (width - side) / 2.0; |
| 214 | + origin.ry() += (height - side) / 2.0; |
| 215 | + return true; |
| 216 | +} |
| 217 | + |
| 218 | +void ChessBoard::paintEvent(QPaintEvent *event) |
| 219 | +{ |
| 220 | + QMainWindow::paintEvent(event); |
| 221 | + |
| 222 | + QPointF boardOrigin; |
| 223 | + qreal boardSide = 0.0; |
| 224 | + if (!boardTransform(boardOrigin, boardSide)) |
| 225 | + return; |
| 226 | + |
| 227 | + QPainter painter(this); |
| 228 | + painter.setRenderHint(QPainter::Antialiasing, true); |
| 229 | + painter.save(); |
| 230 | + painter.translate(boardOrigin); |
| 231 | + const qreal scale = boardSide / 960.0; |
| 232 | + painter.scale(scale, scale); |
| 233 | + |
| 234 | + m_nOffSet = 60.0; //距离界面的边距 |
| 235 | + m_nD = 90.0; //间距为50px |
| 236 | + m_nR = m_nD/2.0; //棋子半径为d/2 |
| 237 | + |
202 | 238 | //*******************绘画棋盘******************* |
203 | 239 | //绘画10条横线 |
204 | 240 | for(int i = 0; i <= 9; i++) |
@@ -239,12 +275,13 @@ void ChessBoard::paintEvent(QPaintEvent *) |
239 | 275 | if(m_bIsShowStep) |
240 | 276 | drawLastStep(painter,m_ChessSteps); |
241 | 277 |
|
242 | | - for(int i = 0; i < 32; i++) |
243 | | - drawChessPieces(painter, i); |
244 | | - |
245 | | - //绘制文本棋谱 |
246 | | - drawTextStep(); |
247 | | -} |
| 278 | + for(int i = 0; i < 32; i++) |
| 279 | + drawChessPieces(painter, i); |
| 280 | + |
| 281 | + //绘制文本棋谱 |
| 282 | + painter.restore(); |
| 283 | + drawTextStep(); |
| 284 | +} |
248 | 285 |
|
249 | 286 | void ChessBoard::drawChessPieces(QPainter &painter, int id) //绘画单个具体的棋子 |
250 | 287 | { |
@@ -361,15 +398,19 @@ void ChessBoard::winMessageBox(QString title, QString msg) |
361 | 398 | message.exec(); |
362 | 399 | } |
363 | 400 |
|
364 | | -QPointF ChessBoard::getRealPoint(QPointF pt) |
365 | | -{ |
366 | | -// 计算 side 时,确保使用 qreal 以避免精度丢失 |
367 | | - qreal side = qMin(qreal((ui->centralwidget->width() - ui->verticalWidget->width()) / 0.9), qreal(ui->label->height())); |
368 | | - QPointF realPt; |
369 | | - realPt.setX(pt.x() * 960.0 / side); |
370 | | - realPt.setY(pt.y() * 960.0 / side); |
371 | | - return realPt; |
372 | | -} |
| 401 | +QPointF ChessBoard::getRealPoint(QPointF pt) |
| 402 | +{ |
| 403 | + QPointF origin; |
| 404 | + qreal side = 0.0; |
| 405 | + if (!boardTransform(origin, side) || side <= 0.0) |
| 406 | + return QPointF(-1.0, -1.0); |
| 407 | + |
| 408 | + const QPointF relative = pt - origin; |
| 409 | + QPointF realPt; |
| 410 | + realPt.setX(relative.x() * 960.0 / side); |
| 411 | + realPt.setY(relative.y() * 960.0 / side); |
| 412 | + return realPt; |
| 413 | +} |
373 | 414 |
|
374 | 415 | bool ChessBoard:: isGeneral() |
375 | 416 | { |
@@ -740,15 +781,23 @@ bool ChessBoard:: canSelect(int id) |
740 | 781 | return m_bIsRed== m_ChessPieces[id].m_bRed; |
741 | 782 | } |
742 | 783 |
|
743 | | -void ChessBoard::mouseReleaseEvent(QMouseEvent *ev) |
744 | | -{ |
745 | | - if (ev->button() != Qt::LeftButton || m_bIsOver== true) { // 排除鼠标右键点击 游戏已结束则直接返回 |
746 | | - return; |
747 | | - } |
748 | | - QPoint mousePos = ev->pos(); // 逻辑坐标 |
749 | | - QPointF pt = getRealPoint(mousePos); // 转换为虚拟坐标,使用 QPointF |
750 | | - click(pt); |
751 | | -} |
| 784 | +void ChessBoard::mouseReleaseEvent(QMouseEvent *ev) |
| 785 | +{ |
| 786 | + if (ev->button() != Qt::LeftButton || m_bIsOver== true) { // 排除鼠标右键点击 游戏已结束则直接返回 |
| 787 | + return; |
| 788 | + } |
| 789 | + |
| 790 | +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) |
| 791 | + const QPointF globalPos = ev->globalPosition(); |
| 792 | +#else |
| 793 | + const QPointF globalPos = ev->globalPos(); |
| 794 | +#endif |
| 795 | + const QPointF windowTopLeft = mapToGlobal(QPoint(0, 0)); |
| 796 | + const QPointF mousePos = globalPos - windowTopLeft; // 统一转换为 ChessBoard 坐标系 |
| 797 | + |
| 798 | + QPointF pt = getRealPoint(mousePos); // 转换为虚拟坐标 |
| 799 | + click(pt); |
| 800 | +} |
752 | 801 |
|
753 | 802 | void ChessBoard::click(QPointF pt) |
754 | 803 | { |
|
0 commit comments