Java 表单元素在激活之前不会完全显示,即单击

Java form elements not showing up fully until activated i.e. clicked on

我一直在尝试将 Java 表单元素(例如 textField 和 passwordField)添加到全屏独占模式框架。我一直遇到的问题是,当我 运行 代码时,我的表单元素不会完全显示或根本不会显示,直到我真正点击它们。

这是我的代码:

Master.java

import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.net.URL;

import javax.swing.ImageIcon;
import javax.swing.JFrame;

public class Master extends JFrame {

    private static final long serialVersionUID = -4927941474660261348L;
    static GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
    static GraphicsDevice gd = ge.getDefaultScreenDevice();
    static int WIDTH = gd.getDisplayMode().getWidth();
    static int HEIGHT = gd.getDisplayMode().getHeight();
    static Toolkit toolkit = Toolkit.getDefaultToolkit();
    static Graphics2D g2d = null;
    static FontMetrics metrics = null;
    static URL vignetteURL = null;
    static Image vignette = null;
    static Rectangle red = new Rectangle(WIDTH - 35, 0, 35, 35);

    public Master() {
        super("Project Zenith");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
        getContentPane().setLayout(null);
        setUndecorated(true);
        setResizable(false);
        gd.setFullScreenWindow(this);
        repaint();

        setIconImage(new ImageIcon(getClass().getResource("images/hex.png")).getImage());
        vignetteURL = getClass().getResource("images/vignette2.png");

        addMouseListener(new MouseListener() {
            @Override
            public void mouseClicked(MouseEvent e) {
                if(e.getX() >= red.getX() && e.getY() <= red.getHeight()) {
                    closeClicked();
                }
            }

            @Override
            public void mouseEntered(MouseEvent arg0) {

            }

            @Override
            public void mouseExited(MouseEvent arg0) {

            }

            @Override
            public void mousePressed(MouseEvent arg0) {

            }

            @Override
            public void mouseReleased(MouseEvent arg0) {

            }           
        });
    }

    public void update(Graphics g) {
        paint(g);
    }

    public void paint(Graphics g) {
        g2d = (Graphics2D) g;
        vignette = toolkit.getImage(vignetteURL);
        g2d.clearRect(0, 0, getWidth(), getHeight());
        g2d.setFont(new Font("Bebas Neue", Font.PLAIN, 25));
        metrics = g2d.getFontMetrics();
        g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        g2d.setColor(new Color(168, 168, 168, 200));
        g2d.drawString("Project Zenith", 10, HEIGHT - 10);
        g2d.setColor(new Color(0xFFA6A6));
        g2d.fill(red);
        g2d.drawImage(vignette, 0, 0, WIDTH, HEIGHT, this); 

    }

    public void closeClicked() {
        System.exit(0);
    }
}

Login.java

import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.RoundRectangle2D;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JPasswordField;
import javax.swing.JTextField;

public class Login extends Master {
    private static final long serialVersionUID = 1L;
    static Master l;
    static JTextField username;
    static JTextField password;
    static Graphics2D g2d = null;
    static FontMetrics metrics = null;
    static RoundRectangle2D loginRect = new RoundRectangle2D.Float((WIDTH / 2) - ((WIDTH / 4) / 2), (HEIGHT / 2) - ((HEIGHT / 4) / 2), (WIDTH / 4), (HEIGHT / 4), 20, 20);

    Login() {
        l = this;
        Font inputFont = new Font("Calibri", Font.PLAIN, 15);

        username = new JTextField();
        username.setBounds((WIDTH / 2) - (((int) loginRect.getY() - 10) / 2), (int) loginRect.getY() + 60, (int) loginRect.getY() - 10, 18);
        username.setFont(inputFont);
        username.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
        username.setEditable(true);
        username.setBackground(new Color(0xE6E6E6));
        //username.setVisible(true);
        getContentPane().add(username);

        password = new JPasswordField();
        password.setBounds((WIDTH / 2) - (((int) loginRect.getY() - 10) / 2), (int) loginRect.getY() + 110, (int) loginRect.getY() - 10, 18);
        password.setFont(inputFont);
        password.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
        password.setEditable(true);
        password.setBackground(new Color(0xE6E6E6));
        //password.setVisible(true);
        getContentPane().add(password);

        JButton loginButton = new JButton("Login");
        loginButton.setBounds((WIDTH / 2) - 40, (int) loginRect.getY() + 155, 80, 20);
        loginButton.setFont(inputFont);
        loginButton.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
        loginButton.setBackground(new Color(0xE6E6E6));
        //loginButton.setVisible(true);
        loginButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                System.out.println(username.getText());
            }
        });
        getContentPane().add(loginButton);
        repaint();
        setVisible(true);

    }

    public void paint(Graphics g) {
        super.paint(g);
        g2d = (Graphics2D) g;
        metrics = g2d.getFontMetrics();
        g2d.setColor(Color.WHITE);
        g2d.fill(loginRect);
        g2d.setColor(new Color(0xA8A8A8));
        g2d.drawString("Access Terminal", (Master.WIDTH / 2) - (metrics.stringWidth("Access Terminal") / 2), (int) loginRect.getY() + metrics.getHeight() + 2);
    }

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

