Domanda

I was given the assignment to make a simple paint program in java that utilizes a GUI and has basic I/O capabilities. That was all I was told to do by my professor. However, I've only made one GUI program before, so jumping straight into this paint program has been a headache. Now I'm nearly done, but the program isn't really behaving as I expected. When new objects are drawn on the Panel, they draw invisible white rectangles on the objects underneath them that erases those objects. I think this is the result of the repaint(xMin, yMin, xMax - xMin + 1, yMax - yMin + 1); method in DrawShapes, but can't think of a way to fix it.

On the other hand, the objects are also not saving properly. I can get it to export a jpg as I intended, however, it will only export the last image drawn and not everything on the paintComponent canvas.

Lastly, the clear method in DrawShapes is working in a very similar way. When the clear method is activated, it will clear everything but the last image drawn.

Is there anyone more familiar than me with these tools that can see a way to fix these? This is only the first program I've utilized draw on, and I/O.

Here is the class for the panel that the shapes are supposed to drawn on:

/**
 * @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

And here is the code for the 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);
 }
}
È stato utile?

Soluzione

There are a few issues I can see, the main one is the fact that you "think" you've overridden a method in the MouseAdaptor class, but haven't

mouseRelease is not method that will cause any events to trigger it. The method you're after is mouseReleased.

When overriding methods, make use the @Override annotation, it will cause a compiler error if the method you "think" you're overriding doesn't exist in any of the parent classes.

@Override
public void mouseReleased(MouseEvent e) {

Several other things pop out.

  1. You're MyDrawUI classes extends from JFrame, but you create a instance of another JFrame called window, onto which you create your UI. In this case, drop the extends JFrame from the MyDrawUI class, as it just adds confusion...
  2. Maintaining a reference to a Graphics context, even one you created, is ill advised in this context. On some systems, until you call dispose it's possible that nothing will be committed to the underlying implementation. Instead, simply use image.getGraphics when you need it and call g2d.dispose when you're done with it.
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top