4

Why JFrame is empty after my graphics

package javaGame;

import java.awt.Graphics;

import javax.swing.JFrame;


public class javaGame extends JFrame {

   public javaGame (){
       setVisible(true);
       setSize(250,250);
       setResizable(false);
       setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
       setTitle("Java Game");
   }

   public void paint (Graphics g){
      g.drawString("Hello world!", 75, 75);
   }

   public static void main (String[] args){
       new javaGame ();
   }
}
Roman C
  • 49,761
  • 33
  • 66
  • 176
alibabaei12
  • 161
  • 1
  • 2
  • 9

3 Answers3

3

You are used to applets, where overriding paint will actually work. In a JFrame, the recommended technique is a little more complicated. Add this code to your constructor:

getContentPane().add(new JPanel() {
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawString("Hello world!", 75, 75);
    }
});

This creates an anonymous subclass of JPanel which overrides paintComponent to do some painting, then adds the JPanel to the frame. The call to super.paintComponent is important.

There are several other things that you should know are different from applets:

  • You need to call setVisible(true) to make the frame appear. This is mandatory for your program to work.
  • You should add setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE) if you want the program to be closed if the window is closed. Highly recommended.
tbodt
  • 16,609
  • 6
  • 58
  • 83
1

When you opening a new frame you should make it visible after validate or pack is applied to it, also call setVisible(true) at the end of the frame creation. The code for modification:

public void paint (Graphics g){
   super.paint(g);
   g.drawString("Hello world!", 75, 75);
}
Roman C
  • 49,761
  • 33
  • 66
  • 176
  • While technically created, it is not recommended to override `paint`, especially of top level containers. Instead, it is recommended to override the `paintComponent` of components extending from `JComponent` instead – MadProgrammer Aug 04 '13 at 08:15
  • Oh, but it works either, for this example is applicable. I don't think OP is trying to draw components. – Roman C Aug 04 '13 at 08:18
  • Doesn't matter, it is recommended to perform all custom painting from within the `paintComponent` method of classes extending from `JComponent` (like `JPanel`). To start with, you can easily screw the paint chain and top level containers aren't double buffered ;) – MadProgrammer Aug 04 '13 at 08:46
  • JFrame is a heavyweight object and should be painting via it's own paint method, you can't use `paintComponent` on heavyweight object. Creating a lightweight object and draw there is another approach, who is recommended it doesn't matter but it has nothing with the question above, which is even doesn't have a question. Don't no why I did answer it. But OP is used JFrame and not used JPanel or JComponent, that's why I think my approach is better. – Roman C Aug 04 '13 at 09:12
  • Generally speaking, for a number of reasons, it is not recommended to extend from top level containers (Applets are an excetion, as you have no choice), but rendering directly to them is not recommended. The general recommendation is to start with a base container, like `JComponent` or `JPanel`. This not only brings you within the double buffered support of Swing, but also means that you application is more re-usable (can be moved to an applet or frame as required). Just because the OP started on an approach doesn't mean it's the right one. – MadProgrammer Aug 04 '13 at 09:58
  • We should be capable of suggesting to developers better ways of solving there problems. [Painting in AWT and Swing](http://www.oracle.com/technetwork/java/painting-140037.html) recommends overriding `paintComponent` instead of `paint` – MadProgrammer Aug 04 '13 at 10:00
  • *"Swing programs should override paintComponent() instead of overriding paint(). Although the API allows it, there is generally no reason to override paintBorder() or paintComponents() (and if you do, make sure you know what you're doing!). This factoring makes it easier for programs to override only the portion of the painting which they need to extend. For example, this solves the AWT problem mentioned previously where a failure to invoke super.paint() prevented any lightweight children from appearing."* - You of course have the choice to make any suggestion you like – MadProgrammer Aug 04 '13 at 10:00
  • Oh, you do suggest, I know the user is not asked for. – Roman C Aug 04 '13 at 10:02
  • Ok, I wish I understood that – MadProgrammer Aug 04 '13 at 10:05
  • I wish you understood me correctly, I have nothing against lightweight component framework and it's painting mechanism, but can't drop down a heavyweight one, and user *must* differentiate this things until he/she get know what is doing instead of blindly taking one's approach because someone recommended it without proper description. – Roman C Aug 04 '13 at 10:12
  • Ah, I think I know what you're getting at, but the choice of using `JFrame` has placed them inside the Swing framework, if they choose `Frame`, I'd have no argument and would agree. (I'd still recommend using a `Panel` instead though ;)) – MadProgrammer Aug 04 '13 at 10:14
  • I think you don't understand what are you posted yourself: "**the API allows it**, there is generally no reason to override paintBorder() or paintComponents()"(and if you do, **make sure you know what you're doing**!)". I know what I am doing, answering this silly question! – Roman C Aug 04 '13 at 10:19
  • I do appropriate your point of view, but, it is still not recommended to override `paint` of a top level container. Sure, if you want to override `paint` of container, knock yourself it. – MadProgrammer Aug 04 '13 at 10:24
  • Also I don't know where you get that description JFrame has no `paintComponent`, so nothing to override. – Roman C Aug 04 '13 at 10:27
  • I know, hence one of the reasons we don't recommended painting directly to a top level container. – MadProgrammer Aug 04 '13 at 10:28
  • yes, there are reasons to not recommend it, but also there's not reason to recommend it. Choose what ever better suits your needs. – Roman C Aug 04 '13 at 10:36
  • *"I know what I am doing"* - I'm glad you do, because it's obvious that the OP doesn't. You're also throwing out the double buffering support provided by Swing by overriding `paint` of a top level container, which will probably be the next question the OP raises - my is my painting flickering :P – MadProgrammer Aug 04 '13 at 10:39
  • Then it would be another question, and you teach them how to write double-buffering, or switch to lightweight framework and use double-buffering implemented by someone else, anyway it would be another question. Programming is a way of thinking not blindly codding. – Roman C Aug 04 '13 at 10:46
1

1) Follow java code conventions javaGame should be JavaGame

2) Swing programs should override paintComponent() instead of overriding paint().

3) You should make custom painting in a JComponent like JPanel.

Change your code to for example something like this.

public class JavaGame {

    private JFrame frame; //use composition instead of concrete inheritance

    public JavaGame () {
        jframe.setSize(250,250);
        jframe.setResizable(false);
        jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jframe.setTitle("Java Game");
        jframe.add(new JPanel() {
            @Override
            public void paintComponent (Graphics g) {
                super.paintComponent(g);
                g.drawString("Hello world!", 75, 75);
            }
        });
        jframe.pack(); //sizes the frame
        jframe.setVisible(true);
    }

    public static void main (String[] args) {
        SwingUTilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new javaGame();
            }
        });
    }
}
nIcE cOw
  • 24,468
  • 7
  • 50
  • 143
nachokk
  • 14,363
  • 4
  • 24
  • 53
  • 1
    Pardon me for the edit, though it was necessary I guess, you forgot to add the `run()` method for the `Runnable` interface :-) – nIcE cOw Aug 04 '13 at 15:26