Java 仅当将鼠标悬停在上方时,才会绘制零部件

Java 仅当将鼠标悬停在上方时,才会绘制零部件,java,swing,Java,Swing,有人能解释为什么我的组件只有在我悬停在它们应该在的位置时才会被绘制吗 我设置了一个无边界的框架,可以拖动到任何地方,我试图在右上角创建一个退出按钮,但直到我将鼠标悬停在它上面,它才被绘制出来。我在JFrame上画了一个背景图像,然后画了我的按钮,并将整个画面设置为可见 import java.awt.*; import java.awt.event.*; import javax.imageio.ImageIO; import javax.swing.*; public class GUI e

有人能解释为什么我的组件只有在我悬停在它们应该在的位置时才会被绘制吗

我设置了一个无边界的框架,可以拖动到任何地方,我试图在右上角创建一个退出按钮,但直到我将鼠标悬停在它上面,它才被绘制出来。我在JFrame上画了一个背景图像,然后画了我的按钮,并将整个画面设置为可见

import java.awt.*;
import java.awt.event.*;
import javax.imageio.ImageIO;
import javax.swing.*;

public class GUI extends JFrame
{
    private Image Background = null;
    private static Point Offset = new Point();

    public GUI() {
        this.setUndecorated(true);
        this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        AddListeners();
        SetCustomTheme();
        LoadBackground();
        Layout();
        pack();
        this.setSize(300, 300);
        this.setVisible(true);
    }

    private void Layout() {
        GroupLayout Info = new GroupLayout(this.getContentPane());
        this.getContentPane().setLayout(Info);
        JButton Button = new JButton();

        Info.setHorizontalGroup(
            Info.createSequentialGroup()
               .addComponent(Button)
         );

        Info.setVerticalGroup(
            Info.createParallelGroup()
                .addComponent(Button)
        );
    }

    private void SetCustomTheme() {
        try {
            UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
        }
    }

    private void LoadBackground() {
        try {
            Background = ImageIO.read(getClass().getResource("Images/meh.png"));
        } catch (Exception Ex) {

        }
    }

    private void SetCustomIcon() {
        Image Icon = Toolkit.getDefaultToolkit().getImage("Images/lol.jpg");
        setIconImage(Icon);
    }

    private void AddListeners() {
        this.addMouseListener(new MouseAdapter() {
            @Override public void mousePressed(MouseEvent e) {
              Offset.x = e.getX();
              Offset.y = e.getY();
            }
          });

        this.addMouseMotionListener(new MouseMotionAdapter() {
            @Override public void mouseDragged(MouseEvent e) {
              Point p = getLocation();
              setLocation(p.x + e.getX() - Offset.x, p.y + e.getY() - Offset.y);
            }
          });
    }

