画板
由于画板是我第一次真正意义上的接触JAVA项目,所以有的地方可能不太完善,现在把写画板的过程回顾一下,这是运行出来的结果:
这个画板的界面MainFrame的布局设置成了边框布局,North位置是菜单栏JMenuBar,West位置是存放工具按钮的ToolsPanel,Center 位置是画图面板DrawPanel,South位置是放了一个存放选择颜色按钮的SelectPanel面板和存放所有颜色按钮的AllPanel面板的大面板。这是设计的第一阶段,设计好各控件的大致分布。
<span style="font-size:14px;"> //增加菜单
Menu mn=new Menu(this);
add(mn,BorderLayout.NORTH);
//增加工具面板
toolsPanel=new ToolsPanel(this);
add(toolsPanel,BorderLayout.WEST);
//添加画板
drawPanel=new DrawPanel(this);
add(drawPanel,BorderLayout.CENTER);
//添加颜色面板
colorPanel=new ColorPanel(this);
add(colorPanel,BorderLayout.SOUTH);</span>
第二阶段就是为颜色按钮和工具按钮增加监听,主要是根据鼠标在DrawPanel的发生的事件和触发的工具按钮画出相应的图形。以矩形为例,先在ToolsPanel单击矩形按钮,触发监听器DrawMouseListener(),首先获取画笔,然后利用监听器获取鼠标在画图面板mousePressed时的坐标(x1,y1)和mouseReleased时的坐标(x2,y2),用画笔的setColor(Color c)方法设置矩形的边框颜色和填充颜色,用画笔以这两点作为矩形斜对角的两顶点画出一个矩形,如下:
<span style="font-size:14px;"> graphics.setColor(bkColor);
graphics.drawRect(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x1-x2), Math.abs(y1-y2));
graphics.setColor(tcColor);
graphics.fillRect(Math.min(x1, x2)+1, Math.min(y1, y2)+1, Math.abs(x1-x2)-1, Math.abs(y1-y2)-1);</span></span>
图中边框颜色为绿色,填充颜色为红色。
矩形、直线、椭圆、圆角矩形是一样的原理,代码相似;而像铅笔、橡皮等需要拖动的图形则是在mouseDragged的过程中即时获取坐标并画短直线并使用相应的颜色。
第三阶段就是增加了撤销Undo和恢复Redo功能,具体实现就是将各个图形封装成一个实现了Shape接口的对象,在创建一个Shape数组,将这些对象存放到数组中,利用数组中的元素增加或减少使用重绘方法repaint()实现此功能。
五子棋
运行结果如下:
左边面板是下棋面板,右边是功能设置面板上面添加了几个按钮,用来实现一些小功能,比如开始和重新开始,悔棋等。在左边面板花了网格线,下棋时通过计算离鼠标点击处最近的线的交叉点,然后在此处画棋子设置标志位来判断棋子的颜色,用一个二维数组来保存棋子在棋盘中的位置,通过删除元素然后重绘来实现悔棋功能
<span style="font-size:14px;"><span style="font-size:14px;"> if(LeftPanel.BorderFlag==false)
{
JOptionPane.showMessageDialog(mf, "请先开始!");
return;
}
//获取鼠标单击处的坐标
int x=e.getX();
int y=e.getY();
//如果鼠标单击在棋盘外则不落棋子
if(x>400||y>400||x<10||y<10)
{
return;
}
else
{
//获取离鼠标单击处最近的棋盘线交叉点坐标
x=x%20>10 ? (x/20+1)*20 : (x/20)*20;
y=y%20>10 ? (y/20+1)*20 : (y/20)*20;
//判断该交叉点是否已经落子
if(allChess[x/20][y/20]!=0)
{
JOptionPane.showMessageDialog(mf, "不能下了");
return;
}
Graphics gg=g.getGraphics();
if(flag)
{
//画黑色棋子
gg.setColor(Color.BLACK);
gg.fillOval(x-9, y-9, 20, 20);
//改变对应二维数组
allChess[x/20][y/20]=1;
//判断输赢
JudgeMent jm=new JudgeMent(x/20,y/20,mf);
jm.Judge();
//改变存放棋子的悔棋二维数组
RightPanel.chehui[RightPanel.i][0]=x/20;
RightPanel.chehui[RightPanel.i][1]=y/20;
RightPanel.i++;
//改变步数
RightPanel.jb5.setText("步数:"+RightPanel.i);
}
else
{
//画白子
gg.setColor(Color.WHITE);
gg.fillOval(x-9, y-9, 20, 20);
allChess[x/20][y/20]=2;
//判断输赢
JudgeMent jm=new JudgeMent(x/20,y/20,mf);
jm.Judge();
//改变悔棋二维数组
RightPanel.chehui[RightPanel.i][0]=x/20;
RightPanel.chehui[RightPanel.i][1]=y/20;
RightPanel.i++;
RightPanel.jb5.setText("步数:"+RightPanel.i);
}
flag=!flag;
mf.repaint();
</span></span>
退出按钮监听则是调用了JFrame的dispose()方法;显示步数就是设置一静态变量,初始为0,落子加1,悔棋减1,重新开始则清零。