Java:为什么在按钮上绘制背景图像?

标签 java swing jpanel jbutton paintcomponent

是否可以在同一个 JPanel 中的按钮后面绘制更新图像?我试图让菜单屏幕正常工作,但是当我尝试放入一个绘画循环来更新背景图像时,按钮消失了。注意:这些是自定义按钮,它们是不可见的,除了我使用 JButton.setIcon 放入其中的自定义图像(如果这对渲染有任何影响)。

public class MenuPanel extends JPanel{
    BufferedImage image;
    private int height =Toolkit.getDefaultToolkit().getScreenSize().height-37;
    private int width = Toolkit.getDefaultToolkit().getScreenSize().width;
    private JButton optionsButton = new JButton("Options");
    private JButton startButton = new JButton ("Start");

    public MenuPanel() {
        setLayout(null);
        setSize(width, height);

        try {image = ImageIO.read(new File("stuyrim.png"));}
        catch (Exception e) {Utilities.showErrorMessage(this, e);}

        optionsButton.addActionListener(e -> {
        //      optionsButton.getParent().getParent();
            });
        optionsButton.setOpaque(false);
        optionsButton.setBorderPainted(false);
        optionsButton.setContentAreaFilled(false);
        optionsButton.setSize(width/10,height/20);
        optionsButton.setVerticalTextPosition(SwingConstants.CENTER);
        optionsButton.setHorizontalTextPosition(SwingConstants.CENTER);
        optionsButton.setFont(new Font("TimesRoman", Font.PLAIN, 20));
        optionsButton.setLocation((width/3)-(width/20), (height/7*6)-(height/40));
        Image img = new ImageIcon("GUI Images/Button.png").getImage().getScaledInstance
            (optionsButton.getWidth(),optionsButton.getHeight(),java.awt.Image.SCALE_SMOOTH);
        optionsButton.setIcon(new ImageIcon(img));
        optionsButton.setForeground(Color.white);


        startButton.addActionListener(e -> {
        startButton.getParent().getParent().add(new Screen());
        startButton.getParent().getParent().add(new GamePanel());
        Graphics g = getGraphics();
        g.clearRect(0,0,width,height);
        startButton.getParent().getParent().remove(this);
        g.dispose();
            });
        startButton.setOpaque(false);
        startButton.setBorderPainted(false);
        startButton.setContentAreaFilled(false);
        startButton.setSize(width/10,height/20);
        startButton.setVerticalTextPosition(SwingConstants.CENTER);
        startButton.setHorizontalTextPosition(SwingConstants.CENTER);
        startButton.setFont(new Font("TimesRoman",Font.PLAIN, 20));
        startButton.setLocation((width/3*2)-(width/20), (height/7*6)-(height/40));
        Image img1 = new ImageIcon("GUI Images/Button.png").getImage().getScaledInstance
            (optionsButton.getWidth(),optionsButton.getHeight(),java.awt.Image.SCALE_SMOOTH);
        startButton.setIcon(new ImageIcon(img1));
        startButton.setForeground(Color.white);
        add(optionsButton);
        add(startButton);
        setVisible(true);
        revalidate();
        repaint();
    }

    public void paintComponent(Graphics g) {
        g.drawImage(image,0,0,width,height, null);
        g.dispose();
    }

}

最佳答案

有两个基本问题...

首先,正如 System.exit 所强调的那样,您应该在执行任何自定义绘制之前调用 super.paintComponent

原因是传递给 paintComponentGraphics 上下文是共享资源。在您的组件之前绘制的所有内容以及在它之后绘制的所有内容都将共享相同的 Graphics 上下文。

paintComponent 的其中一项工作是准备用于绘制的 Graphics 上下文(通常是用组件的背景色填充所需的空间)。

第二个是getGraphics的使用。 getGraphics 获取对用于绘制组件的最后一个 Graphics 上下文的引用(如果组件尚未绘制,则可以为 null) ,如果您在 Swings 定义的绘画链之外使用此绘画,这会产生随机且不可预测的结果。

Swing 使用被动渲染算法,也就是说,绘画以不规则的间隔发生,并且可能由于多种原因而发生,其中许多原因是您无法控制或没有发起的。

所有自定义绘画都应该在 Swing 定义的绘画链中完成,按照惯例,这通常是通过覆盖 paintComponent 方法来完成的。

看看Performing Custom PaintingPainting in AWT and Swing了解更多详情

关于Java:为什么在按钮上绘制背景图像?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23878889/

相关文章:

java - JOptionPane 的 While 循环返回 StringIndexOutOfBounds 异常

java - 如何通过单击按钮在面板的同一区域显示不同的 JPanel

java - 在面板顶部添加面板并且两者都可见

java - (在 Hibernate 5.1.0 中)由 : java. lang.ClassNotFoundException 引起:无法加载请求的类:MyJsonType

java - 随机 URL 在网站中造成泛滥

java - 关于 EMR 错误 : Java heap space 的 Mahout

java - JComponent 在什么情况下请求获得焦点?如何知道哪个组件实际上是焦点所有者?

java - 对两个 Eclipse 项目使用相同的 keystore ,但在同一系统上进行调试时它们无法通信

java - GUI 一次显示阵列的每个图像

java - 如何更改 JPanel 的字体大小