0

Hello I'm new here and also new to Java programming. Recently I'm trying to code a drawing function in JPanel. The problem is, when I add new drawRect (just select draw Rect in the JRadiobutton then drag on the white space) it works fine but when I press undo button there is a dot at the origin. Draw oval and draw polyline works fine. Can anyone help me out?

(Sorry for my poor english, if you don't get my question I'm sorry you can try running the code -> draw rectangles -> click undo -> at the origin got a dot (that's the problem I'm trying to explain))

package com.jetbrains;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.image.BufferedImage;

public class Main
{
private BufferedImage buffPNG = new BufferedImage(900,550,BufferedImage.TYPE_INT_ARGB);

private Main()
{
    draw_Image img = new draw_Image();

    JFrame frame = new JFrame("Ken's Paint");
    JButton undo_Button = new JButton("Undo");
    JRadioButton rb1 = new JRadioButton("Free Hand");
    JRadioButton rb2 = new JRadioButton("Draw Rect");
    JRadioButton rb3 = new JRadioButton("Draw Oval");
    JMenuBar menu_Bar = new JMenuBar();

    undo_Button.setContentAreaFilled(false);
    undo_Button.setFocusPainted(false);
    ButtonGroup mode_Group = new ButtonGroup();
    mode_Group.add(rb1);
    mode_Group.add(rb2);
    mode_Group.add(rb3);
    img.setDraw_Mode(1);
    rb1.setSelected(true);

    menu_Bar.add(rb1);
    menu_Bar.add(rb2);
    menu_Bar.add(rb3);
    menu_Bar.add(undo_Button);
    frameCreate(frame);
    frame.setJMenuBar(menu_Bar);
    frame.add(img);

    rb1.addActionListener(e -> img.setDraw_Mode(1));
    rb2.addActionListener(e -> img.setDraw_Mode(2));
    rb3.addActionListener(e -> img.setDraw_Mode(3));
    undo_Button.addActionListener(e -> img.undo_Pressed());
}

class draw_Image extends JPanel
{
    int layerX = 0;
    int layerY = 0;
    int[] polyX = new int[3000];
    int[] polyY = new int[3000];
    int[] thick = new int[10000];
    int[] nPoint = new int[10000];
    int[] draw_Mode = new int[10000];
    int[][] x = new int[10000][3000];
    int[][] y = new int[10000][3000];
    Color[] color = new Color[10000];
    boolean dragged = false;

    draw_Image() 
    {
        setLayout(null);
        setBounds(0,0,900,550);
        setBackground(Color.lightGray);
        for(int p = 0; p < 10000; p++)
        {
            draw_Mode[p] = 1;
            thick[p] = 3;
            color[p] = Color.black;
        }

        addMouseListener(new MouseAdapter()
        {
            @Override
            public void mouseClicked(MouseEvent e) {super.mouseReleased(e);}

            @Override
            public void mouseReleased(MouseEvent e)
            {
                super.mouseReleased(e);
                if(dragged)
                {
                    layerX++;
                    dragged = false;
                }
                layerY = 0;
            }
        });

        addMouseMotionListener(new MouseMotionListener()
        {
            @Override
            public void mouseDragged(MouseEvent e)
            {
                dragged = true;
                for(int k = layerY; k < 3000; k++)
                {
                    x[layerX][k] = e.getX();
                    y[layerX][k] = e.getY();
                }
                nPoint[layerX]++;
                layerY++;
                repaint();
            }

            @Override
            public void mouseMoved(MouseEvent e){}
        });
    }

    @Override
    public void paint(Graphics g)
    {
        super.paint(g);
        Graphics2D g2 = (Graphics2D)g;
        Graphics2D g3 = buffPNG.createGraphics();
        g2.setColor(Color.white);
        g2.fillRect(0,0,900,550);
        g3.setColor(Color.white);
        g3.fillRect(0,0,900,550);

        /* Draw the image in polyline form (implemented multidimensional array (2D is used)) */
        for(int i = 0; i <= layerX; i++)
        {
            for(int j = 0; j < 3000; j++)
            {
                polyX[j] = x[i][j];
                polyY[j] = y[i][j];
            }

            g2.setColor(color[i]);           /* Set the line color (g2 is for display) */
            g3.setColor(color[i]);           /* Set the line color (g3 is for buffered image) */
            g2.setStroke(new BasicStroke(thick[i])); /* Set line thickness (g2 is for display) */
            g3.setStroke(new BasicStroke(thick[i])); /* Set line thickness (g3 is for buffered image) */

            if(draw_Mode[i] == 1) /* free hand */
            {
                g2.drawPolyline(polyX,polyY,nPoint[i]);
                g3.drawPolyline(polyX,polyY,nPoint[i]);
            }

            else if(draw_Mode[i] == 2) /* draw rect */
            {
                g2.drawRect(polyX[0],polyY[0],(polyX[2999] - polyX[0]),(polyY[2999] - polyY[0]));
                g3.drawRect(polyX[0],polyY[0],(polyX[2999] - polyX[0]),(polyY[2999] - polyY[0]));
            }

            else if(draw_Mode[i] == 3) /* draw oval */
            {
                g2.drawOval(polyX[0],polyY[0],(polyX[2999] - polyX[0]),(polyY[2999] - polyY[0]));
                g3.drawOval(polyX[0],polyY[0],(polyX[2999] - polyX[0]),(polyY[2999] - polyY[0]));
            }
        }
    }

