【问题标题】:Newly created JButton doesn't override the previously created JButtons新创建的 JButton 不会覆盖之前创建的 JButton
【发布时间】:2013-01-19 03:45:56
【问题描述】:

基本上,我编写的是一个益智游戏。

它包含一个图像,图像进一步分为 9 块,放置在包含 3x3 JButton GridLayout 的 JPanel 上。最初,9 个按钮是空的。当用户点击“开始游戏”时,9个按钮将显示按钮上的图像。

我使用 setPreferredSize() 来设置包含 9 个空 JButton 的 JPanel 的大小。之后,我使用 Inset ( 0,0,0,0 ) 使按钮的内容填满整个按钮。

但是现在,当我想添加图像按钮以在用户单击“开始游戏”时替换空按钮时,它不起作用。

我认为这是因为我之前设置的 setPreferredSize() 阻止了 Insets 值的工作。

我插入了一些system.out.println 值来检查方法是否正在运行,它运行了,但是当用户单击“开始游戏”时,图像仍然拒绝出现在按钮上。

    public class GameFrame extends JFrame implements ActionListener {
        private JButton button1;
        private JButton[] button = new JButton[9];
        private Insets buttonMargin;
        private boolean testImageMethod;
        private JPanel puzpiece;

        public GameFrame(){
            //.. coding ..

            // create new buttons - button1
            button1  = new JButton("Start Game");
            // add action event to "Start" button
            button1.addActionListener(this);

            // creates a new panel for the splitted puzzle pieces
            puzpiece = new JPanel();
            puzpiece.setLayout(new GridLayout(3,3));

            // check if testImageMethod boolean ( in setupImage() ) is true, 
            //if it isn't, adds 9 buttons w/o images.
             for(int a=0; a<9; a++){
                 if(testImageMethod){
                 }
                 else{
                     // adds 9 buttons without images 
                   button[a] = new JButton();  
                   puzpiece.add(button[a]);
                   puzpiece.setPreferredSize(new Dimension(500,200));
                 }


             }
             // adds puzpiece panel into the frame 
              this.add(puzpiece,BorderLayout.WEST);     
            //.. coding ..

        }

        public void actionPerformed(ActionEvent e){
            if (e.getSource() == button1){
                // puzpiece.button.setVisible(false);
                //puzpiece.remove(button);

                // call setImage() method
                setImage();

                for(int a=0; a<9; a++){
                // adds the new 9 buttons with images into panel
                puzpiece.add(button[a]);
                // test if method is running
                System.out.println("qq");
                }
            }
            else{
                System.out.println("bbb");
            }
        } 

        // method setImage() divides the image into subimages
        public void setImage(){
          //.. coding ..
          // test if method is running
          System.out.println("a");

            setupImage( count++, sc );
        }

        // method setupImage() adds the subimages to the buttons
        private void setupImage( int a, Image wi )
        { 
          // test if method is running
          System.out.println("d");

            buttonMargin = new Insets( 0, 0, 0, 0 );
            button[a] = new JButton( new ImageIcon( wi ) );
            button[a].setMargin( buttonMargin );

            // test if method is running
            System.out.println("e");

        } // end method setupImage()
    }

【问题讨论】:

  • 为什么要替换 JButtons?为什么不直接交换 JButton 显示的 ImageIcon?
  • 请检查@GagandeepBali 答案的编辑。他提供了一些很好的干净示例代码来说明他的观点。

标签: java image swing


【解决方案1】:

我不确定我到底知道你在做什么,但是,...

  • 您似乎正在使用 3x3 网格的普通 JButton 填充 JPanel,
  • 在按下按钮时,您正在添加显示图像的 JButton。
  • 但我没有看到您在添加新按钮之前删除了原始按钮。
  • 我也没有看到你在更换组件后在 puzpiece JPanel 上调用 revalidate()repaint()
  • 更重要的是,当在 puzpiece JPanel 中已经拥有的 JButton 中交换 ImageIcon 要容易得多时,为什么还要交换 JButton?这是我 10 分钟前在评论中推荐的内容,但现在我正在回答。

【讨论】:

  • 感谢您的提示。是的,你说的反映了我想做的事情。我尝试在之前的反复试验中调用 revalidate() 和 repaint(),但它创建了附加按钮而不是覆盖原来的 9 个按钮:O
【解决方案2】:

对于所说的JButton,只需setIcon,不要将JButton重新添加到JPanel,已经可见

一个小例子:

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

/**
 * Created with IntelliJ IDEA.
 * User: Gagandeep Bali
 * Date: 1/19/13
 * Time: 10:05 AM
 * To change this template use File | Settings | File Templates.
 */
public class ButtonImageTest
{
    private Icon infoIcon = UIManager.getIcon("OptionPane.informationIcon");
    private Icon errorIcon = UIManager.getIcon("OptionPane.errorIcon");
    private JButton button;
    private int counter = 1;

    private void displayGUI()
    {
        JFrame frame  = new JFrame("Button Image Test");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        JPanel contentPane = new JPanel();
        button = new JButton();
        button.setBorderPainted(false);
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (counter % 2 != 0)
                {
                    button.setIcon(errorIcon);
                    counter = 2;
                }
                else
                {
                    button.setIcon(infoIcon);
                    counter = 1;
                }
            }
        });
        contentPane.add(button);

        frame.setContentPane(contentPane);
        frame.setSize(100, 100);
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }
    public static void main(String... args)
    {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new ButtonImageTest().displayGUI();
            }
        });
    }
}

【讨论】:

  • 是的,正如我在之前制作的 cmets 中所说的那样。1+
  • 不错的详细示例代码!我将向 OP 发表评论以对其进行审查,因为他可能还没有看到它。
  • 不,没关系,基本上我只是为未来的访问者添加的,你的回答已经得到了 OP 正在寻找的每一个细节 :-) 谢谢你的回答 :-)
  • actionPerformed 方法的@override 的目的是什么?
  • 它告诉编译器你实际上覆盖了超类的某些方法,所以如果你在定义方法时犯了一些拼写错误,编译器可以检查超类中的所有方法与您的比较,以警告您此方法不会覆盖超类的任何方法。在没有 @Override 的情况下,(考虑到您在覆盖时拼写错误的方法)编译器会将这个拼写错误的方法视为该类的任何其他方法,并且不会产生任何错误。
猜你喜欢
  • 1970-01-01
  • 2013-09-07
  • 1970-01-01
  • 2013-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多