Java 如何使该组件按预期的方式运行?

Java 如何使该组件按预期的方式运行?,java,swing,user-interface,paintcomponent,jcomponent,Java,Swing,User Interface,Paintcomponent,Jcomponent,我被指派用java编写一个简单的绘图程序,该程序利用GUI并具有基本的I/O功能。这就是我的教授告诉我要做的一切。然而,我以前只做过一个GUI程序,所以直接进入这个绘图程序一直是一件令人头痛的事情。现在我几乎完成了,但程序的运行并不像我预期的那样。在面板上绘制新对象时,它们会在其下方的对象上绘制不可见的白色矩形,从而擦除这些对象。我认为这是重新绘制的结果(xMin,yMin,xMax-xMin+1,yMax-yMin+1);方法,但想不出解决方法 另一方面,对象也没有正确保存。我可以让它按照我的

我被指派用java编写一个简单的绘图程序,该程序利用GUI并具有基本的I/O功能。这就是我的教授告诉我要做的一切。然而,我以前只做过一个GUI程序,所以直接进入这个绘图程序一直是一件令人头痛的事情。现在我几乎完成了,但程序的运行并不像我预期的那样。在面板上绘制新对象时,它们会在其下方的对象上绘制不可见的白色矩形,从而擦除这些对象。我认为这是重新绘制的结果(xMin,yMin,xMax-xMin+1,yMax-yMin+1);方法,但想不出解决方法

另一方面,对象也没有正确保存。我可以让它按照我的意图导出jpg,但是,它只导出最后绘制的图像,而不是paintComponent画布上的所有内容

最后,DrawShapes中的clear方法的工作方式非常相似。当“清除”方法被激活时,它将清除除最后绘制的图像以外的所有内容

有没有人比我更熟悉这些工具,可以找到解决这些问题的方法?这只是我第一次使用draw-on和I/O程序

下面是用于绘制形状的面板的类:

/**
 * @author me
 */
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.io.File;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.event.*;

public class DrawShapes extends JPanel{
    Point startPoint = null;
    Point endPoint = null;
    public int drawType = 1;
    BufferedImage image;
    Graphics2D g2d;

public DrawShapes(){
    setBackground(Color.WHITE);

    MyMouseListener m1 = new MyMouseListener();
    addMouseListener(m1);
    addMouseMotionListener(m1);
}//end constructor

//sets draw type, which is the decider of what is being drawn.
public void setType(int type){
    if(type == 1)
    {
        drawType = 1;
    }
    else if(type == 2)
    {
        drawType = 2;
    }
    else if(type == 3)
    {
        drawType = 3;
    }
}//end setType


    public void paintComponent(Graphics g)
{
    super.paintComponent(g);
    if (image == null)
    {
        createEmptyImage();
    }

    g.drawImage(image, 0, 0, null);

    if (startPoint != null && endPoint != null)
    {
            int x = Math.min(startPoint.x, endPoint.x);
            int y = Math.min(startPoint.y, endPoint.y);
            int width = Math.abs(startPoint.x - endPoint.x);
            int height = Math.abs(startPoint.y - endPoint.y);
            switch (drawType)
                {
                    case 1:
                        g.drawRect(x, y, width, height);
                        break;
                    case 2:
                        g.drawOval(x, y, width, height);
                        break;
                    case 3:
                        g.drawLine(startPoint.x, startPoint.y, endPoint.x, endPoint.y);
                        break;
                }
    }
}//end paintComponent

public void save()
{
    BufferedImage bi = new BufferedImage(this.getSize().width, this.getSize().height, BufferedImage.TYPE_INT_RGB);
    Graphics g = bi.createGraphics();
    this.paint(g);
    g.dispose();
    try{ImageIO.write(bi, "png",new File("test.png"));
    }catch (Exception e){}
    }

private void createEmptyImage()
{
    image = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB);
    g2d = (Graphics2D)image.getGraphics();
    g2d.setColor(Color.BLACK);
    g2d.drawString("Add a shape by clicking and dragging.", 40, 15);
}

public void addRect(int x, int y, int width, int height, Color color)
{
       g2d.setColor( color );
       g2d.drawRect(x, y, width, height);
       repaint();
}

