简体   繁体   中英

Problem with refreshing GridLayout on Java Swing

i have a problem with refreshing the values of my gridlayout.

So, i have a JPanel in a JFrame and in that JPanel, once i entered two values(one for rows and one for columns) and then by clicking on validate, i get a GridLayout with the previous values of JButtons. So for exemple if I enter (2,2) i get a GridLayout of 4 JButtons and in each JButton i have an image.

So my problem here is, every time i wanna refresh the GridLayout by changing the values, it doesn't work, the GridLayout doesn't change, or if it change, the JButtons are inclickable. I feel like every time i click on Validate, a new GridLayout is created on my JPanel, but the first one is still there.

I will upload two pictures, one with the normal functioning (entering values first time), and the second with the bug (entering new values).

Thanks guys.

First values Second values

import java.awt.Font;
import java.awt.GridLayout;
import java.awt.Color;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.awt.event.ActionEvent;
import javax.swing.*;




    public class PagePrincipal extends JFrame implements ActionListener {

    JButton Valider;
    JTextField Columns;
    JTextField Rows;
    ArrayList<JButton> butt;
   
    
    public PagePrincipal(){
        
        getContentPane().setLayout(null); //this is not the panel that contains the GridLayout
    
        Columns = new JTextField();
        Columns.setBounds(219, 35, 197, 57);
        getContentPane().add(Columns);
        Columns.setColumns(10);
        
        Rows = new JTextField();
        Rows.setBounds(451, 35, 226, 57);
        getContentPane().add(Rows);
        Rows.setColumns(10);
        
        Valider = new JButton();
        Valider.setBackground(new Color(65, 179, 163));
        Valider.setForeground(Color.WHITE);
        Valider.setFont(new Font("Bookman Old Style", Font.BOLD, 20));
        Valider.setBounds(704, 15, 268, 81);
        Valider.setText("Validation");
        Valider.addActionListener(this);
        this.add(Valider);

        
        this.setResizable(true);
        this.setVisible(true);
        this.setExtendedState(JFrame.MAXIMIZED_BOTH); 
        
        
        
        
        
    }
    

    @Override    
   
    
        
    public void actionPerformed(ActionEvent event) {

     if (event.getSource() == Valider) {   
        int NbRows= Integer.parseInt(Rows.getText());
        int NbColumns=Integer.parseInt(Columns.getText());
        JButton button[] = new JButton[NbRows*NbColumns];
        butt = new ArrayList<>();
       
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        JPanel botPanel = new JPanel(); //this is the panel that contains the GridLayout
        botPanel.setBounds(100, 200, 1000, 400);
        this.add(botPanel);
        
        botPanel.setLayout(new GridLayout(NbRows,NbColumns));
        
        for (int i=0; i<NbRows*NbColumns; i++){
                button[i]=new JButton();
                botPanel.add(button[i]);
                butt.add(button[i]);    
        }
        this.setVisible(true);
        
    }
     
        
}
}

Again, avoid null layouts if at all possible, since they force you to create rigid, inflexible, hard to maintain GUI's that might work on one platform only. Instead, nest JPanels, each using its own layout to help create GUI's that look good, are flexible, extendable and that work.

Also, when changing components held within a container, call revalidate() and repaint() on the container after making the changes. For example, the following GUI:

在此处输入图像描述

在此处输入图像描述

Is created with the following code:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.util.ArrayList;
import java.util.List;

import javax.swing.*;

public class PagePrincipal2 extends JPanel {
    public static final int MAX_ROWS = 40;
    public static final int MAX_COLS = 12;
    private JButton validatorButton = new JButton("Validate");
    private JSpinner columnsSpinner = new JSpinner(new SpinnerNumberModel(2, 1, MAX_COLS, 1));
    private JSpinner rowsSpinner = new JSpinner(new SpinnerNumberModel(2, 1, MAX_ROWS, 1));
    private List<JButton> buttonsList = new ArrayList<>();
    private JPanel gridPanel = new JPanel();
    
    public PagePrincipal2() {
        JPanel topPanel = new JPanel();
        topPanel.add(new JLabel("Columns:"));
        topPanel.add(columnsSpinner);
        topPanel.add(Box.createHorizontalStrut(10));
        topPanel.add(new JLabel("Rows:"));
        topPanel.add(rowsSpinner);
        topPanel.add(Box.createHorizontalStrut(10));
        topPanel.add(validatorButton);
        
        JScrollPane scrollPane = new JScrollPane(gridPanel);
        
        int gridWidth = 1000;
        int gridHeight = 600;
        scrollPane.setPreferredSize(new Dimension(gridWidth, gridHeight));
        
        setLayout(new BorderLayout());
        add(topPanel, BorderLayout.PAGE_START);
        add(scrollPane, BorderLayout.CENTER);
        
        validatorButton.addActionListener(e -> validateGrid());
    }
    
    private void validateGrid() {
        int nbRows = (int) rowsSpinner.getValue();
        int nbColumns = (int) columnsSpinner.getValue();
        gridPanel.removeAll();
        buttonsList.clear();
        gridPanel.setLayout(new GridLayout(nbRows, nbColumns));
        for (int i = 0; i < nbRows * nbColumns; i++) {
            int column = i % nbColumns;
            int row = i / nbColumns;
            String text = String.format("[%02d, %02d]", column, row);
            JButton button = new JButton(text);
            button.addActionListener(e -> gridButtonAction(column, row));
            buttonsList.add(button);
            gridPanel.add(button);
        }
        gridPanel.revalidate();
        gridPanel.repaint();
    }
    
    private void gridButtonAction(int column, int row) {
        String message = String.format("Button pressed: [%02d, %02d]", column, row);
        String title = "Grid Button Press";
        int type = JOptionPane.INFORMATION_MESSAGE;
        JOptionPane.showMessageDialog(this, message, title, type);
    }
    
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            PagePrincipal2 mainPanel = new PagePrincipal2();

            JFrame frame = new JFrame("GUI");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.add(mainPanel);
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        });
    }
}


Note that the gridPanel, the one holding the buttons, is placed into a JScrollPane:

JScrollPane scrollPane = new JScrollPane(gridPanel);

Note that the main JPanel that holds everything is given a BorderLayout, and then 2 components are added, a topPanel JPanel that holds labels, buttons and fields for data input, added at the BorderLayout.PAGE_START , the top position, and the JScrollPane is added to the main JPanel at the BorderLayout.CENTER position:

setLayout(new BorderLayout());
add(topPanel, BorderLayout.PAGE_START);
add(scrollPane, BorderLayout.CENTER);

When the old buttons are removed from the gridPanel, and then new buttons are added, I will call revalidate() and repaint() on the gridPanel, the first method to get the layout managers to layout the new components, and the second method call to remove any dirty pixels that may be present:

private void validateGrid() {
    int nbRows = (int) rowsSpinner.getValue();
    int nbColumns = (int) columnsSpinner.getValue();
    gridPanel.removeAll();
    buttonsList.clear();
    gridPanel.setLayout(new GridLayout(nbRows, nbColumns));
    for (int i = 0; i < nbRows * nbColumns; i++) {
        int column = i % nbColumns;
        int row = i / nbColumns;
        String text = String.format("[%02d, %02d]", column, row);
        JButton button = new JButton(text);
        button.addActionListener(e -> gridButtonAction(column, row));
        buttonsList.add(button);
        gridPanel.add(button);
    }
    gridPanel.revalidate();
    gridPanel.repaint();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM