2

I have the following simple code in a JFrame constructor

    super(name);
    setBounds(0,0,1100,750);
    setLayout(null);


    setVisible(true);

    g = this.getGraphics();
    int[] x =new int[]{65,  122,  77,  20, };
    int[] y =new int[]{226,  258, 341,  310};
    g.setColor(Color.RED);  
    g.drawPolygon (x, y, x.length);
    System.out.println(g);

I get the output on console as:

sun.java2d.SunGraphics2D[font=java.awt.Font[family=Dialog,name=Dialog,style=plain,size=12],color=java.awt.Color[r=255,g=0,b=0]]

But no red polygon drawn on JFrame but just the blank JFrame.

Why ??

mKorbel
  • 109,525
  • 20
  • 134
  • 319
aditya parikh
  • 595
  • 4
  • 11
  • 30
  • This is not the correct way to draw on a JFrame. You should subclass JPanel and override `paintComponent(Graphics)`, and do the painting on the graphics object passed there. – FThompson Oct 25 '12 at 19:04

2 Answers2

7
  • Dont overridepaint(..) in JFrame

  • Rather add custom JPanel with overridden paintComponent(Graphics g) to JFrame

  • Dont use Null/AbsoluteLayout use an appropriate LayoutManager

  • Dont call setBounds(..) on JFrame instance (not that its not allowed but cant see it being relevant in this application)

  • Dont forget to use EDT for creating and changing GUI components:

    javax.swing.SwingUtilities.invokeLater(new Runnable() {
                @Override
               public void run() {
                    Test test = new Test();
               }
    });
    

you would then do something like this:

public class Test {

    /**
     * Default constructor for Test.class
     */
    public Test() {
        initComponents();
    }

    public static void main(String[] args) {

        /**
         * Create GUI and components on Event-Dispatch-Thread
         */
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                Test test = new Test();
            }
        });
    }

    /**
     * Initialize GUI and components (including ActionListeners etc)
     */
    private void initComponents() {
        JFrame jFrame = new JFrame();
        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        jFrame.add(new MyPanel());

        //pack frame (size JFrame to match preferred sizes of added components and set visible
        jFrame.pack();
        jFrame.setVisible(true);
    }
}

class MyPanel extends JPanel {

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        int[] x = new int[]{65, 122, 77, 20};
        int[] y = new int[]{226, 258, 341, 310};
        g.setColor(Color.RED);
        g.drawPolygon(x, y, x.length);
    }

    //so our panel is the corerct size when pack() is called on Jframe
    @Override
    public Dimension getPreferredSize() {
        return new Dimension(400, 400);
    }
}

which produces:

enter image description here

David Kroukamp
  • 36,155
  • 13
  • 81
  • 138
  • 1
    +1, nice example. Only point of curiosity is the comment about setBounds? What's the difference between that at using setLocation & setSize? – MadProgrammer Oct 25 '12 at 19:42
  • @MadProgrammer +1 thank you... As for `setBounds(..)` I have no concrete evidence, but I see it as an amalgamation of `setSize()` and `setLocation()`. I dont have a problem with `setLocation()` (besides the fact that the position could be off screen), but `setSize()` has known issues such as components being hidden due to incorrect size given etc and the same can happen when setting the height and width using `setBounds(x,y,width,height)`. Though I am open for criticism :) – David Kroukamp Oct 25 '12 at 19:53
  • 1
    Personally I have no particular issue, pack and setLocationRelativeXxx are generally more useful day to day, IMHO, although its sometimes necessary/desirable to specify the location size directly. It would "discourage" the use of absolute positioning in this manner without good reason, but that's just me. Just wanted to get your perspective ;) – MadProgrammer Oct 25 '12 at 20:35
  • @MadProgrammer, +1 very true, and not a problem, I edited the post to show the change and OP and others can see the comments – David Kroukamp Oct 25 '12 at 20:46
  • Hey I am adding the following image in the Jpanel http://msu-footprints.org/2011/Aditya/map.jpg and then adding polygon `int[] x = new int[]{65, 122, 77, 20}; int[] y = new int[]{226, 258, 341, 310}; g.setColor(Color.RED); g.drawPolygon(x, y, x.length);` The polygon should coincide with building GER but is a little bit offset. My proff says the co-ordinates are okay. Is there anything wrong with how i put the image position. – aditya parikh Oct 25 '12 at 20:49
  • @adityaparikh If you're still painting directly onto the frame, then you're corrdinate space will be wrong, as it will be taken from the top left of the frame (outside border) not that of the content pane, take a look at [How to Use Root Panes](http://docs.oracle.com/javase/tutorial/uiswing/components/rootpane.html) for an over view ... of why it's a bad idea to override the `paint` method of top level containers like `JFrame`s – MadProgrammer Oct 25 '12 at 21:58
2

You should better override paint(Graphics g) or paintComponent(Graphics g) than the approach you are trying. Add the lines below and remove the lines after setVisible in your code.

public void paint(Graphics g) {
  int[] x =new int[]{65,  122,  77,  20};
  int[] y =new int[]{226,  258, 341,  310};
  g.setColor(Color.RED);  
  g.drawPolygon (x, y, x.length);
}
Dan D.
  • 32,246
  • 5
  • 63
  • 79
  • 1
    and not to use getGraphics(), this method is for Printing or save Graphics to the File – mKorbel Oct 25 '12 at 19:06
  • But paint method runs at start automatically. I want to programatically decide when to draw. – aditya parikh Oct 25 '12 at 19:11
  • 1
    Then put a flag and draw the stuff under paint only when the flag decides that. – Dan D. Oct 25 '12 at 19:15
  • 1
    You really shouldn't override a top level containers paint method. Apart from anything else, it's not double buffered, better to override something that extends from JComponent – MadProgrammer Oct 25 '12 at 19:38
  • That's true. However, I showed where the wrong part is. Things can definitely be improved from this point. – Dan D. Oct 25 '12 at 19:55