public void addOval(int x, int y, int width, int height, Color color)
{
       g2d.setColor( color );
       g2d.drawOval(x, y, width, height);
       repaint();
}

public void addLine(int x1, int y1, int x2, int y2, Color color)
{
        g2d.setColor(color);
        g2d.drawLine(x1, y1, x2, y2);
        repaint();
}

public void clear()
{
       createEmptyImage();
       repaint();
}

class MyMouseListener extends MouseInputAdapter
{
    private int xMin;
    private int xMax;
    private int yMin;
    private int yMax;

    public void mousePressed(MouseEvent e)
    {
           startPoint = e.getPoint();
           endPoint = startPoint;
           xMin = startPoint.x;
           xMax = startPoint.x;
           yMin = startPoint.y;
           yMax = startPoint.y;
    }

    public void mouseDragged(MouseEvent e)
    {
        //This is code I found that should make it so the only area affected by the dragging is repainted.
        endPoint = e.getPoint();
        xMin = Math.min(xMin, endPoint.x);
        xMax = Math.max(xMax, endPoint.x);
        yMin = Math.min(yMin, endPoint.y);
        yMax = Math.max(yMax, endPoint.y);
        repaint(xMin, yMin, xMax - xMin + 1, yMax - yMin + 1);

    }

    public void mouseRelease(MouseEvent e)
    {
        //This code paints the shapes on the Buffered Image created as a canvas
        int x = Math.min(startPoint.x, endPoint.x);
        int y = Math.min(startPoint.y, endPoint.y);
        int width = Math.abs(startPoint.x - endPoint.x);
        int height = Math.abs(startPoint.y - endPoint.y);

        if (width != 0 || height != 0)
    {
        g2d.setColor( e.getComponent().getForeground() );
//      g2d.drawRect(x, y, width, height);
                switch (drawType)
                {
                    case 1:
                        addRect(x, y, width, height, e.getComponent().getForeground());
                        break;
                    case 2:
                        addOval(x, y, width, height, e.getComponent().getForeground());
                        break;
                    case 3:
                        addLine(startPoint.x, startPoint.y, endPoint.x, endPoint.y, e.getComponent().getForeground());
                        break;
                }//end switch statement.
    }

    startPoint = null;
//  repaint();
    }
}

}//end class
下面是UI的代码:

/*@author Me*/
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class MyDrawUI extends JFrame
{
    private DrawShapes draw = new DrawShapes();
    private JPanel ButtonPanel = new JPanel();
    private JFrame window = new JFrame("Draw!");
    //constructor
    MyDrawUI(){
        buildUI();
    }

 void buildUI()
 {
     window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     window.setLayout(new GridLayout(2,2));
     window.add(draw);
     window.add(ButtonPanel, BorderLayout.SOUTH);
     ButtonPanel.setBackground(Color.LIGHT_GRAY);
     draw.setBackground(Color.WHITE);

     //define buttons
     JButton rectangle = new JButton("Rectangle");
     JButton oval = new JButton("Oval");
     JButton line = new JButton("Line");
     JButton exit = new JButton("Exit");
     JButton save = new JButton("Save");
     JButton clear = new JButton("Clear");

     //add buttons
     ButtonPanel.add(rectangle, BorderLayout.SOUTH);
     ButtonPanel.add(oval, BorderLayout.SOUTH);
     ButtonPanel.add(line, BorderLayout.SOUTH);
     ButtonPanel.add(clear, BorderLayout.SOUTH);
     ButtonPanel.add(save, BorderLayout.SOUTH);
     ButtonPanel.add(exit, BorderLayout.SOUTH);
     ButtonPanel.setSize(100, 100);

     save.addActionListener(new ActionListener(){
         public void actionPerformed(ActionEvent e)
         {
         draw.save();
         }
     });

     clear.addActionListener(new ActionListener(){
         public void actionPerformed(ActionEvent e)
         {
         draw.clear();
         }
     });

     rectangle.addActionListener(new ActionListener(){
         public void actionPerformed(ActionEvent e)
         {
             draw.setType(1);
         }
     });

     oval.addActionListener(new ActionListener(){
         public void actionPerformed(ActionEvent e)
         {
             draw.setType(2);
         }
     });

     line.addActionListener(new ActionListener(){
         public void actionPerformed(ActionEvent e)
         {
             draw.setType(3);
         }
     });

     exit.addActionListener(new ActionListener(){
         public void actionPerformed(ActionEvent e)
         {
             System.exit(0);
         }
     });

     window.setVisible(true);
     window.setSize(1024, 800);
 }
}

