【问题标题】:Graphics class seems to be overriding JFrame/JPanel图形类似乎覆盖了 JFrame/JPanel
【发布时间】:2013-07-24 00:16:24
【问题描述】:

我在理解 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**********
}

【问题讨论】:

    标签: java swing graphics jframe jpanel


    【解决方案1】:

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

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

    阅读 Custom Painting 教程上的 Swing 教程以获取更多信息和示例。

    【讨论】:

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

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

      查看Performing Custom Painting 和Painting in AWT and Swing 了解更多详情。

      另外,我没有看到你在哪里调用loadImage,所以图像永远不会加载

      我还建议您使用ImageIO 读取Reading/Loading an Image,当它无法读取图像文件时会抛出Exception,这比ImageIcon 更有用,后者根本失败默默地

      用简单的例子更新

      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- 你最好有充分的理由不使用布局管理器

      【讨论】:

      • 谢谢!它帮助很大。
      • 你能改一下代码给我看看。我明白你在说什么,但现在我正在努力将什么放在主类中或它自己的位置?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-29
      • 1970-01-01
      • 1970-01-01
      • 2018-09-14
      • 1970-01-01
      • 2015-02-04
      相关资源
      最近更新 更多