我在 paintcomponent 方法中的 JLabel 和 GUI 代码没有同时绘制

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

当我尝试绘制 JLabel 或我的 GUI 时,我最后添加到 JFrame 的任何内容都会被绘制,而其余部分永远不会被绘制或覆盖。如果您能帮助我找到在特定位置连同我的 GUI 绘制 JLabel 的解决方案,我将不胜感激。我听说过布局以及它如何帮助我,但是有很多不同的人对这个主题有不同的看法。这是我的代码。

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);
    }
}

如果我不清楚或有任何问题,请告诉我。我只希望 JLabel 和 GUI 绘图出现在 JFrame 上。请随时提出任何我应该重做的建议,感谢您抽出宝贵时间!

您永远不会从绘制方法中向组件添加组件。你永远不应该在 paint 方法中以任何方式修改组件的状态,绘画是为了绘画,没有别的。

参见 Painting in AWT and SwingPerforming Custom Painting 有关在 Swing 中绘画如何工作的更多详细信息...

您正在将三个组件添加到 BorderLayout 中的同一位置,一般情况下,通常只会显示最后一个组件,因为它是由 BorderLayout[= 管理的组件22=]

有关详细信息,请参阅 Laying Out Components Within a Container and How to Use BorderLayout

您还应该确保您是在事件调度线程的上下文中创建 UI,有关详细信息,请参阅 Initial Threads

绘制也与被绘制的组件相关,也就是说,0x0 是组件的左上角,任何超出组件可视范围的绘制都会丢失。

你也应该避免使用 static,一般来说,这很好地表明你的设计有问题,它在 UI 中变得特别混乱。如果你真的想听我抱怨 static 的邪恶,请查看

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();
        }

    }

}