ListerCi 2016-11-21 13:16 采纳率: 60%
浏览 1532
已采纳

Java制作画图程序的GUI问题

做了一个基于工厂模式的画图程序,有一些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();
    }

}
  • 写回答

1条回答 默认 最新

  • _1_1_7_ 2016-11-21 14:11
    关注

    问题出在:

         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();
        }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 关于#vscode#的问题:ESP32开发板对接MQTT实现小灯泡的开关
  • ¥15 TMC2209串口模式下读取不到寄存器的值串口助手蓝色字体是发过去的消息,绿色字体是收到的消息,第二行发送读取寄存器的指令但是没有读取到寄存器的值串口助手如下图:接线如下图,如何解决?
  • ¥15 高通安卓11提取完整线刷包软件,或者优博讯dt50顺丰刷机包
  • ¥20 C,有个译码器,换了信道就跑不出原来数据
  • ¥15 MIMIC数据库安装问题
  • ¥60 基于JTag协议开发Fpga下载器上位机,哪位大🐂有偿指导?
  • ¥20 全书网Java爬取数据
  • ¥15 怎么获取红包封面的原始链接,并且获取红包封面序列号
  • ¥100 微信小程序跑脚本授权的问题
  • ¥100 房产抖音小程序苹果搜不到安卓可以付费悬赏