做了一個基於工廠模式的畫圖程序,有一些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();
}
}
問題出在:
private Point start = new Point();
private Point end = new Point();
不能用,應該:
int x;
int y;
public void mousePressed(MouseEvent e) {
x = e.getX();
y = e.getY();
}
public void mouseReleased(MouseEvent e) {
int x1 = e.getX();
int y1 = e.getY();
shapes.add(ShapeFactory.creator(MyPaint.choices, new Point(x,y), new Point(x1,y1)));
repaint();
}