0

我在理解 JPanel、JFrame 和图形类的整个结构以及扩展和覆盖等方面遇到了一些麻烦。我似乎一切正常,直到我添加了图形类,然后我的 JPanel/JFrame 上的按钮等不再出现。我发现它与覆盖或超级有关?但我真的需要澄清一下。非常感谢!

为了便于查看,我稍微缩小了代码范围。

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.TitledBorder;

public class windowBuild extends JFrame {

    private static final long serialVersionUID = 1L;
    private JPanel contentPane;
    private int energy = 4;
    private JButton btnClaw = new JButton("Claw");
    private Image bg;
    private boolean loaded = false;

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                windowBuild frame = new windowBuild();
                frame.setVisible(true);

            }
        });
    }

    private class ButtonHandler implements ActionListener {

        public void actionPerformed(ActionEvent e) {
            String which = e.getActionCommand();
            if (which.equals("Claw")) {
                energy = energy - 1;
                System.out
                        .println("Player one's dragon clawed the opponent. Dragon's energy is now at: "
                                + energy);
            }

        }

    }

    public void loadImage() {
        bg = new ImageIcon("C:\\res\\dragonDuelBackground.jpeg").getImage();
        loaded = true;
        repaint();
    }

    public windowBuild() {
        ButtonHandler bh;
        System.out.println("Starting frame...");
        bh = new ButtonHandler();
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 800, 600);
        contentPane = new JPanel();
        contentPane.setBorder(new TitledBorder(null, "Dragon Duel",
                TitledBorder.CENTER, TitledBorder.TOP, null, Color.CYAN));
        setContentPane(contentPane);
        contentPane.setLayout(null);

        btnClaw.setBounds(273, 511, 109, 39);
        contentPane.add(btnClaw);
        btnClaw.addActionListener(bh);

    }
//********************************************************************
//  public void paint(Graphics g) {
//      if (loaded) {
//          g.drawImage(bg, 400, 400, null);
//      }
//  }
//***************Uncomment this and the code won't work anymore**********
}
4

2 回答 2

2
  1. 避免直接从JFrame. 您不会向框架添加任何新功能,并且如果这样做,您会限制 UI 的可重用性(因为您不能将框架添加到其他任何东西)
  2. 不要覆盖paint顶级容器。有很多很好的理由,但主要问题是框架包含许多不同的层(JLayeredPane, contentPane),这些层可能会覆盖您所做的任何事情
  3. 您必须致电super.paintXxx以确保油漆链完好无损。

相反,创建一个单独的类(例如从类似的东西扩展JPanel)并覆盖它的paintComponent方法。或者更好。简单的使用 aJLabel来显示图像

查看在 AWT 和 Swing中执行自定义绘画和绘画以了解更多详细信息。

另外,我看不到您在哪里打电话loadImage,因此永远不会加载图像

我还建议您阅读阅读/加载图像using ,当它无法读取图像文件时ImageIO会抛出一个错误,这比它简单地默默失败更有用ExceptionImageIcon

用简单的例子更新

在此处输入图像描述

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.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.TitledBorder;

public class TestGraphics {

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

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

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private int energy = 4;
        private JButton btnClaw = new JButton("Claw");
        private BufferedImage bg;

        public TestPane() {
            setBackground(Color.WHITE);
            try {
                bg = ImageIO.read(new File("dragon.gif"));
            } catch (IOException ex) {
                ex.printStackTrace();
            }

            ButtonHandler bh;
            bh = new ButtonHandler();
            setBorder(new TitledBorder(null, "Dragon Duel",
                    TitledBorder.CENTER, TitledBorder.TOP, null, Color.CYAN));
            setLayout(new BorderLayout());

            JPanel buttonPane = new JPanel();
            buttonPane.setOpaque(false);
            buttonPane.add(btnClaw);

            add(buttonPane, BorderLayout.SOUTH);
            btnClaw.addActionListener(bh);
        }

        @Override
        public Dimension getPreferredSize() {
            return bg == null ? new Dimension(200, 200) : new Dimension(bg.getWidth(), bg.getHeight());
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (bg != null) {
                Graphics2D g2d = (Graphics2D) g.create();
                int x = (getWidth() - bg.getWidth()) / 2;
                int y = (getHeight() - bg.getHeight()) / 2;
                g2d.drawImage(bg, x, y, this);
                g2d.dispose();
            }
        }

        private class ButtonHandler implements ActionListener {

            public void actionPerformed(ActionEvent e) {
                String which = e.getActionCommand();
                if (which.equals("Claw")) {
                    energy = energy - 1;
                    System.out
                            .println("Player one's dragon clawed the opponent. Dragon's energy is now at: "
                            + energy);
                }

            }
        }
    }
}

Ps-你最好有充分的理由不使用布局管理器

于 2013-07-24T00:23:14.367 回答
2

取消注释,代码将不再工作

不要覆盖顶级容器(JFrame、JDialog...)的paint()。自定义绘制是通过覆盖paintComponent()JPanel(或 JComponent)的方法来完成的。然后将面板添加到框架中。不要忘记调用 super.paintComponent(...)。

阅读自定义绘画教程的 Swing 教程以获取更多信息和示例。

于 2013-07-24T00:20:21.913 回答