Qt中国象棋二——棋盘与棋子的绘制

上次和大家分享了Qt的2D绘图基础知识,这样可以更好地理解象棋中一些关于绘图的程序。这次要和大家分享的则是棋盘与棋子的绘制,也可以说是Qt 2D绘图的一些具体应用。

 

源程序是我在网上找的,而且是下载了好几个,之后会把这些程序融合下。

 

一、 绘制棋盘

主窗体是继承MainWidget的,将棋盘设置为背景图片,到这棋盘就绘制好了。惊喜吧~

640?wx_fmt=png

绘制程序也很少:

    //窗口以棋盘图片为大小	
    QPixmap pixChessBoard(":/image/Resources/image/chessBoard.png");	
    setFixedSize(pixChessBoard.size());	

	
    QPalette palette(this->palette());	
    palette.setBrush( QPalette::Window,QBrush(pixChessBoard));	
    this->setPalette(palette);

之后说明下程序中用到的几个宏定义:

#define RECT_WIDTH    55	
#define RECT_HEIGHT    56	

	
#define START_X  (35 - RECT_WIDTH/2)      	
#define START_Y  (45 - RECT_HEIGHT/2)

① RECT_WIDTH 棋盘图片方格的像素宽度,对应下图中1到2的像素距离

② RECT_HEIGHT 棋盘图片方格的像素高度,对应下图中2到3的像素距离

③ 35,45 是棋盘左上角像素坐标,即与1对应

④ START_X,START_Y 计算棋子位置的起点像素坐标,如图4的像素坐标

 

640?wx_fmt=png

 

二、 绘制棋子

 

1. 棋子属性类(Item) 的定义

棋子属性类中主要包括棋子类型,如車、马、相、士、炮、兵、将

棋子颜色                    ,红色、黑色

棋子位置                    ,QPoint 等

Item::Item(ITEM_TYPE t,ITEM_COLOR c,QPoint pt)	
{	
    m_type = t;	
    m_color = c;	
    m_pt = pt;	
    m_bShow = true;	
}

 

2. 初始化黑色棋子的逻辑属性

主要是初始化棋子的类型与逻辑位置。

void MainWindow::initItems()	
{	
    m_items.clear();	

	
    //初始化所有黑方棋子	
    Item item1(ITEM_JU,COLOR_BLACK,QPoint(0,0));	
    Item item2(ITEM_MA,COLOR_BLACK,QPoint(1,0));	
    Item item3(ITEM_XIANG,COLOR_BLACK,QPoint(2,0));	
    Item item4(ITEM_SHI,COLOR_BLACK,QPoint(3,0));	
    Item item5(ITEM_SHUAI,COLOR_BLACK,QPoint(4,0));	
    Item item6(ITEM_SHI,COLOR_BLACK,QPoint(5,0));	
    Item item7(ITEM_XIANG,COLOR_BLACK,QPoint(6,0));	
    Item item8(ITEM_MA,COLOR_BLACK,QPoint(7,0));	
    Item item9(ITEM_JU,COLOR_BLACK,QPoint(8,0));	
    Item item10(ITEM_PAO,COLOR_BLACK,QPoint(1,2));	
    Item item11(ITEM_PAO,COLOR_BLACK,QPoint(7,2));	
    Item item12(ITEM_BING,COLOR_BLACK,QPoint(0,3));	
    Item item13(ITEM_BING,COLOR_BLACK,QPoint(2,3));	
    Item item14(ITEM_BING,COLOR_BLACK,QPoint(4,3));	
    Item item15(ITEM_BING,COLOR_BLACK,QPoint(6,3));	
    Item item16(ITEM_BING,COLOR_BLACK,QPoint(8,3));	

	
    m_items.push_back(item1);	
    m_items.push_back(item2);	
    m_items.push_back(item3);	
    m_items.push_back(item4);	
    m_items.push_back(item5);	
    m_items.push_back(item6);	
    m_items.push_back(item7);	
    m_items.push_back(item8);	
    m_items.push_back(item9);	
    m_items.push_back(item10);	
    m_items.push_back(item11);	
    m_items.push_back(item12);	
    m_items.push_back(item13);	
    m_items.push_back(item14);	
    m_items.push_back(item15);	
    m_items.push_back(item16);	
}

 

3. 绘制棋子

①从图片中切割棋子

资源文件中棋子是这样的,通过drawPixmap(rcTarget,m_itemImage,rcSrc)函数将图片中指定的像素区域切割出来,然后绘制到棋盘上的目标区域,最后就看到棋盘上有棋子的效果了。

 

640?wx_fmt=png

这里所有绘制的动作都是在void paintEvent(QPaintEvent *)绘图事件中完成的。

void MainWindow::paintEvent(QPaintEvent *)	
{	
    QPainter painter(this);	
    for (int i = 0; i<m_items.size(); i++)	
    {	
        drawItem(painter,m_items[i]);	
    }	

	
# if 0   //方便理解棋盘中宏定义的位置	
    painter.setPen(QPen(Qt::blue,5));	
    painter.drawPoint(35,45);	

	
    painter.drawPoint(90,45);	
    painter.drawPoint(90,101);	

	
    painter.drawPoint(START_X,START_Y);	
#endif	

	
//    update();	
}

