Diamundo Diamundo - 29 days ago 14
Java Question

How to remove (nuke) a javax.swing.box entirely?

I have a JPanel that currently has a swing.box in it, which in itself houses an arbitrary number of JButtons.

Now one of the JButtons has the ability to create a new JButton, which goes fine.
However, after creating said new button, I want the button to go in the list at the right position (alphabetically sorted) which also goes fine. I am however sure that it is never the last button as I add some standard buttons at the end.

Now the problem is that I cannot nuke the box that has said buttons in them after which I rebuild the box.

(also see https://github.com/Diamundo/PhotoSelectorSys/ButtonPanel.java and specifically at line 42, start of function initButtons() )

(problem I also have, is that I add buttons with a preferred size which does take effect if I put them straight in the panel, but not if I put them in the box... so if you have a solution which lets me delete all buttons instead of the box that's also very welcome :D )

package photoselectorsys;

import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.File;
import java.util.ArrayList;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;

public class ButtonPanel extends JPanel {
private AppFrame listener;
private String path;
private Box box;

public ButtonPanel(int width, int height){
setPreferredSize(new Dimension(width, height));
setVisible(true);
box = Box.createVerticalBox();
}

public void setPath(String path){
this.path = path;
initButtons();
// pushButtons();
this.revalidate();
}

/*public void pushButtons() {
for(JButton jb : buttons) { //buttons was an ArrayList of button names. Is now the box.
this.remove(jb); //remove the button from the panel.
}
for(JButton jb : buttons) { //buttons should be changed to the box
add(jb);
}
}*/

public void initButtons(){
/* if(box.hasButtons()) {
box.nuke();
box = new Box(..);
}
*/

JButton jb;
File directory = new File(path);
File[] listFiles = directory.listFiles();
ArrayList<String> btns = new ArrayList<>();
for (File file : listFiles) {
if (file.isDirectory()) {
btns.add(file.getName());
}
}
btns.add("Add a new Button");
btns.add("Rotate CW");
btns.add("Rotate CCW");
btns.add("Rotate 180*");

System.out.println("buttons " + btns.size());
if(btns.size() > 4) { //if there's at least one folder, size > 4. Else add one big button or ask to create subfolder
for(String btn : btns) {
jb = new JButton(btn);
jb.setFont(new Font("Arial", Font.PLAIN, 20));
jb.setPreferredSize(new Dimension(this.getWidth()-20, 40));
jb.setVisible(true);

jb.addMouseListener(new MouseListener() {
@Override
public void mouseClicked(MouseEvent arg0) {
onButtonPress((JButton) arg0.getSource());
}
@Override
public void mouseEntered(MouseEvent e) { /* unused */ }
@Override
public void mouseExited(MouseEvent e) { /* unused */ }
@Override
public void mousePressed(MouseEvent e) { /* unused */ }
@Override
public void mouseReleased(MouseEvent e) { /* unused */ }
});
/*box.*/add(jb);
}
} else {
// do add folder magic from the start.
jb = new JButton("Add a new Button");
jb.setFont(new Font("Arial", Font.PLAIN, 20));
jb.setPreferredSize(new Dimension(this.getWidth()-20, this.getHeight()-30));
jb.setSize(new Dimension(this.getWidth()-20, this.getHeight()));
jb.setVisible(true);

jb.addMouseListener(new MouseListener() {
@Override
public void mouseClicked(MouseEvent arg0) {
onButtonPress((JButton) arg0.getSource());
}
@Override
public void mouseEntered(MouseEvent e) { /* unused */ }
@Override
public void mouseExited(MouseEvent e) { /* unused */ }
@Override
public void mousePressed(MouseEvent e) { /* unused */ }
@Override
public void mouseReleased(MouseEvent e) { /* unused */ }
});
/*box.*/add(jb);
}
// add(box);
}

public void onButtonPress(JButton jb){
// not interesting for this question. See github for function.
}

public void addListener(AppFrame listener) {
this.listener = listener;
}
}

Answer

To change the buttons in your box you don't have to create a new box but rather do one of the following 2 things:

a) add the button at the correct position using box.add( button, index )
b) remove all buttons using box.removeAll() and (re)add the buttons as needed

I'd prefer variant a) but there might be cases where rebuilding the box contents from scratch might be the better way.

Normally that alone should be sufficient since the component should realize it's layout is invalid and needs to be recalculated. If this doesn't happen or you need to revalidate the parent container as well for some reason call the invalidate() method on the relevant component.

Comments