首先查看 Painting in AWT and Swing and Performing Custom Painting 以了解如何在 Swing 中绘制。

基本问题是:

  1. 你正在打破绘画链
  2. 您正在绘制子组件

这是您不应该覆盖 paint 顶级容器的(原因之一)。相反,首先使用 JPanel 并覆盖它的 paintComponent(在执行任何自定义绘画之前调用 super.paintComponent

您还应该使用适当的布局管理器来更好地处理分辨率和字体渲染要求的​​差异。

查看 Laying Out Components Within a Container 了解更多详情

通过一些巧妙的计划,您可以做一些非常先进的事情

现在,显然这不是全屏显示,但这就是重点,您现在可以取消注释 gd.setFullScreenWindow(frame); 行,它会通过布局管理器的力量自动神奇地重新对齐。

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.RoundRectangle2D;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;

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();
                }
                GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
                GraphicsDevice gd = ge.getDefaultScreenDevice();

                Login login = new Login();
                JFrame frame = new JFrame("Project Zenith");
                frame.setUndecorated(true);
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(login);
                frame.pack();
                frame.setLocationRelativeTo(null);
//              gd.setFullScreenWindow(frame);
                frame.setVisible(true);
            }
        });
    }

    public static class Master extends JPanel {

        private static final long serialVersionUID = -4927941474660261348L;

        private Rectangle closeRect;

        public Master() {

            addMouseListener(new MouseListener() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    if (e.getX() >= closeRect.getX() && e.getY() <= closeRect.getHeight()) {
                        closeClicked();
                    }
                }

                @Override
                public void mouseEntered(MouseEvent arg0) {

                }

                @Override
                public void mouseExited(MouseEvent arg0) {

                }

                @Override
                public void mousePressed(MouseEvent arg0) {

                }

                @Override
                public void mouseReleased(MouseEvent arg0) {

                }
            });
        }

        @Override
        public void invalidate() {
            super.invalidate();
            closeRect = new Rectangle(getWidth() - 35, 0, 35, 35);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g;
            g2d.setFont(new Font("Bebas Neue", Font.PLAIN, 25));
            g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
            g2d.setColor(new Color(168, 168, 168, 200));
            FontMetrics fm = g2d.getFontMetrics();
            int y = (getHeight() - fm.getHeight()) + fm.getAscent();
            g2d.drawString("Project Zenith", 10, y);
            g2d.setColor(new Color(0xFFA6A6));
            g2d.fill(closeRect);
        }

        public void closeClicked() {
            System.exit(0);
        }
    }

    public static class Login extends Master {

        private static final long serialVersionUID = 1L;
        private JTextField username;
        private JTextField password;


        Login() {
            Font inputFont = new Font("Calibri", Font.PLAIN, 15);

            setLayout(new GridBagLayout());

            JPanel content = new JPanel(new GridBagLayout()) {
                @Override
                protected void paintComponent(Graphics g) {
                    super.paintComponent(g);
                    RoundRectangle2D loginRect = new RoundRectangle2D.Float(0, 0, getWidth() - 1, getHeight() - 1, 20, 20);
                    Graphics2D g2d = (Graphics2D) g;
                    g2d.setColor(Color.WHITE);
                    g2d.fill(loginRect);
                    g2d.setColor(new Color(0xA8A8A8));
                    g2d.draw(loginRect);
                }
            };
            content.setBorder(new EmptyBorder(20, 20, 20, 20));

            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridwidth = GridBagConstraints.REMAINDER;
            gbc.insets = new Insets(0, 0, 25, 0);

            gbc.gridx = 0;
            gbc.gridy = 0;

            JLabel label = new JLabel("Access Terminal");
            label.setFont(new Font("Bebas Neue", Font.PLAIN, 25));
            label.setForeground(new Color(0xA8A8A8));

            content.add(label, gbc);

            gbc.gridy++;
            username = new JTextField(25);
            username.setFont(inputFont);
            username.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
            username.setEditable(true);
            username.setBackground(new Color(0xE6E6E6));
            //username.setVisible(true);
            content.add(username, gbc);

            gbc.gridy++;
            password = new JPasswordField(25);
            password.setFont(inputFont);
            password.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
            password.setEditable(true);
            password.setBackground(new Color(0xE6E6E6));
            //password.setVisible(true);
            content.add(password, gbc);

            gbc.gridy++;

            JButton loginButton = new JButton("Login");
            loginButton.setFont(inputFont);
            loginButton.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
            loginButton.setBackground(new Color(0xE6E6E6));
            loginButton.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    System.out.println(username.getText());
                }
            });
            content.add(loginButton, gbc);

            add(content);

        }

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

基本上,在您的 Login 视图中,我使用复合组件来生成 "rounded border" 效果,创建 JPanel 并覆盖它的 paintComponent 方法来绘制效果。这为我提供了子组件的布局信息,以便确定效果应该有多大。然后将其添加到 Login 面板本身,并通过使用布局管理器,使其全部居中