我可以看到一些问题,主要的问题是您“认为”您已经覆盖了
MouseAdaptor
类中的一个方法,但还没有

mousererelease
不是会导致任何事件触发它的方法。您要使用的方法是
mousererelease

重写方法时,请使用
@Override
注释,如果您“认为”要重写的方法在任何父类中都不存在,则会导致编译器错误

@Override
public void mouseReleased(MouseEvent e) {
其他一些东西突然出现

  • 您是从
    JFrame
    扩展而来的
    MyDrawUI
    类,但是您创建了另一个名为
    window
    JFrame
    实例,您可以在该实例上创建UI。在这种情况下,从
    MyDrawUI
    类中删除
    extensedjframe
    ,因为它只会增加混淆
  • 在这种情况下,维护对
    图形
    上下文(即使是您创建的上下文)的引用是不明智的。在某些系统上,在调用
    dispose
    之前,可能不会向底层实现提交任何内容。相反,只需在需要时使用
    image.getGraphics
    ,完成后调用
    g2d.dispose

  • 我可以看到一些问题,主要的问题是您“认为”您已经覆盖了
    MouseAdaptor
    类中的一个方法,但还没有

    mousererelease
    不是会导致任何事件触发它的方法。您要使用的方法是
    mousererelease

    重写方法时,请使用
    @Override
    注释,如果您“认为”要重写的方法在任何父类中都不存在,则会导致编译器错误

    @Override
    public void mouseReleased(MouseEvent e) {
    
    其他一些东西突然出现

  • 您是从
    JFrame
    扩展而来的
    MyDrawUI
    类,但是您创建了另一个名为
    window
    JFrame
    实例,您可以在该实例上创建UI。在这种情况下,从
    MyDrawUI
    类中删除
    extensedjframe
    ,因为它只会增加混淆
  • 在这种情况下,维护对
    图形
    上下文(即使是您创建的上下文)的引用是不明智的。在某些系统上,在调用
    dispose
    之前,可能不会向底层实现提交任何内容。相反,只需在需要时使用
    image.getGraphics
    ,完成后调用
    g2d.dispose

  • 我可以看到一些问题,主要的问题是您“认为”您已经覆盖了
    MouseAdaptor
    类中的一个方法,但还没有

    mousererelease
    不是会导致任何事件触发它的方法。您要使用的方法是
    mousererelease

    重写方法时,请使用
    @Override
    注释,如果您“认为”要重写的方法在任何父类中都不存在,则会导致编译器错误

    @Override
    public void mouseReleased(MouseEvent e) {
    
    其他一些东西突然出现

  • 您是从
    JFrame
    扩展而来的
    MyDrawUI
    类,但是您创建了另一个名为
    window
    JFrame
    实例,您可以在该实例上创建UI。在这种情况下,从
    MyDrawUI
    类中删除
    extensedjframe
    ,因为它只会增加混淆
  • 在这种情况下,维护对
    图形
    上下文(即使是您创建的上下文)的引用是不明智的。在某些系统上,在调用
    dispose
    之前,可能不会向底层实现提交任何内容。相反,只需在需要时使用
    image.getGraphics
    ,完成后调用
    g2d.dispose

  • 我可以看到一些问题,主要的问题是您“认为”您已经覆盖了
    MouseAdaptor
    类中的一个方法,但还没有

    mousererelease
    不是会导致任何事件触发它的方法。您要使用的方法是
    mousererelease

    重写方法时,请使用
    @Override
    注释,如果您“认为”要重写的方法在任何父类中都不存在,则会导致编译器错误

    @Override
    public void mouseReleased(MouseEvent e) {
    
    其他一些东西突然出现

  • 您是从
    JFrame
    扩展而来的
    MyDrawUI
    类,但是您创建了另一个名为
    window
    JFrame
    实例,您可以在该实例上创建UI。在这种情况下,从
    MyDrawUI
    类中删除
    extensedjframe
    ,因为它只会增加混淆
  • 维护对
    图形的引用