做了一个基于工厂模式的画图程序,有一些bug,画图会出现一些乱七八糟的情况。。。百思不得其解,来求助各位。。。
父类Shape:
import java.awt.Graphics;
public abstract class Shape {
abstract void draw(Graphics g);
}
Line类:
import java.awt.Graphics;
import java.awt.Point;
public class Line extends Shape {
private Point start;
private Point end;
Line(Point start, Point end) {
this.start = start;
this.end = end;
}
@Override
void draw(Graphics g) {
g.drawLine(start.x, start.y, end.x, end.y);
}
}
Circle类:
import java.awt.Graphics;
import java.awt.Point;
public class Circle extends Shape {
private Point start;
private Point end;
public Circle(Point start, Point end) {
this.start = start;
this.end = end;
}
@Override
void draw(Graphics g) {
g.drawOval(Math.min(start.x, end.x), Math.min(start.y, end.y),
Math.max(Math.abs(start.x), Math.abs(start.y - end.y)),
Math.max(Math.abs(start.x - end.x), Math.abs(start.y - end.y)));
}
}
Rect类:
import java.awt.Graphics;
import java.awt.Point;
public class Rect extends Shape {
private Point start;
private Point end;
public Rect(Point start, Point end) {
this.start = start;
this.end = end;
}
@Override
void draw(Graphics g) {
g.drawRect(Math.min(start.x, end.x), Math.min(start.y, end.y),
Math.abs(start.x - end.x), Math.abs(start.y - end.y));
}
}
工厂类:
import java.awt.Point;
public class ShapeFactory {
public static Shape creator(int choices, Point start, Point end) {
if (choices == 1)
return new Line(start, end);
else if (choices == 2)
return new Circle(start, end);
else if (choices == 3)
return new Rect(start, end);
else return null;
}
}
主类,这边把代码全贴上来,想运行的朋友可以运行一下:
有些功能还没写完整,比如保存之类。
目前思路是这样:在菜单上选择要画的图形,这时会给choices赋一个值,代表要画的图形。
在鼠标点下的时候记录初始坐标。
鼠标抬起时记录终止坐标,并添加一个图形对象到保存的Vector中,再进行重绘。
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Vector;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JToolBar;
import javax.swing.UIManager;
/**
* @description 画图程序(以松耦合为目的,以工厂模式为实现方法)
* @date 2016-11-19
*/
/**
* @description 窗口类,定义大小以及窗口形态
*/
public class MyPaint extends JFrame {
private static final long serialVersionUID = 1L;
private DrawPanel drawingArea;
private int width = 800, height = 600;
public static int choices = 1;
// Constructor
public MyPaint() {
super("Drawing Program");
/**
* 定义菜单条的文件选项,设置四个选项分别为:
* 新建、打开、保存以及退出
*/
JToolBar buttonPanel; //按钮面板
JButton line, circle, rect;
JMenuBar bar = new JMenuBar(); //菜单条
JMenu fileMenu = new JMenu("File");
// 新建
JMenuItem newItem = new JMenuItem("New");
newItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//如果被触发,则调用新建文件函数段
}});
fileMenu.add(newItem);
// 保存
JMenuItem saveItem = new JMenuItem("Save");
saveItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//如果被触发,则调用保存文件函数段
}});
fileMenu.add(saveItem);
// 打开
JMenuItem loadItem = new JMenuItem("Load");
loadItem.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
//如果被触发,则调用打开文件函数段
}});
fileMenu.add(loadItem);
// 设置分割线 & 退出
fileMenu.addSeparator();
JMenuItem exitItem = new JMenuItem("Exit");
exitItem.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.exit(0); //如果被触发,则退出画图板程序
}});
fileMenu.add(exitItem);
bar.add(fileMenu);
/**
* 定义菜单栏的帮助选项,对软件进行解释
*/
JMenu helpMenu = new JMenu("Help");
JMenuItem aboutItem = new JMenuItem("About");
aboutItem.setMnemonic('A');
aboutItem.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(null,
"This is a mini drawing program",
" 画图板程序说明 ",
JOptionPane.INFORMATION_MESSAGE);
}});
helpMenu.add(aboutItem);
bar.add(helpMenu);
/**
* 按钮面板
*/
buttonPanel = new JToolBar(JToolBar.HORIZONTAL);
// 添加直线按钮以及点击事件
line = new JButton("Line");
line.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
repaint();
choices = 1;
}});
// 添加圆按钮以及点击事件
circle = new JButton("Circle");
circle.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
repaint();
choices = 2;
}});
// 添加矩形按钮以及点击事件
rect = new JButton("Rect");
rect.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
repaint();
choices = 3;
}});
buttonPanel.add(line);
buttonPanel.add(circle);
buttonPanel.add(rect);
setJMenuBar(bar);
// 定义画图区域
drawingArea = new DrawPanel();
Container c = getContentPane();
// 添加控件
c.add(drawingArea, BorderLayout.CENTER);
c.add(buttonPanel, BorderLayout.NORTH);
// 设置窗口
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(width, height);
setVisible(true);
}
/**
* Main
*/
public static void main(String[] args) {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
e.printStackTrace();
}
new MyPaint();
}
}
/**
* @description 画图面板类,提供鼠标监听器
*
*/
class DrawPanel extends JPanel implements MouseListener {
private static final long serialVersionUID = 1L;
// 用于保存图形
private Vector<Shape> shapes;
// 用于记录鼠标画图时留下的两个点的坐标
private Point start = new Point();
private Point end = new Point();
// Constructor
public DrawPanel() {
shapes = new Vector<>();
setBackground(Color.white);
this.addMouseListener(this);
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
for (int i = 0; i < shapes.size(); i++) {
draw(g, shapes.elementAt(i));
}
}
void draw(Graphics g, Shape shape) {
shape.draw(g);
}
@Override
public void mouseClicked(MouseEvent e) {
// do nothing here
}
@Override
public void mouseEntered(MouseEvent e) {
// do nothing here
}
@Override
public void mouseExited(MouseEvent e) {
// do nothing here
}
//按下鼠标时记录坐标点
@Override
public void mousePressed(MouseEvent e) {
start.x = e.getX();
start.y = e.getY();
}
// 松开鼠标时记录坐标点并将图形画出来
@Override
public void mouseReleased(MouseEvent e) {
end.x = e.getX();
end.y = e.getY();
shapes.add(ShapeFactory.creator(MyPaint.choices, start, end));
repaint();
}
}