两中方法实现----在窗体内“单击鼠标左键”,在光标处绘制一个“绿圆”;窗体内“单击鼠标右键”,在光标处绘制一个“红色方框”;窗体内“双击鼠标左键”,清空所有已画“圆”和“方”。
方法一:
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.Iterator;
public class Three0307_1 {
//控制画出来的图像的大小的常量
static final int W = 20, H = 20;
public static void main(String[] args) {
new MyFrame();
}
static class MyFrame extends Frame {
ArrayList<MyPoint> myPoints;//创建用于存点,存的数组
int m_c = 0;//记录单击还是双击
MyFrame() {
myPoints = new ArrayList<>();
setBounds(400, 400, 600, 600);//设置窗口出现的位置以及大小
setVisible(true);//设置窗口可视化
addWindowListener(new WindowAdapter() {//监听窗口,实现窗口可关闭同时,程序停止
@Override
public void windowClosing(WindowEvent e) {
super.windowClosing(e);
System.exit(0);
}
});
addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
super.mouseClicked(e);
MyFrame myFrame = (MyFrame) e.getSource();//不用new,相当于接管地址
//用一个动态的数组不断的接收点击鼠标后的地址
//还需要判断鼠标的点击方式
m_c = e.getClickCount();
myPoints.add(new MyPoint(e.getX(),e.getY(),e.getButton()));
//用于刷新
myFrame.repaint();
}
});
}
@Override
public void paint(Graphics g) {
super.paint(g);
//判断是否为鼠标单击
if (m_c == 1){
for (int i = 0; i < myPoints.size(); i++){//因为数组会动态的更新,所以我们一直遍历它
if (myPoints.get(i).z == 1){
g.setColor(Color.green);
g.fillOval(myPoints.get(i).x,myPoints.get(i).y,W,H);
}
else if (myPoints.get(i).z == 3){
g.setColor(Color.red);
g.fillRect(myPoints.get(i).x,myPoints.get(i).y,W,H);
}
}
}
else if (m_c == 2){
myPoints.clear();
}
}
//写一个类,实现储存这些点的功能
static class MyPoint {
//新增变量c,记录鼠标的点击键位
public int x, y, z;
MyPoint(int a, int b, int c) {
x = a;
y = b;
z = c;
}
}
}
方法二
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class Three0307_2 {
//控制画出来的图像的大小的常量
static final int W = 20, H = 20;
public static void main(String[] args) {
new MyFrame();
}
//继承Frame
static class MyFrame extends Frame{
MyFrame(){
//设置窗口的大小,出现的位置,以及可见
setBounds(400,400,600,600);
setVisible(true);
//设置窗口可以关闭
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
super.windowClosing(e);
System.exit(0);
}
});
//创建监听系统,获得鼠标点击信息
addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
super.mouseClicked(e);
//关键:
//Graphics graphics1 =(Graphics)e.getSource();
//在内部获得画笔,我们需要的是这个类的方法,在内部我们可以轻松的获得坐标
Graphics graphics = getGraphics();
//鼠标单击后进行左右键位的判断
if (e.getClickCount() == 1){
if (e.getButton() == 1){
graphics.setColor(Color.green);
graphics.fillOval(e.getX(),e.getY(),W,H);
}
else if (e.getButton() == 3 ){
graphics.setColor(Color.red);
graphics.fillOval(e.getX(),e.getY(),W,H);
}
}
else if (e.getClickCount() == 2 ){
repaint();//鼠标双击后经行清屏操作
}
}
});
}
}
}
对比
-
两种方法在解决这个问题上明显第二种更简洁
-
在方法二中,用getGraphics()方法在监听器下面获得画笔,而在监听器下面获得坐标是很简单的,因此就能轻易作画了
-
但是第二种方法是无法记录鼠标在窗口上点击时的键位以及坐标的,而在有些时候我们是需要记录这些坐标另有他用的
-
第一中方法中,将各个分散的部分连接起来的方法也很有意思
-
两种方法中Frame中的repaint()方法使用的目的不一样,方法一中是不停的绘制,方法二中是为了清屏。
错误记录
//在第一次的发布中,方法二中画笔的创造方式我写为:
Graphics graphics = (Graphics) e.getSource();
//报错为
/*Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException: class Three0307_2$MyFrame cannot be cast to class java.awt.Graphics (Three0307_2$MyFrame is in unnamed module of loader 'app'; java.awt.Graphics is in module java.desktop of loader 'bootstrap')
at Three0307_2$MyFrame$2.mouseClicked(Three0307_2.java:45)*/
这个过程我用一个接口类去强转一个null类型或obj类,是肯定不可以的。但我也去了解了相关的类转换------兄弟之间不能转,父子关系才可以。而接口这种用于作为方便调用子类,是不能将其他毫不相关的类型强制转化过来的