6
\$\begingroup\$

I have written a very basic paint program in java using AWT and Swing. I have separated the program into two different class files; one of them holds the JFrame and adds a custom panel (this custom panel being the second class file, extending JPanel).

In my first try, I tried using Timer and an ActionListener with repaint() but that seemed very very laggy (I could not draw straight lines/curves, they would always be laggy when I dragged my mouse fast.)

Then I switched to using a different approach (stored previous x and y locations and drew a line between the current position and the previous location). Here are the two class files:

The custom JPanel class:

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

public class Panel extends JPanel
{
  // PROPERTIES
  private final int DEFAULT_WIDTH  = 800;
  private final int DEFAULT_HEIGHT = 800;
  private final Color BACK_COLOR   = Color.WHITE;

  private int x1, y1, x2, y2;

  private MyMouseHandler handler;
  private Graphics g;

  // CONSTRUCTOR
  public Panel()
  {
    setBackground( BACK_COLOR );
    setPreferredSize( new Dimension( DEFAULT_WIDTH, DEFAULT_HEIGHT ) );

    handler  = new MyMouseHandler();

    this.addMouseListener( handler );
    this.addMouseMotionListener( handler );
  }

  // METHOD
  public void paintComponent(Graphics g)
  {
    super.paintComponent(g);
  }

  private void setUpDrawingGraphics()
  {
    g = getGraphics();
  }

  // INNER CLASS
  private class MyMouseHandler extends MouseAdapter
  {
    public void mousePressed( MouseEvent e )
    {
      x1 = e.getX();
      y1 = e.getY();

      System.out.println("Mouse is being pressed at X: " + x1 + " Y: " + y1);

      setUpDrawingGraphics();

      x2=x1;
      y2=y1;
    }

    public void mouseDragged( MouseEvent e )
    {
      x1 = e.getX();
      y1 = e.getY();

      System.out.println("Mouse is being dragged at X: " + x1 + " Y: " + y1);  

      g.drawLine(x1,y1,x2,y2);

      x2=x1;
      y2=y1;
    }
  }
}

and the JFrame class with the main method:

import java.awt.*;
import javax.swing.*;

public class RunPanel
{
  public static void main(String[] args)
  {
    JFrame frame = new JFrame( "Run Panel" );
    frame.setDefaultCloseOperation(3);

    Panel  panel = new Panel();
    frame.add( panel );

    frame.pack();
    frame.setVisible( true );
  }
}

The program works fine, I can draw normal curves at low mouse speed. But again, as I increase the mouse speed the lines/curves start the get jaggy and ugly.

enter image description here

Maybe this is because I am drawing lines in between the positions, but drawing individual pixels look MUCH worse.

NOTE: I have gathered the two classes into one class file and the program stopped the lag. What is causing this? You can see the code here.

\$\endgroup\$
4
\$\begingroup\$

Your code formatting deviates from the default Java code formatting, just saying.


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

Wildcard imports are kinda bad. If you can avoid them, please do so.


public class Panel extends JPanel

I'm sure you can find a more descriptive name for this class, like PaintablePanel or MousePaintablePanel.


// PROPERTIES

Personally, I don't like such "structuring" comments, they do nothing and only clutter up the code and need to be manually moved when refactoring automatically.


private final int DEFAULT_WIDTH  = 800;
private final int DEFAULT_HEIGHT = 800;
private final Color BACK_COLOR   = Color.WHITE;

Personally I also don't like this column based alignment, it puts my brain into some sort of "column reading mode" which makes it hard for me to associate the value with the variable.


private int x1, y1, x2, y2;

You should not declare multiple variables on the same line, it makes it easy to miss the declaration of variables.


private MyMouseHandler handler;

MyMouseHandler is not a very good name.


public void paintComponent(Graphics g)
{
  super.paintComponent(g);
}

This method seems to override a super method, yet misses the @Override annotation. Also, if it does not do anything, why override it?


public void mousePressed( MouseEvent e )
{
...
     SetUpDrawingGraphics();

Why are you doing this on every mouse press?


public class RunPanel

This is another bad name. What does it run? And it is not a panel.


frame.setDefaultCloseOperation(3);

Any reason why you're not using the constants defined in JFrame?


The program works fine, I can draw normal curves at low mouse speed. But again, as I increase the mouse speed the lines/curves start the get jaggy and ugly.

That is how it is.

I have gathered the two classes into one class file and the program stoped the lag. What is causing this?

I see this behavior in both programs. Combining them in the same file has for sure nothing to do with it.

\$\endgroup\$
  • \$\begingroup\$ The formatting choices are solely based on my instructor's demands. He wants us to write in this style (comments, variable declaration, imports etc) But thank you for all the feedback! I will try to rework it to a better state. Also, strangely, the one-class-file code works great for me without lag :/ very weird stuff \$\endgroup\$ – hope4tg Mar 27 '16 at 5:44
3
\$\begingroup\$

The call to System.out.println, which is an expensive operation, is performed every time the mouse is dragged. Every position change will print a line. The faster a position changes the faster it will print.

Deleting this print call should fix the problem and make the console info more useful.

A minimum difference condition to allow the call to print could also solve the problem.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.