Skip to content

Commit 03647d4

Browse files
committed
ifix: picking at 1080p 100% scaling
close #44
1 parent 7dd96d9 commit 03647d4

File tree

3 files changed

+122
-67
lines changed

3 files changed

+122
-67
lines changed

ChessBoard.cpp

Lines changed: 99 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,28 @@
77
#include "ui_ChessBoard.h"
88
#include <mutex>
99

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+
{
1414
init();
1515

1616
//计时器部分
1717
m_timer = new QTimer; //初始化定时器
1818
m_timeRecord = new QTime(0, 0, 0); //初始化时间
1919
m_bIsStart = false; //初始为还未计时
2020
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+
}
2732

2833
ChessBoard::~ChessBoard()
2934
{
@@ -183,22 +188,53 @@ QPointF ChessBoard::center(int row, int col)
183188
}
184189

185190
//重载:坐标转换
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+
202238
//*******************绘画棋盘*******************
203239
//绘画10条横线
204240
for(int i = 0; i <= 9; i++)
@@ -239,12 +275,13 @@ void ChessBoard::paintEvent(QPaintEvent *)
239275
if(m_bIsShowStep)
240276
drawLastStep(painter,m_ChessSteps);
241277

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+
}
248285

249286
void ChessBoard::drawChessPieces(QPainter &painter, int id) //绘画单个具体的棋子
250287
{
@@ -361,15 +398,19 @@ void ChessBoard::winMessageBox(QString title, QString msg)
361398
message.exec();
362399
}
363400

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+
}
373414

374415
bool ChessBoard:: isGeneral()
375416
{
@@ -740,15 +781,23 @@ bool ChessBoard:: canSelect(int id)
740781
return m_bIsRed== m_ChessPieces[id].m_bRed;
741782
}
742783

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+
}
752801

753802
void ChessBoard::click(QPointF pt)
754803
{

ChessBoard.h

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,10 @@ class ChessBoard : public QMainWindow
6969
void whoWin(); // 谁胜谁负
7070
bool isChecked(QPointF pt, int& row, int& col); // 是否选中该枚棋子。pt为输入参数; row, col为输出参数
7171
int relation(int row1, int col1, int row2, int col2); // 计算选中的棋子的位置和要移动的位置之间的位置关系
72-
QPointF getRealPoint(QPointF pt); // 使mouseMoveEvent取得的坐标同Painter的坐标一致
73-
bool isGeneral(); // 校验将移动后位置是否将死
74-
void showNetworkGui(const bool& show = false);
75-
72+
QPointF getRealPoint(QPointF pt); // 使mouseMoveEvent取得的坐标同Painter的坐标一致
73+
bool isGeneral(); // 校验将移动后位置是否将死
74+
void showNetworkGui(const bool& show = false);
75+
7676
private:
7777
bool hongMenFeast(); // 鸿门宴:对将
7878
bool havePieces(int row, int col); // 判断某一格子,是否有棋子
@@ -81,14 +81,15 @@ class ChessBoard : public QMainWindow
8181

8282
public:
8383
//视图相关
84-
QPointF center(int row, int col); // 象棋的棋盘的坐标转换成界面坐标
85-
QPointF center(int id);
86-
virtual void paintEvent(QPaintEvent *); // 绘画棋盘
87-
void drawChessPieces(QPainter& painter, int id); // 绘画单个具体的棋子
88-
void drawLastStep(QPainter &painter, QVector<ChessStep*>& steps); // 绘制上次移动棋子的起止位置
89-
void drawTextStep(); // 绘制文本棋谱
90-
// virtual void mousePressEvent(QMouseEvent *); // 鼠标点击事件
91-
// virtual void clickPieces(int checkedID, int& row, int& col);
84+
QPointF center(int row, int col); // 象棋的棋盘的坐标转换成界面坐标
85+
QPointF center(int id);
86+
virtual void paintEvent(QPaintEvent *); // 绘画棋盘
87+
void drawChessPieces(QPainter& painter, int id); // 绘画单个具体的棋子
88+
void drawLastStep(QPainter &painter, QVector<ChessStep*>& steps); // 绘制上次移动棋子的起止位置
89+
void drawTextStep(); // 绘制文本棋谱
90+
// virtual void mousePressEvent(QMouseEvent *); // 鼠标点击事件
91+
// virtual void clickPieces(int checkedID, int& row, int& col);
92+
bool boardTransform(QPointF& origin, qreal& side) const; // 计算棋盘绘制和点击的起点与边长
9293

9394
// 象棋移动的规则[将 士 象 马 车 炮 兵]
9495
bool canMove(int moveId, int killId, int row, int col);

MachineGame.cpp

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -128,11 +128,16 @@ void MachineGame::mousePressEvent(QMouseEvent *ev)
128128
return;
129129
}
130130

131-
int row, col;
132-
QPointF pt = getRealPoint(ev->pos()); // 转换为虚拟坐标,使用 QPointF
133-
if (!isChecked(pt, row, col)) { // 使用 QPointF 调用 isChecked
134-
return;
135-
}
131+
int row, col;
132+
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
133+
const QPointF logicalPos = ev->position();
134+
#else
135+
const QPointF logicalPos = ev->pos();
136+
#endif
137+
QPointF pt = getRealPoint(logicalPos); // 转换为虚拟坐标
138+
if (!isChecked(pt, row, col)) {
139+
return;
140+
}
136141

137142
m_nCheckedID = -1;
138143

0 commit comments

Comments
 (0)