    @Override public void paint(Graphics g) {
        g.drawImage(Background, 0,0,this.getWidth(),this.getHeight(), null);
    }
}
  • 与UI的所有交互必须在事件调度线程内执行
  • 您应该避免从顶级容器(如
    JFrame
    )进行扩展,而是使用
    JPanel
  • 未能遵守
    喷漆
    链合同将阻止任何子组件开始喷漆
  • 用于执行自定义绘制的首选替代方法是
    paintComponent
  • 你可能想通读一遍

    试试这样的方法

    public class BadPaint01 {
    
        public static void main(String[] args) {
            new BadPaint01();
        }
    
        public BadPaint01() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    }
    
                    JFrame frame = new JFrame();
                    Image Icon = Toolkit.getDefaultToolkit().getImage("Images/lol.jpg");
                    frame.setIconImage(Icon);
                    frame.setUndecorated(true);
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setLayout(new BorderLayout());
                    frame.add(new GUI());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        public static class GUI extends JPanel {
    
            private Image Background = null;
            private static Point Offset = new Point();
    
            public GUI() {
                AddListeners();
                SetCustomTheme();
                LoadBackground();
            }
    
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(300, 300);
            }
    
            private void Layout() {
                GroupLayout Info = new GroupLayout(this);
                setLayout(Info);
                JButton Button = new JButton();
    
                Info.setHorizontalGroup(
                        Info.createSequentialGroup()
                        .addComponent(Button));
    
                Info.setVerticalGroup(
                        Info.createParallelGroup()
                        .addComponent(Button));
            }
    
            private void SetCustomTheme() {
                try {
                    UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }
            }
    
            private void LoadBackground() {
                try {
                    Background = ImageIO.read(getClass().getResource("Images/meh.png"));
                } catch (Exception Ex) {
                }
            }
    
            private void AddListeners() {
                this.addMouseListener(new MouseAdapter() {
                    @Override
                    public void mousePressed(MouseEvent e) {
                        Offset.x = e.getX();
                        Offset.y = e.getY();
                    }
                });
    
                this.addMouseMotionListener(new MouseMotionAdapter() {
                    @Override
                    public void mouseDragged(MouseEvent e) {
                        Point p = getLocation();
                        setLocation(p.x + e.getX() - Offset.x, p.y + e.getY() - Offset.y);
                    }
                });
            }
    
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g); //To change body of generated methods, choose Tools | Templates.
                g.drawImage(Background, 0, 0, this.getWidth(), this.getHeight(), null);
            }
        }
    }
    
    你可能还想通读一遍,你不会因为忽略他们而交到任何朋友;)

  • 与UI的所有交互必须在事件调度线程内执行
  • 您应该避免从顶级容器(如
    JFrame
    )进行扩展,而是使用
    JPanel
  • 未能遵守
    喷漆
    链合同将阻止任何子组件开始喷漆
  • 用于执行自定义绘制的首选替代方法是
    paintComponent
  • 你可能想通读一遍

    试试这样的方法

    public class BadPaint01 {
    
        public static void main(String[] args) {
            new BadPaint01();
        }
    
        public BadPaint01() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    }
    
                    JFrame frame = new JFrame();
                    Image Icon = Toolkit.getDefaultToolkit().getImage("Images/lol.jpg");
                    frame.setIconImage(Icon);
                    frame.setUndecorated(true);
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setLayout(new BorderLayout());
                    frame.add(new GUI());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        public static class GUI extends JPanel {
    
            private Image Background = null;
            private static Point Offset = new Point();
    
            public GUI() {
                AddListeners();
                SetCustomTheme();
                LoadBackground();
            }
    
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(300, 300);
            }
    
            private void Layout() {
                GroupLayout Info = new GroupLayout(this);
                setLayout(Info);
                JButton Button = new JButton();
    
                Info.setHorizontalGroup(
                        Info.createSequentialGroup()
                        .addComponent(Button));
    
                Info.setVerticalGroup(
                        Info.createParallelGroup()
                        .addComponent(Button));
            }
    
            private void SetCustomTheme() {
                try {
                    UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }
            }
    
            private void LoadBackground() {
                try {
                    Background = ImageIO.read(getClass().getResource("Images/meh.png"));
                } catch (Exception Ex) {
                }
            }
    
            private void AddListeners() {
                this.addMouseListener(new MouseAdapter() {
                    @Override
                    public void mousePressed(MouseEvent e) {
                        Offset.x = e.getX();
                        Offset.y = e.getY();
                    }
                });
    
                this.addMouseMotionListener(new MouseMotionAdapter() {
                    @Override
                    public void mouseDragged(MouseEvent e) {
                        Point p = getLocation();
                        setLocation(p.x + e.getX() - Offset.x, p.y + e.getY() - Offset.y);
                    }
                });
            }
    
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g); //To change body of generated methods, choose Tools | Templates.
                g.drawImage(Background, 0, 0, this.getWidth(), this.getHeight(), null);
            }
        }
    }
    

    你可能还想通读一遍,你不会因为忽略他们而交到任何朋友;)

    如果我记得清楚的话,
    ToolKit.getImage
    返回一个
    图像
    ,该图像可能没有完全加载。当您将鼠标悬停在它上方时,它可能同时已在后台加载。 改为这样做(类似于您的背景行):


    (为了更好地理解,您可能需要搜索
    MediaTracker
    ,我相信它是用来确保图像已完全加载的。)

    如果我记得很清楚,
    ToolKit.getImage
    返回一个可能未完全加载的
    图像。当您将鼠标悬停在它上方时,它可能同时已在后台加载。
    改为这样做(类似于您的背景行):


    (为了更好地理解,您可能需要搜索
    MediaTracker
    ,我相信这是用来确保映像完全加载的。)

    那么为什么Netbeans从JFrame而不是JPanel扩展因为这不是一个无效的操作,只是一个错误的建议。有时,您可能希望向
    JFrame
    添加其他功能,但在这种情况下,您没有添加任何价值。此外,在顶级容器上绘制是一个坏主意,因为1-它们不是双缓冲的,2-框架有一个
    JRootPane
    ontop,它包含内容窗格,所以您所做的任何绘制都将在内容的下面或上面进行,这在您的情况下是不可取的,因为根窗格将隐藏您的工作(如果您确实正确地使用了绘制机制。Java允许您从任何线程更新UI组件,但这被认为是一种不好的做法,开发人员和API之间有一个理解契约,尽管您可以打破这个契约,但希望事情很快就变好。@DavidKroukamp“那为什么我的车能跑220公里?”那么为什么Netbeans是从JFrame扩展而不是从JPanel扩展的呢?:s因为这不是一个无效的操作,只是一个不明智的操作。有时候,您可能想向
    JFrame
    添加额外的功能,但在这种情况下,您没有添加任何值。此外,在顶级容器上绘制也是一个坏主意,因为1-它们是not双缓冲和2-框架有一个
    JRootPane
    ontop,其中包含内容窗格,因此您所做的任何绘制都将在内容下方或上方进行,这在您的情况下是不可取的,因为根窗格将隐藏您的工作(如果您确实正确地使用了绘图机制。Java允许您从任何线程更新UI组件,但这被认为是一种不好的做法,开发人员和API之间有一个理解契约,尽管您可以打破这个契约,但希望事情很快就变好。@DavidKroukamp see”为什么我的车能跑220公里