② 绘制棋子

 

OK,接下来看下drawItem()

painter 是事件中传入的,

item 是类中定义所有棋子属性的容器,QVector<Item> m_items;

 

void MainWindow::drawItem(QPainter &painter, Item item)	
{	
    if (!item.m_bShow)	
    {	
        return;	
}	
//根据顺序切割棋子图片像素位置	
QRect rcSrc(m_nItemWidth*item.m_color,m_nItemHeight*item.m_type,	
m_nItemWidth,m_nItemHeight);	

	
//将对应棋子的逻辑位置映射为棋盘上的像素位置	
    QRect rcTarget( START_X + item.m_pt.x()*RECT_WIDTH,	
                    START_Y + item.m_pt.y()*RECT_HEIGHT,	
                    RECT_WIDTH,RECT_HEIGHT);	

	
//在棋盘上绘制m_itemImage中对应的像素棋子	
    painter.drawPixmap(rcTarget,m_itemImage,rcSrc);	
}

 

最终就是下面这样:

640?wx_fmt=png

 

下次和大家分享的则是对棋子的操作,主要通过鼠标事件来完成,这次的则是通过绘图事件来完成的。通过本次的练习结合上次所说的,大家会对Qt的绘图事件有一个整体的概念了。Qt是基于事件驱动的,以后对这句话的理解会越来越深刻的。

对了,如果觉得有帮助,欢迎关注:

640?wx_fmt=png

下面是一个简单的例子,使用Qt绘制中国象棋棋盘。 首先,我们需要在Qt的窗口中创建一个QPainter对象,然后通过QPainter对象绘制棋盘。 ```cpp void ChessBoard::paintEvent(QPaintEvent *event) { QPainter painter(this); int squareSize = width() / 10; // 绘制棋盘 painter.setBrush(QColor("#D18B47")); painter.drawRect(0, 0, 9 * squareSize, 10 * squareSize); painter.fillRect(squareSize, squareSize, 8 * squareSize, 8 * squareSize, QColor("#F0D9B5")); for (int i = 0; i < 9; ++i) { painter.drawLine((i + 1) * squareSize, squareSize, (i + 1) * squareSize, 9 * squareSize); } painter.drawLine(squareSize, squareSize, 9 * squareSize, squareSize); painter.drawLine(squareSize, 9 * squareSize, 9 * squareSize, 9 * squareSize); // 绘制棋盘上的点 painter.setBrush(Qt::black); painter.drawEllipse(QPoint(4 * squareSize, 3 * squareSize), 5, 5); painter.drawEllipse(QPoint(6 * squareSize, 3 * squareSize), 5, 5); painter.drawEllipse(QPoint(4 * squareSize, 6 * squareSize), 5, 5); painter.drawEllipse(QPoint(6 * squareSize, 6 * squareSize), 5, 5); } ``` 在上面的代码中,我们使用QPainter对象的drawRect()和fillRect()方法绘制棋盘的外框和内部,使用drawLine()方法绘制棋盘上的线条,使用drawEllipse()方法绘制棋盘上的点。 在这个例子中,我们将棋盘的大小设置为窗口宽度的10分之9,并将棋盘上每个格子的大小设置为窗口宽度的10分之1。 ```cpp int squareSize = width() / 10; ``` 最后,我们需要在QWidget的构造函数中启用绘图功能: ```cpp ChessBoard::ChessBoard(QWidget *parent) : QWidget(parent) { setFixedSize(9 * squareSize, 10 * squareSize); } ``` 完整的代码可以参考以下代码: ```cpp #include <QtWidgets> class ChessBoard : public QWidget { public: ChessBoard(QWidget *parent = 0) : QWidget(parent) { setFixedSize(9 * squareSize, 10 * squareSize); } protected: void paintEvent(QPaintEvent *event) override { QPainter painter(this); int squareSize = width() / 10; // 绘制棋盘 painter.setBrush(QColor("#D18B47")); painter.drawRect(0, 0, 9 * squareSize, 10 * squareSize); painter.fillRect(squareSize, squareSize, 8 * squareSize, 8 * squareSize, QColor("#F0D9B5")); for (int i = 0; i < 9; ++i) { painter.drawLine((i + 1) * squareSize, squareSize, (i + 1) * squareSize, 9 * squareSize); } painter.drawLine(squareSize, squareSize, 9 * squareSize, squareSize); painter.drawLine(squareSize, 9 * squareSize, 9 * squareSize, 9 * squareSize); // 绘制棋盘上的点 painter.setBrush(Qt::black); painter.drawEllipse(QPoint(4 * squareSize, 3 * squareSize), 5, 5); painter.drawEllipse(QPoint(6 * squareSize, 3 * squareSize), 5, 5); painter.drawEllipse(QPoint(4 * squareSize, 6 * squareSize), 5, 5); painter.drawEllipse(QPoint(6 * squareSize, 6 * squareSize), 5, 5); } private: int squareSize = width() / 10; }; int main(int argc, char *argv[]) { QApplication app(argc, argv); ChessBoard board; board.show(); return app.exec(); } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值