使用Java在Puzzle Game中将Image设置为Button并处理ActionListener [英] Set Image to Button and process ActionListener in Puzzle Game using Java

查看:23
本文介绍了使用Java在Puzzle Game中将Image设置为Button并处理ActionListener的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我只学习了 Java Swing 1 周,所以我尝试完成一些练习.这是我的代码.我将 9 图标设置为 9 按钮,但它没有显示在按钮上.

打包mypack;导入 java.awt.Color;导入 javax.swing.*;公共类 PuzzleGame 扩展 JFrame{静态 JButton bt1,bt2,bt3,bt4,bt5,bt6,bt7,bt8,bt9,btNew,btExit;静态 JLabel 移动、移动数、时间、时间数;公共拼图游戏(){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.setBounds(480,10,50,20);moveNum = new JLabel("0");moveNum.setBounds(530, 10, 50, 20);time = new JLabel("时间:");time.setBounds(580, 10, 50, 20);timeNum = new JLabel("0");timeNum.setBounds(630,10,50,20);btNew = new JButton("新游戏");btNew.setBounds(480, 270, 200, 80);btExit = new JButton("退出");btExit.setBounds(480, 370, 200, 80);jf.add(移动);jf.add(moveNum);jf.add(时间);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);}公共静态无效主(字符串 [] args){PuzzleGame.createMyGUI();}}

我认为 setIcon 方法不适用于 Button.另外,有人教我用我的代码在拼图游戏中如何设置一个动作将杂乱的图片排列成完整的图片.

解决方案

