文章目录

  • 事件处理
    • GUI事件处理机制
    • 常见事件和事件监听器
      • 低级事件
      • 高级事件
      • 事件监听器分类
  • 菜单组件
  • 组件绘图原理
    • Graphics类
    • 处理位图
    • ImageIO的使用
  • 五子棋

事件处理

在 AWT 编程中 ,所有用户的操作,都必须都需要经过一套事件处理机制来完成,而 Frame 和组件本身并没有事件处理能力。

GUI事件处理机制

在某个组件上发生某些操作的时候,会自动的触发一段代码的执行。

事件源(Event Source):操作发生的场所,通常指某个组件,例如按钮、窗口等;
事件(Event):在事件源上发生的操作可以叫做事件,GUI会把事件都封装到一个Event对象中,如果需要知道该事件的详细信息,就可以通过Event对象来获取。
事件监听器(Event Listener):当在某个事件源上发生了某个事件,事件监听器就可以对这个事件进行处理。
注册监听:把某个事件监听器(A)通过某个事件(B)绑定到某个事件源©上,当在事件源C上发生了事件B之后,那么事件监听器A的代码就会自动执行。

public class EventDemo1 {Frame frame=new Frame("这是文件处理");TextField tf=new TextField(30);//创建事件源对象JButton button=new JButton("确定");public  void init(){//创建监听器对象MyListener myListener=new MyListener();//注册监听button.addActionListener(myListener);frame.add(tf,BorderLayout.NORTH);frame.add(button);frame.pack();frame.setVisible(true);}
//自定义内部类,实现接口,重写方法private class MyListener implements ActionListener{@Overridepublic void actionPerformed(ActionEvent e) {tf.setText("hello world");}}
}

常见事件和事件监听器

事件监听器必须实现事件监听器接口, AWT 提供了大量的事件监听器接口用于实现不同类型的事件监听器,用于监听不同类型的事件 。 AWT 中提供了丰富的事件类,用于封装不同组件上所发生的特定操作, AWT 的事件类都是 AWTEvent 类的子类 , AWTEvent是 EventObject 的子类。

低级事件

这类事件是基于某个特定动作的事件。比如进入、点击、拖放等动作的鼠标事件,再比如得到焦点和失去焦点等焦点事件。

高级事件

这类事件并不会基于某个特定动作,而是根据功能含义定义的事件。

事件监听器分类

不同的事件需要使用不同的监听器监听,不同的监听器需要实现不同的监听器接口, 当指定事件发生后 , 事件监听器就会调用所包含的事件处理器(实例方法)来处理事件 。

