我在理解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**********
}
答案 0 :(得分:2)
取消注释,代码将不再起作用
不要覆盖顶级容器的paint()(JFrame,JDialog ...)。通过覆盖JPanel(或JComponent)的paintComponent()
方法来完成自定义绘制。然后将面板添加到框架中。不要忘记调用super.paintComponent(...)。
阅读Custom Painting教程中的Swing教程,了解更多信息和示例。
答案 1 :(得分:2)
JFrame
延伸。您没有向框架添加任何新功能,并且如果您这样做,则限制了UI的可重用性(因为您无法向其他任何内容添加框架)paint
。有很多很好的理由,但主要的问题是框架容器有许多不同的层(JLayeredPane
,contentPane
)可以涂抹任何你做的事情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-你最好有充分的理由不使用布局管理器