我发现您的代码存在一些问题:

  1. 您正在扩展 JFrame 并在您的类中创建一个新的 JFrame 对象.您永远不会使用您的类(扩展类)的 JFrame.所以删除它是明智的.

    你应该避免扩展JFrame,因为这意味着你的类是一个JFrameJFrame是一个刚性的容器,而是基于 JPanel 制作您的程序并将它们添加到其他容器中.参考:

    但是如果你想遵循我上面的建议,你可以试试这个代码,它使用布局管理器、空边框、覆盖 getPreferredSize() 方法并使用 pack()等,并生成与您已有的 GUI 非常相似的 GUI:

    import java.awt.BorderLayout;导入 java.awt.Color;导入 java.awt.Dimension;导入 java.awt.GridBagConstraints;导入 java.awt.GridBagLayout;导入 java.awt.GridLayout;导入 java.awt.Insets;导入 java.awt.image.BufferedImage;导入 java.io.IOException;导入 javax.imageio.ImageIO;导入 javax.swing.BorderFactory;导入 javax.swing.ImageIcon;导入 javax.swing.JButton;导入 javax.swing.JFrame;导入 javax.swing.JLabel;导入 javax.swing.JPanel;导入 javax.swing.SwingUtilities;公共类ImagesInResourcesExample {私人 JFrame 框架;私人 JPanel 按钮面板;私人 JPanel 右窗格;私人 JPanel scorePanel;私人 JPanel colorPanel;私有 BufferedImage img;私人 JButton[][] 按钮;私人 JLabel 移动标签;私人 JLabel 时间标签;私人 JButton newGameButton;私有 JButton 退出按钮;公共静态无效主(字符串 [] args){SwingUtilities.invokeLater(new Runnable() {公共无效运行(){new ImagesInResourcesExample().createAndShowGui();}});}@SuppressWarnings("串行")公共无效 createAndShowGui() {frame = new JFrame(getClass().getSimpleName());按钮 = 新 JButton[3][3];moveLabel = new JLabel("移动:0");timeLabel = new JLabel("时间:0");颜色面板 = 新 JPanel() {@覆盖公共维度 getPreferredSize() {返回新维度(200, 200);}};colorPanel.setBackground(Color.BLUE);colorPanel.setOpaque(true);newGameButton = new JButton("新游戏");exitButton = new JButton("退出");尝试 {img = ImageIO.read(Thread.currentThread().getContextClassLoader().getResourceAsStream("images/arrow.png"));} catch (IOException e) {e.printStackTrace();}buttonPane = 新 JPanel() {@覆盖公共维度 getPreferredSize() {返回新维度(500, 500);}};buttonPane.setLayout(new GridLayout(3, 3));buttonPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));for (int i = 0; i 

    如您所见,代码最多比您已有的代码长 20 行,但是如果您不断向两个程序添加元素,我所做的代码将来会比您的代码更短'最终会使用 null layout.

    我希望您遵循上述建议,并以这个例子尝试理解并改进它.

    I only learn Java Swing 1 week so I tried complete some exercises. This is my code. I set 9 icon to 9 button but it doesn't show on button.

    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();
        }   
    }
    

    I think method setIcon is not apply for Button. Besides, someone show me how to set a action to arrange mess picture into a complete picture in Puzzle Game with my code.

    解决方案

    I see some issues in your code:

    1. You're extending JFrame and creating a new JFrame object inside your class. You're never using the JFrame of your class (the extended one). So it's wise to just remove it.

      You should avoid extending JFrame because that means that your class is a JFrame, JFrame is a rigid container, instead make your programs based on JPanels and add them to other Containers. For reference see: Using extends JFrame vs calling it inside of class.

    2. You're over using the static keyword. static is not a cross method passing word, it will harm you a lot, stop using it. Instead create instances of your class and call your methods that way.

    3. You have multiple objects that do the same:

      Icon ic1 = new ImageIcon("images/1.png");
      Icon ic2 = new ImageIcon("images/2.png");
      ...
      

      Why not have an Icon[] icons and iterate over it?

    4. You're using the evil null layout and setBounds(...), stop using it and instead make use of the layout managers along with EmptyBorders for extra spacing between components.

      While pixel perfect positioning might be like the easiest way to Swing newbies to create complex GUIs, the more you use it, the more problems you'll find regarding this. Swing has to deal with different platforms, screen sizes, resolutions, PLAFs, etc. That's why pixel perfect GUIs are just an illusion. For reference see Null layout is evil and the answers in this question for a further explanation on why you should avoid null layout.

    5. You're making your JFrame visible before you have added all your components, this could cause your GUI to not be painted fully before it's shown and could cause a "bug" that the components don't display until you hover where they should be. JFrame#setVisible(...) should be one of the last lines to be called.

    6. You're calling JFrame#setSize(...), you should instead override the getPreferredSize of your inner JPanels and then call JFrame#pack(), so your JFrame reduces its size to the minimum size where all your components are visible on their preferred sizes. See Should I avoid the use of setPreferred|Maximum|MinimumSize in Java Swing? (The general consensus says "yes").

    7. You're not placing your program on the Event Dispatch Thread (EDT), Swing is not Thread safe and this could make your program to freeze sometimes, you can solve this by changing your main(...) method like this one:

      public static void main(String[] args) {
          SwingUtilities.invokeLater(new Runnable() {
              public void run() {
                  //Your constructor here
              }
          });
      }
      


    Your images probably aren't located, but they'll become embedded resources once you package your program as a JAR file, and thus, it's wise to start treating the files (or images) as if they already were.

    You can change for example:

    Icon ic1 = new ImageIcon("images/1.png");
    

    To this:

    Icon ic1 = null;
    try {
        ic1 = new ImageIcon(ImageIO.read(Thread.currentThread().getContextClassLoader().getResourceAsStream("images/1.png")));
    } catch (IOException e) {
        e.printStackTrace();
    }
    

    That will make your image to be loaded. See this question and the accepted answer for reference.

    That should solve your question, and your GUI (I did it with 2 icons) shoudl look like this one:

    But if you want to follow my above recommendations you could try this code, which uses layout managers, empty borders, overrides getPreferredSize() methods and uses pack(), etc and generates a really similar GUI like the one you already have:

    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);
        }
    }
    

    As you can see, the code is at most 20 lines longer than the one you already have, but if you keep adding elements to both programs, the one I did will, in a future, be shorter than the one you'll end up by using null layout.

    I hope you follow the above recommendations and take this example and try to understand it and improve it.

    这篇关于使用Java在Puzzle Game中将Image设置为Button并处理ActionListener的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