1

I am a beginner to JAVA and I'm breaking my head on the following problem:

Why does this code not draw

import ...

public class tekening extends JFrame{

    private JPanel p;
    private Graphics g;

    tekening(){

        setLayout(new FlowLayout());

        p = new JPanel();
        p.setPreferredSize(new Dimension(350, 350));
        p.setBackground(Color.WHITE);
        add(p);

        setLocationByPlatform(true);
        setSize(400, 400); 
        setVisible(true);
        setDefaultCloseOperation(EXIT_ON_CLOSE); 

        g = p.getGraphics();
        g.setColor(Color.BLACK);
        g.drawRect(30, 30, 80, 40);
        g.drawLine(10, 10, 40, 50);
    }

}

And why does this code draw

import ...

public class tekenclasse extends JFrame implements ActionListener{

    private JPanel p;
    private Graphics g;
    private JButton button1;

    tekenclasse(){

        setLayout(new FlowLayout());

        button1 = new JButton("Knop 1");
        button1.addActionListener(this);
        add(button1);

        p = new JPanel();
        p.setPreferredSize(new Dimension(350, 350));
        p.setBackground(Color.WHITE);
        add(p);

        setLocationByPlatform(true);
        setSize(400, 400); 
        setVisible(true);
        setDefaultCloseOperation(EXIT_ON_CLOSE); 
    }

    public void actionPerformed(ActionEvent e){
        g = p.getGraphics();
        g.setColor(Color.BLACK);
        g.drawRect(30, 30, 80, 40);
        g.drawLine(10, 10, 40, 50);
    }

}

For me this is completely strange. Why can't I use the Graphics inside the constructor. And why can I use it after an event. This is stupid I want to draw on immediately and I don't want to press a button.

Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720
botenvouwer
  • 4,334
  • 9
  • 46
  • 75
  • 5
    Don't draw on `JFrame` this way. Override the `paint` method instead. [Oracle Tutorials: custom painting](http://docs.oracle.com/javase/tutorial/uiswing/painting/index.html) – BackSlash Sep 19 '14 at 09:34
  • Whats wrong, i have tested your code,i got a frame with white colour panel in output. Is that your output? – Anptk Sep 19 '14 at 09:40
  • 1
    You could use the debug first and see that the figures are really drawing. I'm not sure why that happen but I think the image is being re-drawn after that and that's why you get blank frame. Correct me please =) – Donvino Sep 19 '14 at 09:46
  • I think @Donvino is correct. Since you only have drawing inside constructor it will get redrawn – Thusitha Thilina Dayaratne Sep 19 '14 at 10:00
  • @Donvino I think you are right but how can I fix that? – botenvouwer Sep 19 '14 at 10:01
  • @sirwilliam You can find some explanation here: http://stackoverflow.com/a/15991175/2902209 – Donvino Sep 19 '14 at 10:17

1 Answers1

3
  1. Never use getGraphics() to paint.

  2. Don't try and paint on top level containers like JFrame

  3. Instead (as shown in Performing Custom Painting - MUST READ), use a JPanel (or JComponent) and override its protected void paintComponent(Graphics g) method. Use that graphics context to do your painting. All your painting should be done within that graphics context provides, whether directly writing code in the paintComponent method, or calling a method in which you pass the Graphics object to as an argument.

  4. Override public Dimension getPreferredSize() in the JPanel/JComponent to give you painting surface a preferred size. Ad the pabel to the frame, then pack() your frame.

    public class DrawPanel extends JPanel {
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.draw...  // do all your drawing here
        }
        @Override
        public Dimension getPreferredSize() {
            return new Dimension(400, 400);
        }
    }
    

Important: You MUST read the link about custom painting before posting another question about painting, or you will get a spanking :-)

Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720
  • Can you explain why I can't use `getGraphics()` and why I have to override `paintComponent()`. – botenvouwer Sep 19 '14 at 10:09
  • 2
    1. getGraphics() exists for one call as doesn't persist anything. 2. It's part of the paint chain for how components are painted. These methods get called, so you don't have to call them yourself. Read the link, they give good explanations – Paul Samsotha Sep 19 '14 at 10:12