50

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

 4 years ago
source link: http://mp.weixin.qq.com/s?__biz=MzUxMTk4MzY3MA%3D%3D&%3Bmid=2247484083&%3Bidx=1&%3Bsn=93deedff5a81fffc972de7951d46c864
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

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

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

一、  绘制棋盘

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

zQBzyqf.png!web

绘制程序也很少:

//窗口以棋盘图片为大小

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 的像素坐标

aqYBJ3A.jpg!web

二、  绘制棋子

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) 函数将图片中指定的像素区域切割出来,然后绘制到棋盘上的目标区域,最后就看到棋盘上有棋子的效果了。

qamAfiU.jpg!web

这里所有绘制的动作都是在 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  是事件中传入的,

i tem   是类中定义所有棋子属性的容器, 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);

}

最终就是下面这样:

Vrqy2a3.jpg!web

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

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

NfqIJfB.png!web


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK