【问题标题】:JButtons won't update on button clickJButtons 不会在按钮单击时更新
【发布时间】:2014-03-03 12:50:57
【问题描述】:

目前显示一个带有 8x8 网格的随机颜色按钮的 GUI。 newButton 用于将分数显示重置为 0,并在单击后将网格重置为新的,就像它在启动时所做的那样。除了与 Java 显示它的按钮的方式和分层的工作方式有关之外,我还没有找到很多解决方案。这是我正在使用的 2 个类。

import javax.swing.JFrame; 
import javax.swing.*;
import java.awt.event.*;
import javax.swing.JPanel;
import java.awt.Color;

public class ShinyButtonsApp extends JFrame implements ActionListener {

    private static byte ROWS = 8;
    public int useThis; 
    ShinyButtons shiny = new ShinyButtons();
    public static ImageIcon[] icons = {new ImageIcon("RedButton.png"),
                                       new ImageIcon("OrangeButton.png"), 
                                       new ImageIcon("YellowButton.png"), 
                                       new ImageIcon("GreenButton.png"), 
                                       new ImageIcon("BlueButton.png"), 
                                       new ImageIcon("LightGrayButton.png"), 
                                       new ImageIcon("DarkGrayButton.png")}; 


    public ShinyButtonsApp(String title) { 
        super(title); // Set title of window 
        setDefaultCloseOperation(EXIT_ON_CLOSE); // allow window to close 
        setSize(578, 634); // Set size of window 
        setResizable(false);

        getContentPane().setLayout(null);   

        JLabel aLabel = new JLabel("Score: "); 
        aLabel.setLocation(10, 570); 
        aLabel.setSize(80,30); 
        getContentPane().add(aLabel);

        JTextField scoreField = new JTextField(); 
        scoreField.setText(Integer.toString(shiny.score));
        scoreField.setEditable(false);
        scoreField.setHorizontalAlignment(JTextField.RIGHT);
        scoreField.setLocation(60, 570); 
        scoreField.setSize(120,30);
        scoreField.setBackground(Color.WHITE); 
        getContentPane().add(scoreField);

        JButton newButton = new JButton("New Game");
        newButton.addActionListener(this);
        newButton.setLocation(348,570);
        newButton.setSize(110,30);
        getContentPane().add(newButton);

        JButton quitButton = new JButton("Quit");
        quitButton.setLocation(468,570);
        quitButton.setSize(80,30);
        getContentPane().add(quitButton);

        resetButtons2();
    } 

    public void actionPerformed(ActionEvent e) {
                shiny.score = 0;
                shiny.resetButtons();
                resetButtons2();
    }

    public void resetButtons2() {
        for (int r=0; r<ROWS; r++) {
            for (int c=0; c<ROWS; c++) {
                ImageIcon image1 = icons[(int)shiny.getButton(r,c)];
                JButton button = new JButton(image1);
                button.setLocation(10+(69*r),10+(69*c));
                button.setSize(69,69);
                button.setBorder(BorderFactory.createLineBorder(Color.GRAY,1));
                getContentPane().add(button);
            }
        }
    }

    public static void main(String[] args) { 
        ShinyButtonsApp frame;      
        frame = new ShinyButtonsApp("Shiny Buttons"); // Create window 
        frame.setVisible(true); // Show window      
    }   
}

和

import javax.swing.JFrame; 
import javax.swing.*;
import java.awt.event.*;
import javax.swing.JPanel;
import java.awt.Color;

public class ShinyButtons extends JPanel{ 
    public static byte RED = 0; 
    public static byte ORANGE = 1; 
    public static byte YELLOW = 2; 
    public static byte GREEN = 3; 
    public static byte BLUE = 4; 
    public static byte LIGHT_GRAY = 5; 
    public static byte DARK_GRAY = 6; 

    public static byte ROWS = 8; 

    public byte[][] buttonTable;

    public int score = 0; 

    public ShinyButtons() { 
        buttonTable = new byte[ROWS][ROWS]; 
        resetButtons(); 
    } 

    public void resetButtons() { 
        for (int r=0; r<ROWS; r++) 
            for (int c=0; c<ROWS; c++) 
                buttonTable[r][c] = (byte)(Math.random()*7); 
    } 

    public byte getButton(int r, int c) { return buttonTable[r][c]; } 

    public int getScore() { return score; }
} 

【问题讨论】:

  • 好的,问题我已经读了五遍了,请问您遇到了什么问题?
  • @MadProgrammer 抱歉,当我单击“新游戏”按钮时,8x8 网格不会更新为新的随机彩色图标。我相信它是,但它在程序启动时创建的第一个 8x8 网格下面分层
  • 不确定这是否与我们的问题有关,但this answer 使用布局管理器(您应该这样做)而不是设置位置和大小。看起来与您的情况相似,如果不一样,也许您会从中获得一些东西,即使它不能解决这个特定问题。
  • @peeskillet 我试试看,谢谢 :)

标签: java jbutton


【解决方案1】:

基于this answer 指出的内容(使用布局管理器而不是设置大小,正如您应该所做的那样),您可以通过循环组件来重置图像(JLabels ) 的JPanel 并更改它们的图标。

此特定示例使用JLabels 和MouseListeners,但它可以很容易地切换到JButtons 和ActionListeners

newGame.addActionListener(new ActionListener(){
    public void actionPerformed(ActionEvent e) {
         reset(iconPanel, icons);               <--- call reset method from below
         score = 0;
         scoreField.setText(String.valueOf(score));
    }
});
....

private void reset(JPanel panel, ImageIcon[] icons) {
    Component[] comps = panel.getComponents();
    Random random = new Random();
    for(Component c : comps) {
        if (c instanceof JLabel) {
            JLabel button = (JLabel)c;
            int index = random.nextInt(icons.length);
            button.setIcon(icons[index]);
        }
    }
}

这是完整的运行代码。您只需要替换图像路径即可。

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Random;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.border.LineBorder;

public class CircleImages {

    private int score = 0;
    private JTextField scoreField = new JTextField(10);

    public CircleImages() {
        scoreField.setEditable(false);

        final ImageIcon[] icons = createImageIcons();
        final JPanel iconPanel = createPanel(icons, 8);

        JPanel bottomLeftPanel = new JPanel(new FlowLayout(FlowLayout.LEADING));
        bottomLeftPanel.add(new JLabel("Score: "));
        bottomLeftPanel.add(scoreField);

        JPanel bottomRightPanel = new JPanel(new FlowLayout(FlowLayout.TRAILING));
        JButton newGame = new JButton("New Game");
        bottomRightPanel.add(newGame);
        JButton quit = new JButton("Quit");
        bottomRightPanel.add(quit);

        JPanel bottomPanel = new JPanel(new GridLayout(1, 2));
        bottomPanel.add(bottomLeftPanel);
        bottomPanel.add(bottomRightPanel);

        newGame.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e) {
                reset(iconPanel, icons);
                score = 0;
                scoreField.setText(String.valueOf(score));
            }
        });

        JFrame frame = new JFrame();
        frame.add(iconPanel);
        frame.add(bottomPanel, BorderLayout.PAGE_END);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    private void reset(JPanel panel, ImageIcon[] icons) {
        Component[] comps = panel.getComponents();
        Random random = new Random();
        for(Component c : comps) {
            if (c instanceof JLabel) {
                JLabel button = (JLabel)c;
                int index = random.nextInt(icons.length);
                button.setIcon(icons[index]);
            }
        }
    }

    private JPanel createPanel(ImageIcon[] icons, int gridSize) {
        Random random = new Random();
        JPanel panel = new JPanel(new GridLayout(gridSize, gridSize));
        for (int i = 0; i < gridSize * gridSize; i++) {
            int index = random.nextInt(icons.length);
            JLabel label = new JLabel(icons[index]);
            label.addMouseListener(new MouseAdapter(){
                public void mouseClicked(MouseEvent e) {
                    score += 1;
                    scoreField.setText(String.valueOf(score));
                }
            });
            label.setBorder(new LineBorder(Color.GRAY, 2));
            panel.add(label);
        }
        return panel;
    }

    private ImageIcon[] createImageIcons() {
        String[] files = {"blackcircle.png",
            "bluecircle.png",
            "greencircle.png",
            "greycircle.png",
            "orangecircle.png",
            "redcircle.png",
            "yellowcircle.png"
        };
        ImageIcon[] icons = new ImageIcon[files.length];
        for (int i = 0; i < files.length; i++) {
            icons[i] = new ImageIcon(getClass().getResource("/circles/" + files[i]));
        }
        return icons;
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new CircleImages();
            }
        });
    }
}

【讨论】:

    【解决方案2】:

    您正在resetButtons2() 中创建一组新按钮,并将它们放置在相同位置的现有按钮组的顶部(或更确切地说是其下方)。您应该创建一次按钮集,并且仅在重置时更新其图标。

    你应该做很多事情:

    • 使用适当的布局管理器,例如 GridLayout
    • 只创建一次 8x8 按钮网格,并在需要时替换它们的图标
    • 调用 invalidate/repaint 刷新内容窗格

    而JFrame你不需要getContentPane().add(...),你可以直接做add(...)

    【讨论】:

    • 我将如何更换它们?有一个列表?
    • 您可以使用数组,就像使用 icons 一样。
    【解决方案3】:

    两件事。

    首先,请确保先删除现有按钮。或者,您可以简单地更新按钮的状态。这需要您首先创建一个数组或List 按钮,然后您的重置方法将对其进行迭代并根据需要更新它们的属性。

    其次,使用适当的布局管理器。 null 布局是一个非常糟糕的主意。您不控制底层平台的字体指标,这将改变您的按钮在不同系统上的外观,使您的 UI 不那么动态

    【讨论】:

    • 如何“删除”现有按钮?
    • 鉴于您没有参考它们,很难。您可以使用getComponents 并在for-loop 中循环生成数组以查找JButton 的实例...但是List 会简单得多
    猜你喜欢
    • 1970-01-01
    • 2020-08-20
    • 1970-01-01
    • 2019-11-05
    • 2019-11-27
    • 1970-01-01
    • 2012-05-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多