Nirav Kamani
Nirav Kamani

Reputation: 3272

Unable to display string

I am having following code.

package lab1;

import java.awt.Color;
import java.awt.Graphics;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.plaf.metal.DefaultMetalTheme;
import javax.swing.plaf.metal.MetalLookAndFeel;

public class Snake extends JFrame {

private static final long serialVersionUID = 1L;
private JPanel jp;
private JFrame jf;

public Snake() {

    initlookandfeel();

    jf = new JFrame();
    jf.setVisible(true);
    jf.setBounds(200, 200, 500, 500);
    jp = new JPanel();
    jp.setVisible(true);
    jf.setContentPane(jp);
    jp.setLayout(null);
    jp.setBounds(0, 0, jf.getWidth(), jf.getHeight());
    jf.setTitle("NIRAV KAMANI");
    jp.repaint();

}

public static void main(String[] args) {

    JFrame.setDefaultLookAndFeelDecorated(true);
    Snake sn = new Snake();
}

public void paint(Graphics g) {

    g.setColor(Color.red);
    g.drawString("NIRAV KAMANI", 50, 50);

}

public void initlookandfeel() {
    String lookandfeel;
    lookandfeel = "javax.swing.plaf.metal.MetalLookAndFeel";

    try {
        UIManager.setLookAndFeel(lookandfeel);
        MetalLookAndFeel.setCurrentTheme(new DefaultMetalTheme());
        UIManager.setLookAndFeel(new MetalLookAndFeel());
    } catch (Exception e) {
        System.out.println("" + e);
    }

}
}

I know that i am making some mistakes related to JPanel or JFrame. But i am unable to understand what's the mistake i am doing?And why? I think that there is something like one layer is overridden by another so the string is not displayed.But what i have to do if i want to display String inside JPanel?

Upvotes: 0

Views: 195

Answers (1)

MadProgrammer
MadProgrammer

Reputation: 347244

The main reason you're having problems is the frame that is displaying on the screen isn't the one you think you're painting to...

Basically, you created a new class that extends from a JFrame

public class Snake extends JFrame {

The completely ignored it in your constructor...

public Snake() {

    initlookandfeel();

    // I'm a new instance of a JFrame which has nothing to do with the
    // instance of Snake...
    jf = new JFrame();
    jf.setVisible(true);
    jf.setBounds(200, 200, 500, 500);
    jp = new JPanel();
    jp.setVisible(true);
    jf.setContentPane(jp);
    // Bad idea, JFrame uses a `BorderLayout` anyway, which will do the job you want
    jp.setLayout(null);
    // Bad idea
    // The frame contains a border, possibly a menu bar and other components.  The
    // visible size of the frame will actually be smaller then it's size...
    jp.setBounds(0, 0, jf.getWidth(), jf.getHeight());
    jf.setTitle("NIRAV KAMANI");
    jp.repaint();

}

Now. Before you fire up your editor to make corrections, let's see if we can make it even better...

  1. Use a layout manager. Makes life easier.
  2. You're overriding the paint method of a top level container, this is, generally a bad idea and you found it one of the reasons why. A frame has a lot on it, normally, it has a JLayeredPane and a content pane, but you've also added another panel ontop of it.
  3. You should avoid extending from top level containers. This will make your components more re-usable and flexible, as you're not locking yourself into deployment requirement...

Instead. Make your self a custom component, say extending from something like JPanel, override it's paintComponent method and perform you custom painting there.

You should AWLAYS call super.paintXxx as the paint methods are chained together, failing to call one could greatly mess up the paint process, leaving artifacts and remnants of other painted components on it...

Take a look at Performing Custom Painting for more details

Update with Example

enter image description here

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class CustomPainting {

    public static void main(String[] args) {
        new CustomPainting();
    }

    public CustomPainting() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            FontMetrics fm = g2d.getFontMetrics();
            String text = "Hello world";
            int x = (getWidth() - fm.stringWidth(text)) / 2;
            int y = ((getHeight() - fm.getHeight()) / 2) + fm.getAscent();
            g2d.drawString(text, x, y);
            g2d.dispose();
        }
    }
}

Upvotes: 2

Related Questions