Raheel138
Raheel138

Reputation: 147

My JLabel and GUI code in a paintcomponent method do not draw at the same time

When I try to draw a JLabel or my GUI, whatever I add to my JFrame last is drawn and the rest is just never drawn or painted over. I would appreciate if you could help me find a solution to draw the JLabel at a specific place along with my GUI. I have heard about layout and how it could help me with that, but there were many different people saying different things about this subject. Here is my code.

import java.util.*;
import java.awt.*;
import javax.swing.*;
import javax.swing.Timer;
import javax.swing.JPanel;
import javax.swing.JFrame;
import static java.lang.System.*;
import java.awt.event.*;
import java.awt.Graphics.*;


public class Main extends JPanel
{
    Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
    double w = screenSize.getWidth();
    double h = screenSize.getHeight();
    static JFrame f = new JFrame("Tic-Tac-Toe");
    static JPanel p = new JPanel();
    int width = (int)w;
    int height = (int)h;
    int width1a = width/2 - 300;
    int width2a = width/2 - 100;
    int width3a = width/2 + 100; 
    int width4a = width/2 + 300;
    int height1from = (int)height - 100;
    int height1to = (int)height - (int)(height/1.05);
    public void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        JLabel l = new JLabel("Hello World !");
        f.add(l);
        Graphics2D g2 = (Graphics2D) g;
        g2.setStroke(new BasicStroke(10));
        g.setColor(Color.black);
        g2.drawLine(width1a, height1from, width1a, height1to);
        g2.drawLine(width2a, height1from, width2a, height1to);
        g2.drawLine(width3a, height1from, width3a, height1to);
        g2.drawLine(width4a, height1from, width4a, height1to);
    }
    public static void main(String[] args)
    {
        Main m = new Main();
        f.setSize(400,300);
        f.setExtendedState(Frame.MAXIMIZED_BOTH); 
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setVisible(true);      
        JLabel l = new JLabel("Hello World !");               
        f.add(p);
        f.add(m);
    }
}

Please tell me if I was unclear or anything. I just want the JLabel and the GUI drawings to appear on the JFrame. Feel free to suggest anything I should redo and thank you for your time!

Upvotes: 1

Views: 831

Answers (1)

MadProgrammer
MadProgrammer

Reputation: 347314

You don't, ever, add components to a component from within a paint method. You should never modify the state of a component in any way from within a paint method, painting is for painting, nothing else.

See Painting in AWT and Swing and Performing Custom Painting for more details about how painting works in Swing...

You are adding three components to the same position within a BorderLayout, generally, only the last component would normally be shown, as it's the one that is been managed by the BorderLayout

See Laying Out Components Within a Container and How to Use BorderLayout for more details.

You should also make sure that you are creating your UI from within the context of the Event Dispatching Thread, see Initial Threads for more details

Painting is also contextual to the component been painted, that is, the 0x0 is the top left corner of the component, any painting done beyond the visual range of the component is simply lost.

You should also avoid the use of static, generally, this is a good indication that you have a problem with your design, it gets especially messy within a UI. If you really want to hear me whinge about the evils of static, check out this answer

Example

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

public class Test {

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

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

                JPanel blue = new JPanel();
                blue.setBackground(Color.BLUE);

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new JLabel("Hello world"), BorderLayout.NORTH);
                frame.add(new TestPane());
                frame.add(blue, BorderLayout.SOUTH);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            setLayout(new GridBagLayout());
            add(new JLabel("Hello World"));
        }

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

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            // This could actually be achieved using a EmptyBorder and a LineBorder
            // but this demonstrates the point...
            g2d.setColor(Color.RED);
            g2d.drawRect(10, 10, getWidth() - 20, getHeight() - 20);
            g2d.dispose();
        }

    }

}

Upvotes: 4

Related Questions