0

I have a program that draws Vehicle Objects (e.g. Car Shapes) onto a JFrame using a paint method. However whenever I click on the screen to draw the vehicles I have to refresh the window for them to be shown even with the repaint() method added.


The first picture shows where I clicked. Nothing happened.

enter image description here

After minimizing and opening the window.

enter image description here

    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.event.MouseEvent;
    import java.awt.event.MouseListener;
    import java.util.Iterator;
    import java.util.LinkedList;
    import javax.swing.JFrame;


    /** Program specs: Draws shapes (Vehicles) that are contained within LinkedLists. 
     * When a shape is drawn over another shape it 'joins' its list. (not implemented yet, not my issue)

     */

    /**
      Creates JFrame
    */
    public class FramePanel extends JFrame implements MouseListener
    {
       private static final int FRAME_WIDTH = 600;
       private static final int FRAME_HEIGHT = 600;

       Car car; // Car is a subclass of Vehicle. It only contains a draw method.
       //Vehicle is an abstract class that only contains a draw method

       LinkedList<LinkedList<Vehicle>> list = new LinkedList<LinkedList<Vehicle>>();
       LinkedList<Vehicle> temp = new LinkedList <Vehicle>();

       /**
          Constructs the frame.
       */
       public FramePanel()
       {  
          addMouseListener(this);
          setSize(FRAME_WIDTH, FRAME_HEIGHT);

          repaint();
       }


    @Override
    public void mouseClicked(MouseEvent evt) {

    car = new Car (evt.getX(), evt.getY()); 
    temp.add(car); //Add Vehicle to LinkedList
    list.add(temp); //Add LinkedList to Collection of LinkedLists

    }

    public void mouseEntered(MouseEvent arg0) {}
    public void mouseExited(MouseEvent arg0) {}
    public void mousePressed(MouseEvent arg0) {}
    public void mouseReleased(MouseEvent arg0) {}


    public void paint(Graphics g) {
        super.paintComponents(g) ;
         Graphics2D g2 = (Graphics2D) g;

       for (LinkedList<Vehicle> veh : list){ // list is collection of Linked Lists

        Iterator<Vehicle> it = veh.iterator();
           while (it.hasNext()){
               it.next().draw(g2);
           }  
       }
    }

    public static void main(String[] args)
    {  
       JFrame frame = new FramePanel();
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
       frame.setTitle("Viewer");
       frame.setVisible(true);      
    }

    }

NOTE: If I add a repaint() statement onto my paint(Graphic g) method the car will be draw but will flicker undesirably with/without the repaint() in the constructor. I do not want this.

Jebathon
  • 4,310
  • 14
  • 57
  • 108
  • You aren't triggering repaint inside mouseClicked. Is this intentional? – Juan Lopes Mar 29 '14 at 19:53
  • You need to implement double buffering http://stackoverflow.com/questions/5924697/java-double-buffering. – BitNinja Mar 29 '14 at 19:57
  • 1
    @codeNinja This has **nothing** to do with double buffering .... – Marco13 Mar 29 '14 at 20:12
  • @Marco13 sure it does, the image flickers if he adds `repaint()`. – BitNinja Mar 29 '14 at 20:20
  • Overriding the `paint` method of `JFrame` is questionable anyhow (and for a beginner, one could say that it is plainly *wrong*), and calling `repaint()` in any `paint`-method will send the Event Dispatch Thread to an endless journey of painting operations, which also is not such a good idea. I added a few remarks in my answer, however. – Marco13 Mar 29 '14 at 20:26

1 Answers1

4

Adding a call to repaint() in the last line of your mouseClicked method will already resolve this issue.

However, there are a few other points:

  • Don't extend JFrame (especially, don't override the paint method of JFrame). Instead, use a JPanel for paining, and override its paintComponent method.
  • Don't let a top-level class implement the MouseListener interface
  • Don't declare your lists as LinkedList, but only as List ( What does it mean to "program to an interface"? )
  • The GUI should be created on the Event-Dispatch-Thread
  • Fields should be private (and final, if possible)

So some cleanups:

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.LinkedList;
import java.util.List;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class FramePanel extends JPanel
{
    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            @Override
            public void run()
            {
                createAndShowGUI();
            }
        });
    }

    private static void createAndShowGUI()
    {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        FramePanel framePanel = new FramePanel();
        f.getContentPane().add(framePanel);

        f.setSize(600,600);
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    private final List<List<Vehicle>> list = new LinkedList<List<Vehicle>>();

    /**
      Constructs the panel.
     */
    public FramePanel()
    {  
        addMouseListener(new MouseAdapter()
        {
            @Override
            public void mouseClicked(MouseEvent e)
            {
                addCarAt(e.getX(), e.getY());
            }
        });
    }

    private void addCarAt(int x, int y)
    {
        Car car = new Car(x, y); 
        List<Vehicle> temp = new LinkedList<Vehicle>();
        temp.add(car); //Add Vehicle to LinkedList
        list.add(temp); //Add LinkedList to Collection of LinkedLists
        repaint();
    }

    @Override
    protected void paintComponent(Graphics gr) 
    {
        super.paintComponent(gr) ;
        Graphics2D g = (Graphics2D)gr;

        for (List<Vehicle> veh : list) // list is collection of Linked Lists
        { 
            for (Vehicle v : veh)
            {
                v.draw(g);
            }  
        }
    }
}
Community
  • 1
  • 1
Marco13
  • 53,703
  • 9
  • 80
  • 159