public class ListenerDemo1 {public static void main(String[] args) {Frame frame = new Frame("这里测试监听器");//创建一个单行文本域TextField tf = new TextField(30);//给文本域添加TextListener,监听内容的变化tf.addTextListener(new TextListener() {@Overridepublic void textValueChanged(TextEvent e) {System.out.println("当前内容:"+tf.getText());;}});//给frame注册ContainerListener监听器,监听容器中组件的添加frame.addContainerListener(new ContainerAdapter() {@Overridepublic void componentAdded(ContainerEvent e) {Component child = e.getChild();System.out.println("容器中添加了新组件:"+child);}});//添加tf到frameframe.add(tf);//设置frame最佳大小并可见frame.pack();frame.setVisible(true);}
}
//用户点击错号即可关闭
public class ListenerDemo2 {public static void main(String[] args) {Frame frame = new Frame("这里测试WindowListener");frame.addWindowListener(new WindowAdapter() {//文件适配器WindowAdapter,根据自己选择选取内部方法@Overridepublic void windowClosing(WindowEvent e) {System.exit(0);}});frame.setBounds(200,200,500,300);frame.setVisible(true);}
}

菜单组件

在实际开发中,除了主界面,还有一类比较重要的内容就是菜单相关组件,可以通过菜单相关组件很方便的使用特定的功能,在AWT中,菜单相关组件的使用和之前学习的组件是一模一样的,只需要把菜单条、菜单、菜单项组合到一起,按照一定的布局,放入到容器中即可。
(1)常见的菜单组件:

菜单组件名称 功能
MenuBar 菜单条 , 菜单的容器 。
Menu 菜单组件 , 菜单项的容器 。 它也是Menultem的子类 ,所以可作为菜单项使用
PopupMenu 上下文菜单组件(右键菜单组件)
Menultem 菜单项组件 。
CheckboxMenuItem 复选框菜单项组件

(2)菜单相关组件的使用:

1.准备菜单项组件,这些组件可以是MenuItem及其子类对象。
2.准备菜单组件Menu或者PopupMenu(右击弹出子菜单),把第一步中准备好的菜单项组件添加进来。
3.准备菜单条组件MenuBar,把第二步中准备好的菜单组件Menu添加进来。
4.把第三步中准备好的菜单条组件添加到窗口对象中显示。

(3)相关技巧:

1.如果要在某个菜单的菜单项之间添加分割线,那么只需要调用Menu的add(new MenuItem(-))即可。

2.如果要给某个菜单项关联快捷键功能,那么只需要在创建菜单项对象时设置即可,例如给菜单项关联 ctrl+shif+/ 快捷键,只需要:new MenuItem("菜单项名字",newMenuShortcut(KeyEvent.VK_Q,true);

public class SimpleMenu {//创建窗口private Frame frame = new Frame("这里测试菜单相关组件");//创建菜单条组件private MenuBar menuBar = new MenuBar();//创建文件菜单组件private Menu fileMenu = new Menu("文件");//创建编辑菜单组件private Menu editMenu = new Menu("编辑");//创建格式菜单private Menu formatMenu = new Menu("格式");//创建新建菜单项private MenuItem newItem = new MenuItem("新建");//创建保存菜单项private MenuItem saveItem = new MenuItem("保存");//创建退出菜单项private MenuItem exitItem = new MenuItem("退出");//创建自动换行选择框菜单项private CheckboxMenuItem autoWrap = new CheckboxMenuItem("自动换行");//创建复制菜单项private MenuItem copyItem = new MenuItem("复制");//创建粘贴菜单项private MenuItem pasteItem = new MenuItem("粘贴");//创建注释菜单项private MenuItem commentItem = new MenuItem("注释");//创建取消注释菜单项private MenuItem cancelItem = new MenuItem("取消注释");//创建一个文本域private TextArea ta = new TextArea(6, 40);public void init(){//定义菜单事件监听器ActionListener listener = new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {String command = e.getActionCommand();ta.append("单击“"+command+"”菜单\n");if (command.equals("退出")){System.exit(0);}}};//为注释菜单项和退出菜单项注册监听器commentItem.addActionListener(listener);exitItem.addActionListener(listener);//为文件菜单fileMenu添加菜单项fileMenu.add(newItem);fileMenu.add(saveItem);fileMenu.add(exitItem);//为编辑菜单editMenu添加菜单项editMenu.add(autoWrap);editMenu.add(copyItem);editMenu.add(pasteItem);//为格式化菜单formatMenu添加菜单项formatMenu.add(commentItem);formatMenu.add(cancelItem);//将格式化菜单添加到编辑菜单中,作为二级菜单editMenu.add(new MenuItem("-"));editMenu.add(formatMenu);//将文件菜单和编辑菜单添加到菜单条中menuBar.add(fileMenu);menuBar.add(editMenu);//把菜单条设置到frame窗口上frame.setMenuBar(menuBar);//把文本域添加到frame中frame.add(ta);//设置frame最佳大小并可见frame.pack();frame.setVisible(true);}public static void main(String[] args) {new SimpleMenu().init();}
}
public class PopupMenuTest {private Frame frame = new Frame("这里测试PopupMenu");//创建PopubMenu菜单private PopupMenu popupMenu = new PopupMenu();//创建菜单条private MenuItem commentItem = new MenuItem("注释");private MenuItem cancelItem = new MenuItem("取消注释");private MenuItem copyItem = new MenuItem("复制");private MenuItem pasteItem = new MenuItem("保存");//创建一个文本域private TextArea ta = new TextArea("我爱中华!!!", 6, 40);//创建一个Panelprivate  Panel panel = new Panel();public void init(){//把菜单项添加到PopupMenu中popupMenu.add(commentItem);popupMenu.add(cancelItem);popupMenu.add(copyItem);popupMenu.add(pasteItem);//设置panel大小panel.setPreferredSize(new Dimension(300,100));//把PopupMenu添加到panel中panel.add(popupMenu);//为panel注册鼠标事件panel.addMouseListener(new MouseAdapter() {@Overridepublic void mouseReleased(MouseEvent e) {boolean flag = e.isPopupTrigger();//判断当前鼠标操作是不是触发PopupMenu的操作if (flag){//让PopupMenu显示在panel上,并且跟随鼠标事件发生的地方显示popupMenu.show(panel,e.getX(),e.getY());}}});//把ta添加到frame中间区域中frame.add(ta);//把panel添加到frame底部frame.add(panel,BorderLayout.SOUTH);//设置frame最佳大小,并可视;frame.pack();frame.setVisible(true);}public static void main(String[] args) {new PopupMenuTest().init();}}

组件绘图原理

在AWT中,真正提供绘图功能的是Graphics对象,那么Component组件和Graphics对象存在什么关系,才能让Component绘制自身图形呢?在Component类中,提供了下列三个方法来完成组件图形的绘制与刷新:

paint(Graphics g):绘制组件的外观;
update(Graphics g):内部调用paint方法,刷新组件外观;
repaint():调用update方法,刷新组件外观;


一般情况下,update和paint方法是由AWT系统负责调用,如果程序要希望系统重新绘制组件,可以调用repaint方法完成。

Graphics类

AWT中提供了Canvas类充当画布,提供了Graphics类来充当画笔,通过调用Graphics对象的setColor()方法可以给画笔设置颜色。

画图的步骤:
1.自定义类,继承Canvas类,重写paint(Graphics g)方法完成画图;
2.在paint方法内部,真正开始画图之前调用Graphics对象的setColor()、setFont()等方法设置画笔的颜色、字体等属性;
3.调用Graphics画笔的drawXxx()方法开始画图。

画图的核心:使用Graphics画笔在Canvas画布上画出什么颜色、什么样式的图形.

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;public class SimpleDraw {//标记画的是椭圆还是矩形private final String RECT_SHAPE="rect";private final String OVAL_SHAPE="oval";private Frame frame = new Frame("这里测试绘图");private Button drawRectBtn = new Button("绘制矩形");private Button drawOvalBtn = new Button("绘制椭圆");//定义变量用来保存当前用户需要绘制什么样的图形private String shape="";//创建画布private MyCanvas drawArea = new MyCanvas();public void init(){//为按钮添加点击事件drawRectBtn.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {shape = RECT_SHAPE;drawArea.repaint();}});drawOvalBtn.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {shape = OVAL_SHAPE;drawArea.repaint();}});//定义一个Panel,装载两个按钮Panel p = new Panel();p.add(drawRectBtn);p.add(drawOvalBtn);//把panel添加到frame底部frame.add(p,BorderLayout.SOUTH);//设置画布的大小drawArea.setPreferredSize(new Dimension(300,200));//把画布添加到frame中frame.add(drawArea);frame.pack();frame.setVisible(true);}public static void main(String[] args) {new SimpleDraw().init();}//1.自定义类,继承Canvas类,重写paint方法private class MyCanvas extends Canvas{@Overridepublic void paint(Graphics g) {Random r = new Random();if (shape.equals(RECT_SHAPE)){//绘制矩形g.setColor(Color.BLACK);g.drawRect(r.nextInt(200),r.nextInt(100),40,60);}if(shape.equals(OVAL_SHAPE)){//绘制椭圆g.setColor(Color.RED);g.drawOval(r.nextInt(200),r.nextInt(100),60,40);}}}}

Java也可用于开发一些动画。所谓动画,就是间隔一定的时间(通常小于0 . 1秒 )重新绘制新的图像,两次绘制的图像之间差异较小,肉眼看起来就成了所谓的动画 。

​为了实现间隔一定的时间就重新调用组件的 repaint()方法,可以借助于 Swing 提供的Timer类,Timer类是一个定时器, 它有如下一个构造器 :
Timer(int delay, ActionListener listener): 每间隔 delay 毫秒,系统自动触发 ActionListener 监听器里的事件处理器方法,在方法内部我们就可以调用组件的repaint方法,完成组件重绘。

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;public class PinBall {//桌面宽度private final int TABLE_WIDTH = 300;//桌面高度private final int TABLE_HEIGHT = 400;//球拍的高度和宽度private final int RACKET_WIDTH = 60;private final int RACKET_HEIGHT = 20;//小球的大小private final int BALL_SIZE = 16;//定义小球纵向运行速度private int ySpeed = 10;//小球横向运行速度private int xSpeed = 5;//定义小球的初始坐标private int ballX = 120;private int ballY = 20;//定义球拍的初始坐标,x坐标会发生变化,y坐标不会发生变化private int rackeX = 120;private final int RACKET_Y = 340;//声明定时器private Timer timer;//定义游戏结束的标记private boolean isLose = false;//声明一个桌面private MyCanvas tableArea = new MyCanvas();//创建窗口对象private Frame frame = new Frame("弹球游戏");public void init(){//设置桌面区域的最佳大小tableArea.setPreferredSize(new Dimension(TABLE_WIDTH,TABLE_HEIGHT));//把桌面添加到frame中frame.add(tableArea);//定义键盘监听器KeyListener keyListener = new KeyAdapter(){//监听键盘 ←  → 按下操作,当指定的键按下时,球拍的水平坐标分别会增加或者减少@Overridepublic void keyPressed(KeyEvent e) {int keyCode = e.getKeyCode();if (keyCode==KeyEvent.VK_LEFT){//←//没有到左边界,可以继续向左移动if (rackeX>0){rackeX-=10;}}if (keyCode==KeyEvent.VK_RIGHT){//→//没有到右边界,可以继续向右移动if (rackeX<TABLE_WIDTH-RACKET_WIDTH){rackeX+=10;}}}};//为窗口和tableArea分别添加键盘事件frame.addKeyListener(keyListener);tableArea.addKeyListener(keyListener);//定义ActionListener,用来监听小球的变化情况ActionListener timerTask = new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {//小球碰到左右边框if (ballX<=0 || ballX>=TABLE_WIDTH-BALL_SIZE){xSpeed=-xSpeed;}//小球的高度超出了球拍的位置,且横向不在球拍范围内,则游戏结束if (ballY > RACKET_Y && (ballX<rackeX || ballX>rackeX+RACKET_WIDTH)){//结束定时器timer.stop();//把游戏结束的标记设置为trueisLose = true;//重绘界面tableArea.repaint();}//如果小球横向在球拍范围内,且到达球拍位置或者到达顶端位置,则小球反弹if (ballY<=0 || (ballY>=RACKET_Y-BALL_SIZE && ballX>=rackeX && ballX<=rackeX+RACKET_WIDTH)){ySpeed=-ySpeed;}//更新小球的坐标ballX+=xSpeed;ballY+=ySpeed;//重绘桌面tableArea.repaint();}};//设置定时器,定时任务就是timerTasktimer = new Timer(100,timerTask);timer.start();//设置frame最佳大小,并可视frame.pack();frame.setVisible(true);}public static void main(String[] args) {new PinBall().init();}private class MyCanvas extends Canvas{//重写paint方法,实现绘图@Overridepublic void paint(Graphics g) {//判断游戏是否结束if (isLose){//结束g.setColor(Color.BLUE);g.setFont(new Font("Times",Font.BOLD,30));g.drawString("游戏结束!",50,200);}else{//没有结束//设置颜色并绘制小球g.setColor(Color.RED);g.fillOval(ballX,ballY,BALL_SIZE,BALL_SIZE);//设置颜色并绘制球拍g.setColor(Color.PINK);g.fillRect(rackeX,RACKET_Y,RACKET_WIDTH,RACKET_HEIGHT);}}}
}

处理位图

AWT 允许在组件上绘制位图, Graphics 提供了 drawlmage() 方法用于绘制位图,该方法需要一个Image参数一一代表位图,通过该方法就可以绘制出指定的位图 。

方法
1.创建Image的子类对象BufferedImage(int width,int height,int ImageType),创建时需要指定位图的宽高及类型属性;此时相当于在内存中生成了一张图片;

2.调用BufferedImage对象的getGraphics()方法获取画笔,此时就可以往内存中的这张图片上绘图了,绘图的方法和之前学习的一模一样;

3.调用组件的drawImage()方法,一次性的内存中的图片BufferedImage绘制到特定的组件上。

使用位图绘制组件的好处:

使用位图来绘制组件,相当于实现了图的缓冲区,此时绘图时没有直接把图形绘制到组件上,而是先绘制到内存中的BufferedImage上,等全部绘制完毕,再一次性的图像显示到组件上即可,这样用户的体验会好一些。

import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;public class HandDraw {//定义画图区的宽高private final int AREA_WIDTH = 500;private final int AREA_HEIGHT = 400;//定义变量,保存上一次鼠标拖动时,鼠标的坐标private int preX = -1;private int preY = -1;//定义一个右键菜单,用于设置画笔的颜色private PopupMenu colorMenu = new PopupMenu();private MenuItem redItem = new MenuItem("红色");private MenuItem greenItem = new MenuItem("绿色");private MenuItem blueItem = new MenuItem("蓝色");//定义一个BufferedImage对象private BufferedImage image = new BufferedImage(AREA_WIDTH,AREA_HEIGHT,BufferedImage.TYPE_INT_RGB);//获取BufferedImage对象关联的画笔private Graphics g = image.getGraphics();//定义窗口对象private Frame frame = new Frame("简单手绘程序");//定义画布对象private Canvas drawArea =  new Canvas(){@Overridepublic void paint(Graphics g) {//把位图image绘制到0,0坐标点g.drawImage(image,0,0,null);}};//定义一个Color对象,用来保存用户设置的画笔颜色,默认为黑色private Color forceColor = Color.BLACK;public void init(){//定义颜色菜单项单击监听器ActionListener menuListener = new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {String command = e.getActionCommand();switch (command){case "红色":forceColor=Color.RED;break;case "绿色":forceColor = Color.GREEN;break;case "蓝色":forceColor = Color.BLUE;break;}}};//为三个菜单项添加点击事件redItem.addActionListener(menuListener);greenItem.addActionListener(menuListener);blueItem.addActionListener(menuListener);//把菜单项添加到右键菜单中colorMenu.add(redItem);colorMenu.add(greenItem);colorMenu.add(blueItem);//把右键菜单添加到绘图区域drawAreadrawArea.add(colorMenu);//将iamge图片背景设置为白色g.fillRect(0,0,AREA_WIDTH,AREA_HEIGHT);//设置绘图区域drawArea的大小drawArea.setPreferredSize(new Dimension(AREA_WIDTH,AREA_HEIGHT));//绘图区域drawArea设置鼠标移动监听器drawArea.addMouseMotionListener(new MouseMotionAdapter() {//用于绘制图像@Overridepublic void mouseDragged(MouseEvent e) {//按下鼠标键并拖动会触发//如果上次鼠标的坐标在绘图区域,才开始绘图if (preX>0 && preY>0){//设置当前选中的画笔颜色g.setColor(forceColor);//绘制线条,需要有两组坐标,一组是上一次鼠标拖动鼠标时的坐标,一组是现在鼠标的坐标g.drawLine(preX,preY,e.getX(),e.getY());}//更新preX和preYpreX = e.getX();preY = e.getY();//重新绘制drawArea组件drawArea.repaint();}});drawArea.addMouseListener(new MouseAdapter() {//用于弹出右键菜单@Overridepublic void mouseReleased(MouseEvent e) {//松开鼠标键会触发boolean popupTrigger = e.isPopupTrigger();if (popupTrigger){//把colorMenu显示到drawArea画图区域,并跟随鼠标显示colorMenu.show(drawArea,e.getX(),e.getY());}//当鼠标松开时,把preX和preY重置为-1preX = -1;preY = -1;}});//把drawArea添加到frame中frame.add(drawArea);//设置frame最佳大小并可见frame.pack();frame.setVisible(true);}public static void main(String[] args) {new HandDraw().init();}
}

ImageIO的使用

软件都支持打开本地磁盘已经存在的图片,然后进行编辑,编辑完毕后,再重新保存到本地磁盘。我们可以用imageIO类来操作本地磁盘的图片文件。

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;public class ReadAndSaveImage {private Frame frame = new Frame("图片查看器");private BufferedImage image;private class MyCanvas  extends Canvas{@Overridepublic void paint(Graphics g) {if (image!=null){g.drawImage(image,0,0,image.getWidth(),image.getHeight(),null);}}}private MyCanvas imageComponent = new MyCanvas();public void init() throws Exception{//设置菜单项MenuBar mb = new MenuBar();Menu menu = new Menu("文件");MenuItem openItem = new MenuItem("打开");MenuItem saveItem = new MenuItem("另存为");openItem.addActionListener(e -> {//弹出对话框,选择本地图片FileDialog oDialog = new FileDialog(frame);oDialog.setVisible(true);//读取用户选择的图片String dir = oDialog.getDirectory();String file = oDialog.getFile();try {image = ImageIO.read(new File(dir,file));imageComponent.repaint();} catch (IOException e1) {e1.printStackTrace();}});saveItem.addActionListener(e -> {//弹出对话框,另存为FileDialog sDialog = new FileDialog(frame,"保存图片",FileDialog.SAVE);sDialog.setVisible(true);String dir = sDialog.getDirectory();String file = sDialog.getFile();try {ImageIO.write(image,"JPEG",new File(dir,file));} catch (IOException e1) {e1.printStackTrace();}});mb.add(menu);menu.add(openItem);menu.add(saveItem);frame.setMenuBar(mb);frame.add(imageComponent);frame.setBounds(200,200,800,600);frame.setVisible(true);frame.addWindowListener(new WindowAdapter() {@Overridepublic void windowClosing(WindowEvent e) {System.exit(0);}});}public static void main(String[] args) throws Exception {new ReadAndSaveImage().init();}
}

五子棋

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.File;public class Gobang {//定义三个BufferedImage,分别代表棋盘图、黑子图、白子图private BufferedImage table;private BufferedImage black;private BufferedImage white;//定义一个BufferedImage,代表当鼠标移动时将要下子的选择框private BufferedImage selected;//定义棋盘的宽高,这里的定义尺寸和给定的board.jpg图片的尺寸一致因为棋盘背景是通过图片加载的private final int TABLE_WIDTH = 535;private final int TABLE_HEIGHT = 536;//定义棋盘中,每行和每列可下子的数目,这个数目跟给定的board.jpg中的数目是一致的,都为15private final int  BOARD_SIZE = 15;//定义每个棋子所占棋盘总宽度的大小比率;每个棋子所占宽度 535/15=35private final int RATE = TABLE_WIDTH/BOARD_SIZE;//定义棋盘有效区域与背景图坐标之间的偏移值,x坐标右移5个像素,y坐标下移6个像素private final int X_OFFSET = 5;private final int Y_OFFSET = 6;/*定义一个二维数组充当棋盘上每个位置处的棋子;该数组的索引与该棋子在棋盘上的坐标需要有一个对应关系:例如: 索引[2][3]处的棋子,对一个的真实绘制坐标应该是:xpos = 2*RATE+X_OFFSET=75;ypos = 3*RATE+Y_OFFSET=111;*/private int[][] board = new int[BOARD_SIZE][BOARD_SIZE];//如果存储0,代表没有棋子,如果存储1,代表黑棋,如果存储2,代表白棋//定义五子棋游戏窗口private JFrame f = new JFrame("五子棋游戏");//定义五子棋游戏棋盘对应的Canvas组件private class ChessBoard extends JPanel{//重写paint方法,实现绘画@Overridepublic void paint(Graphics g) {//绘制五子棋棋盘g.drawImage(table,0,0,null);//绘制选中点的红框if (selectX>0 && selectY>0){g.drawImage(selected,selectX*RATE+X_OFFSET,selectY*RATE+Y_OFFSET,null);}//遍历数组,绘制棋子for (int i = 0; i < BOARD_SIZE; i++) {for (int j = 0; j < BOARD_SIZE; j++) {//绘制黑棋if (board[i][j]==1){g.drawImage(black,i*RATE+X_OFFSET,j*RATE+Y_OFFSET,null);}//绘制白棋if (board[i][j]==2){g.drawImage(white,i*RATE+X_OFFSET,j*RATE+Y_OFFSET,null);}}}}}private ChessBoard chessBoard = new ChessBoard();//定义变量,记录当前选中的坐标点对应的boad数组中对应的棋子索引;private int selectX = -1;private int selectY = -1;//定义一个变量,记录当前用户选择下的是白棋还是黑棋还是清除,清除:0,黑棋:1,白棋:2;private int chessCategory = 1;//定义Panel,放置点击按钮Panel p = new Panel();private Button whiteBtn = new Button("白棋");private Button blackBtn = new Button("黑棋");private Button clearBtn = new Button("删除");public void updateBtnColor(Color whiteBtnColor,Color blackBtnColor,Color clearBtnColor){whiteBtn.setBackground(whiteBtnColor);blackBtn.setBackground(blackBtnColor);clearBtn.setBackground(clearBtnColor);}public void init() throws Exception{//初始化按钮的颜色updateBtnColor(Color.LIGHT_GRAY,Color.GREEN,Color.LIGHT_GRAY);whiteBtn.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {chessCategory = 2;updateBtnColor(Color.GREEN,Color.LIGHT_GRAY,Color.LIGHT_GRAY);}});blackBtn.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {chessCategory=1;updateBtnColor(Color.LIGHT_GRAY,Color.GREEN,Color.LIGHT_GRAY);}});clearBtn.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {chessCategory=0;updateBtnColor(Color.LIGHT_GRAY,Color.LIGHT_GRAY,Color.GREEN);}});p.add(whiteBtn);p.add(blackBtn);p.add(clearBtn);//把Panel放入到frame底部f.add(p,BorderLayout.SOUTH);//初始化黑棋,白棋,棋盘,选中框table = ImageIO.read(new File("awt_demo\\board.jpg"));black = ImageIO.read(new File("awt_demo\\black.gif"));white = ImageIO.read(new File("awt_demo\\white.gif"));selected = ImageIO.read(new File("awt_demo\\selected.gif"));//初始化board数组,默认情况下,所有位置处都没有棋子for (int i = 0; i < BOARD_SIZE; i++) {for (int j = 0; j < BOARD_SIZE; j++) {board[i][j]=0;}}//设置chessBoard的最佳大小chessBoard.setPreferredSize(new Dimension(TABLE_WIDTH,TABLE_HEIGHT));//给chessBoard注册鼠标监听器chessBoard.addMouseListener(new MouseAdapter() {//鼠标单击会触发@Overridepublic void mouseClicked(MouseEvent e) {//将用户鼠标的坐标,转换成棋子的坐标int xPos = (e.getX()-X_OFFSET)/RATE;int yPos = (e.getY()-Y_OFFSET)/RATE;board[xPos][yPos] = chessCategory;//重绘chessBoardchessBoard.repaint();}//当鼠标退出棋盘区域后,复位选中坐标,重绘chessBoard,要保证红色选中框显示正确@Overridepublic void mouseExited(MouseEvent e) {selectX=-1;selectY=-1;chessBoard.repaint();}});//给chessBoard注册鼠标移动监听器chessBoard.addMouseMotionListener(new MouseMotionAdapter() {//当鼠标移动时,修正selectX和selectY,重绘chessBoard,要保证红色选中框显示正确@Overridepublic void mouseMoved(MouseEvent e) {//将鼠标的坐标,转换成棋子的索引selectX = (e.getX()-X_OFFSET)/RATE;selectY = (e.getY()-Y_OFFSET)/RATE;chessBoard.repaint();}});//把chessBoard添加到Frame中f.add(chessBoard);//设置frame最佳大小并可见f.pack();f.setVisible(true);}public static void main(String[] args) throws Exception{new Gobang().init();}}

图形用户界面GUI(二)相关推荐

  1. php做gui,php7 图形用户界面GUI如何开发

    php7 图形用户界面GUI如何开发?这篇文章主要介绍了php7 图形用户界面GUI 开发,结合实例形式分析了PHP7基于php_ui扩展实现的图形用户界面GUI相关操作技巧,感兴趣的用户就来一聚教程 ...

  2. php7可以做什么开发,php7 图形用户界面GUI 开发怎么做?看完这个代码你就明白了...

    [摘要]php7作为PHP的一个版本,也能实现很多功能,不过今天环球网校的小编要为大家讲解php7 图形用户界面GUI 开发怎么做?看完这个代码你就明白了,因为只要你了解了php7 图形用户界面GUI ...

  3. gui设置可编辑文本框的回调函数_用Tkinter制作Python程序的图形用户界面(GUI),打包后比Qt5减少60M(77.5%)(实例63)...

    实例61使用PyQt5制作了图形用户界面(GUI).这个香是香,但是打包后的安装文件太大(约80M),感觉有些美中不足啊.由于这个GUI实在简单,从现实角度实在用不着高大上的PyQt5,所以改用Pyt ...

  4. button点击后出现的边框_用Tkinter制作Python程序的图形用户界面(GUI),打包后比Qt5减少60M(77.5%)(实例63)...

    实例61使用PyQt5制作了图形用户界面(GUI).这个香是香,但是打包后的安装文件太大(约80M),感觉有些美中不足啊.由于这个GUI实在简单,从现实角度实在用不着高大上的PyQt5,所以改用Pyt ...

  5. 安装PHP7的图形用户界面(GUI) 扩展

    今天翻了翻PHP手册,无意中发现这个PHP7才加入的新扩展:图形用户界面(GUI) 扩展 PHP-UI,觉得挺有意思的,2016年10月才发布的,网上搜了一圈发现几乎没有相关资讯,连安装说明都没有一个 ...

  6. Java高级教程3_图形用户界面GUI

    张老师的Java高级教程中图形用户界面GUI对应的笔记 网络编辑器还要重新排版,提供原始文件下载,先看个概貌 Java高级3_图形用户界面GUI AWT的基础知识 GUI:Graphical User ...

  7. java图形界面包_抽象窗口工具包( )是java提供的建立图形用户界面GUI的开发包

    抽象窗口工具包( )是java提供的建立图形用户界面GUI的开发包 劈指是用大指弹奏的.A:对B:错 要保证权利与义务相对等,寿险保费的计算就必须遵循收支平衡的原则.A:对B:错 抽样平均误差的实质是 ...

  8. 【单片机学习笔记】(28):图形用户界面(GUI),串口通信协议与匿名上位机,获取MPU6050欧拉角,H桥电路、制作风力摆(空心杯电机、TB6612)

    Graphical User Interface(GUI) (OLED)使用图形用户界面 简易菜单 菜单和各种显示都放到main.c里面,要显示的数据经过字符转化之后放到buff里面再 调用显示 . ...

  9. 使用MATLAB GUI创建图形用户界面GUI

    MATLAB是众多理工科学生及工程师经常使用的一款数学软件,除了可以实现数据处理,矩阵运算.函数绘制等功能外,MATLAB还可以实现图形用户界面的设计. 下面介绍如何让小白也能用GUI创建最基本的用户 ...

  10. Python之图形用户界面--GUI

    GUI是Graphical User Interface(图形用户界面)的缩写.在GUI中,并不只是键入文本和返回文本,用户可以看到窗口.按钮.文本框等图形,而且可以用鼠标点击,还可以通过键盘键入.我 ...

最新文章

  1. 猪八戒网CI/CD最佳实践之路
  2. 【响应式Web前端设计】CSS3伪类与伪元素的区别
  3. python 文件和路径操作函数小结
  4. linux efi 双系统,EFI+GPT模式下Linux与Windows双系统要诀
  5. 《Python Cookbook 3rd》笔记(1.17):从字典中提取子集
  6. 上位机和下位机的概念,理解如何实现PC从PLC中读取数据?
  7. 6. 以下耦合度中最松散的耦合是_什么是程序设计中的高内聚、低耦合?
  8. sql azure 语法_Azure Kubernetes服务(AKS)–管理SQL Server数据库文件
  9. 分布式搜索Elasticsearch——QueryBuilders.matchPhrasePrefixQuery
  10. 23种设计模式(八)对象创建之抽象工厂
  11. java 图片合成pdf_Java将图片组合成PDF文件的方法
  12. Java内存模型详解
  13. 群晖系统硬盘损毁的修复
  14. python socket基于TCP/IP协议实现多人聊天室
  15. 我们的管理:项目管理
  16. 串口通信-电脑控制单片机点亮LED
  17. Apache中间件漏洞深析
  18. Pass! (bsgs 推柿子)
  19. 韩剧机器人题材的_穿越、超能力、监狱题材之后,2018年的韩剧盯上了机器人...
  20. jeesite4中图片上传功能

热门文章

  1. 染成茜色的坂道 圣诞汉化补丁翻译讨论(有点雷)
  2. SpringCloud-05 Hystrix学习笔记
  3. Linux 编译内核且增加一个系统调用
  4. U盘重装Win10方法以及常用必备软件安装
  5. tinder项目感言
  6. baum welch java_HMM的Baum-Welch算法和Viterbi算法公式推导细节(转载)
  7. 实时监听textField输入中文内容的时候拼音,拼音不跟着响应
  8. Xj123.biz 新疆维文网址导航站正式开通了!
  9. 硕士论文中期汇报ppt_研知|中期怎么办?不慌!
  10. hasOne和hasMany的区别