    void setDraw_Mode(int mode) /* Method to set draw mode */
    {
        for(int q = layerX; q < 10000; q++)
        {
            draw_Mode[q] = mode;
        }
    }


    void undo_Pressed() /* Undo an action / Return to previous line drawing */
    {
        if(layerX > 0)layerX--;
        for(int j = 0; j < 3000; j++)
        {
            x[layerX][j] = 0;
            y[layerX][j] = 0;
        }
        nPoint[layerX] = 0;
        setDraw_Mode(draw_Mode[layerX+1]);
        repaint();
    }
}

private void frameCreate(JFrame frame)
{
    frame.pack();
    Insets insetValue = frame.getInsets();
    int height = insetValue.top + insetValue.bottom + 600 - 10;
    int width = insetValue.left + insetValue.right + 900 - 10;
    frame.setSize(width,height);                                    /* Set the frame size */
    frame.setLocation(195,50);                                      /* Set the frame start up location */
    frame.setResizable(false);                                      /* Disable frame resize & full window option */
    frame.setLayout(null);                                          /* Set the layout to null */
    frame.setVisible(true);                                         /* Set the frame visible */
    frame.getContentPane().setBackground(Color.white);              /* Set the frame background color */
    frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);  /* Specify the default behavior upon closing */
}

public static void main(String[] args)
{
    new Main();
}
}
  • 1) For better help sooner, post a [MCVE] or [Short, Self Contained, Correct Example](http://www.sscce.org/). 2) See [Detection/fix for the hanging close bracket of a code block](http://meta.stackexchange.com/q/251795/155831) for a problem I could no longer be bothered fixing. 3) `frame.setLayout(null); ` Java GUIs have to work on different OS', screen size, screen resolution etc. using different PLAFs in different locales. As such, they are not conducive to pixel perfect layout. Instead use layout managers, or [combinations of them](http://stackoverflow.com/a/5630271/418556) .. – Andrew Thompson Jul 29 '17 at 18:10
  • .. along with layout padding and borders for [white space](http://stackoverflow.com/a/17874718/418556). – Andrew Thompson Jul 29 '17 at 18:11
  • Sorry for the inconvenience caused. I'll try to edit it and thank you for your advice. – Heng Yew Ken Jul 29 '17 at 18:13
  • I already tried to make it shorter and thanks for reminding for the hanging close bracket. – Heng Yew Ken Jul 29 '17 at 18:26

1 Answers1

1

Won't solve your problem, but some general tips:

class draw_Image extends JPanel
  1. Class names should start with an upper case character
  2. Don't use "_" in the class name.

Use the API as a guide for class naming conventions.

int[] polyX = new int[3000];
int[] polyY = new int[3000];
int[] thick = new int[10000];
int[] nPoint = new int[10000];

Don't use hardcoded numbers throughout the program. At the very least use a variable:

private static int SMALLER_SIZE = 3000;
private static int LARGER_SIZE = 10000;
...
int[] polyX = new int[SMALLER_SIZE];
int[] polyY = new int[SMALLER_SIZE];
int[] thick = new int[LARGER_SIZE];
int[] nPoint = new int[LARGER_SIZE];

Even better, don't use arrays. Instead use an ArrayList. Then you don't need to choose some randomly large number for the size of the array.

int[] polyX = new int[SMALLER_SIZE];
int[] polyY = new int[SMALLER_SIZE];

Don't keep two arrays. If the data is related then the data should be stored in an object. I the above case you can use the Point object that is part of the JDK. So the code for using the ArrayList (instead of arrays) would be something like:

private ArrayList<Point> points = new ArrayList<Point>();

Then you add Point object to the ArrayList using code like:

points.add( new Point(...) );

Now your looping code has no hard coded values:

for (int i = 0; i < points.getSize(); I++
{
    Point p = points.get(i);
    // do something with the Point
}

Some painting tips:

public void paint(Graphics g)

Don't override paint(...). Custom painting is done by overriding paintComponent(...)

    g2.setColor(Color.white);
    g2.fillRect(0,0,900,550);
    g3.setColor(Color.white);
    g3.fillRect(0,0,900,550);

Don't hardcode sizes. You have no idea what the screen size might be. Instead when you create the component you just do:

DrawImage panel= new DrawImage();
panel.setBackground(Color.WHITE);

Now when the super.paintComponent(...) is invoked the background of the panel will be painted white.

I also have no idea why you are using a transparent BufferedImage. Just paint directly to the panel.

If you really want to know how to paint Rectangles at random locations on the panel then you can check out Custom Painting Approaches. It demonstrates two common approaches. You would probably use the Draw On Component example since it would allow you to "undo" painting of the rectangles. Of course you need to implement this logic, but by keeping all the information if the ArrayList this would simple be a matter of removing the last item in the list.

camickr
  • 321,443
  • 19
  • 166
  • 288