我只学习了 Java Swing 1 周,所以我尝试完成一些练习。这是我的代码。我将 9 图标设置为 9 按钮,但它没有显示在按钮上。
package mypack;
import java.awt.Color;
import javax.swing.*;
public class PuzzleGame extends JFrame{
static JButton bt1,bt2,bt3,bt4,bt5,bt6,bt7,bt8,bt9,btNew,btExit;
static JLabel move, moveNum, time, timeNum;
public PuzzleGame(){
createMyGUI();
}
public static void createMyGUI(){
JFrame jf = new JFrame("Game Puzzle Java");
JPanel jpl = new JPanel();
Icon icSpace = new ImageIcon("images/0.png");
Icon ic1 = new ImageIcon("images/1.png");
Icon ic2 = new ImageIcon("images/2.png");
Icon ic3 = new ImageIcon("images/3.png");
Icon ic4 = new ImageIcon("images/4.png");
Icon ic5 = new ImageIcon("images/5.png");
Icon ic6 = new ImageIcon("images/6.png");
Icon ic7 = new ImageIcon("images/7.png");
Icon ic8 = new ImageIcon("images/8.png");
jpl.setSize(100,100);
jpl.setBounds(480, 50, 200, 200);
jpl.setBackground(Color.BLUE);
move = new JLabel("Move:");
move.setBounds(480,10,50,20);
moveNum = new JLabel("0");
moveNum.setBounds(530, 10, 50, 20);
time = new JLabel("Time:");
time.setBounds(580, 10, 50, 20);
timeNum = new JLabel("0");
timeNum.setBounds(630,10,50,20);
btNew = new JButton("New Game");
btNew.setBounds(480, 270, 200, 80);
btExit = new JButton("Exit");
btExit.setBounds(480, 370, 200, 80);
jf.add(move);
jf.add(moveNum);
jf.add(time);
jf.add(timeNum);
jf.add(btNew);
jf.add(btExit);
jf.add(jpl);
jf.setSize(700, 500);
jf.setLocation(300,20);
jf.setLayout(null);
jf.setResizable(false);
jf.setVisible(true);
bt1 = new JButton();
bt1.setBounds(10, 10, 150, 150);
bt1.setIcon(ic1);
bt2 = new JButton();
bt2.setBounds(160, 10, 150, 150);
bt2.setIcon(ic2);
bt3 = new JButton();
bt3.setBounds(310, 10, 150, 150);
bt3.setIcon(ic3);
bt4 = new JButton();
bt4.setBounds(10, 160, 150, 150);
bt4.setIcon(ic4);
bt5 = new JButton();
bt5.setBounds(160, 160, 150, 150);
bt5.setIcon(ic5);
bt6 = new JButton();
bt6.setBounds(310, 160, 150, 150);
bt6.setIcon(ic6);
bt7 = new JButton();
bt7.setBounds(10, 310, 150, 150);
bt7.setIcon(ic7);
bt8 = new JButton();
bt8.setBounds(160, 310, 150, 150);
bt8.setIcon(ic8);
bt9 = new JButton();
bt9.setBounds(310, 310, 150, 150);
bt9.setIcon(icSpace);
jf.add(bt1);
jf.add(bt2);
jf.add(bt3);
jf.add(bt4);
jf.add(bt5);
jf.add(bt6);
jf.add(bt7);
jf.add(bt8);
jf.add(bt9);
}
public static void main(String[] args){
PuzzleGame.createMyGUI();
}
}
我认为 setIcon 方法不适用于 Button。另外,有人告诉我如何用我的代码在益智游戏中设置一个 Action 将困惑的图片排列成完整的图片。
最佳答案
我在您的代码中发现了一些问题:
您正在扩展
JFrame
并在类中创建一个新的JFrame
对象。您永远不会使用您的类(扩展类)的JFrame
。因此,明智的做法是删除它。您应该避免扩展
JFrame
,因为这意味着您的类是JFrame
,JFrame
是一个刚性的容器,而不是让您的程序基于 JPanel 并将它们添加到其他容器。引用:Using extends JFrame vs calling it inside of class .您已经不再使用
static
关键字。static
不是跨方法传字,它会对你造成很大的伤害,不要再使用它了。相反,创建类的实例并以这种方式调用您的方法。您有多个执行相同操作的对象:
Icon ic1 = new ImageIcon("images/1.png"); Icon ic2 = new ImageIcon("images/2.png"); ...
为什么不使用
Icon[] 图标
并对其进行迭代?您正在使用邪恶的
null 布局
和setBounds(...)
,停止使用它,而使用 layout managers以及EmptyBorder s 用于组件之间的额外间距。虽然像素完美定位可能是 Swing 新手创建复杂 GUI 的最简单方法,但您使用它的次数越多,您会发现与此相关的问题就越多。 Swing 必须处理不同的平台、屏幕尺寸、分辨率、PLAF 等。这就是为什么像素完美的 GUI 只是一种幻想。引用见Null layout is evil以及 this question 中的答案进一步解释为什么应该避免
空布局
。在添加所有组件之前,您要使
JFrame
可见,这可能会导致 GUI 在显示之前无法完全绘制,并可能导致出现“错误”组件只有在将鼠标悬停在其应在的位置时才会显示。JFrame#setVisible(...)
应该是最后调用的行之一。您正在调用
JFrame#setSize(...)
,您应该覆盖getPreferredSize
您的内部JPanel
,然后调用JFrame#pack()
,因此您的JFrame
将其尺寸减小到所有组件都以其首选尺寸可见的最小尺寸。请参阅Should I avoid the use of setPreferred|Maximum|MinimumSize in Java Swing? (普遍共识是"is")。您没有将程序放在 Event Dispatch Thread (EDT) 上,Swing 不是线程安全的,这可能会使您的程序有时卡住,您可以通过更改
main(...)
方法来解决此问题,如下所示:public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { //Your constructor here } }); }
您的图像可能没有被定位,但是一旦您将程序打包为 JAR 文件,它们就会成为嵌入式资源,因此,明智的做法是开始将文件(或图像)视为已经存在的文件(或图像)。
您可以更改例如:
Icon ic1 = new ImageIcon("images/1.png");
对此:
Icon ic1 = null;
try {
ic1 = new ImageIcon(ImageIO.read(Thread.currentThread().getContextClassLoader().getResourceAsStream("images/1.png")));
} catch (IOException e) {
e.printStackTrace();
}
这将使您的图像被加载。看这个question以及接受的答案供引用。
这应该可以解决您的问题,并且您的 GUI(我用 2 个图标完成)应该如下所示:
但是如果您想遵循我的上述建议,您可以尝试此代码,它使用布局管理器、空边框、覆盖 getPreferredSize()
方法并使用 pack()
等,并生成一个与您已有的非常相似的 GUI:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class ImagesInResourcesExample {
private JFrame frame;
private JPanel buttonsPane;
private JPanel rightPane;
private JPanel scorePanel;
private JPanel colorPanel;
private BufferedImage img;
private JButton[][] buttons;
private JLabel moveLabel;
private JLabel timeLabel;
private JButton newGameButton;
private JButton exitButton;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new ImagesInResourcesExample().createAndShowGui();
}
});
}
@SuppressWarnings("serial")
public void createAndShowGui() {
frame = new JFrame(getClass().getSimpleName());
buttons = new JButton[3][3];
moveLabel = new JLabel("Move: 0");
timeLabel = new JLabel("Time: 0");
colorPanel = new JPanel() {
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
};
colorPanel.setBackground(Color.BLUE);
colorPanel.setOpaque(true);
newGameButton = new JButton("New Game");
exitButton = new JButton("Exit");
try {
img = ImageIO.read(Thread.currentThread().getContextClassLoader().getResourceAsStream("images/arrow.png"));
} catch (IOException e) {
e.printStackTrace();
}
buttonsPane = new JPanel() {
@Override
public Dimension getPreferredSize() {
return new Dimension(500, 500);
}
};
buttonsPane.setLayout(new GridLayout(3, 3));
buttonsPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
for (int i = 0; i < buttons.length; i++) {
for (int j = 0; j < buttons.length; j++) {
buttons[i][j] = new JButton(new ImageIcon(img));
buttonsPane.add(buttons[i][j]);
}
}
rightPane = new JPanel();
rightPane.setLayout(new GridBagLayout());
scorePanel = new JPanel();
scorePanel.setLayout(new GridLayout(1, 2, 10, 10));
scorePanel.add(moveLabel);
scorePanel.add(timeLabel);
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.fill = GridBagConstraints.BOTH;
gbc.insets = new Insets(10, 10, 10, 10);
rightPane.add(scorePanel, gbc);
gbc.gridx = 0;
gbc.gridy = 1;
rightPane.add(colorPanel, gbc);
gbc.gridy = 2;
gbc.ipadx = 30;
gbc.ipady = 80;
rightPane.add(newGameButton, gbc);
gbc.gridy = 3;
rightPane.add(exitButton, gbc);
rightPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
frame.add(buttonsPane, BorderLayout.CENTER);
frame.add(rightPane, BorderLayout.EAST);
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
正如你所看到的,代码最多比你已有的代码长 20 行,但是如果你继续向两个程序添加元素,我所做的代码将来会比你的代码短。最终将使用空布局
。
我希望您遵循上述建议并以这个例子为例并尝试理解它并改进它。
关于java - 使用 Java 将 Image 设置为 Button 并在 Puzzle Game 中处理 ActionListener,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42443759/