Dynamically remove Component from JPanel - java

I am adding and deleting components dynamically in a JPanel.
Adding and deleting functionality works fine but when I delete the component it deletes the last component rather than the component to be deleted.
How can I solve this issue?

Interestingly enough I am coming across the same issue and I am surprised people are upvoting the other answer, as he is clearly asking about dynamically created Components, not components already created under a variable name which is obtainable, instead of anonymously created objects.
The answer is pretty simple. Use
getComponents() to iterate through an array of components added to the JPanel. Find the kind of component you want to remove, using instanceof for example. In my example, I remove any JCheckBoxes added to my JPanel.
Make sure to revalidate and repaint your panel, otherwise changes will not appear
Component is from java.awt.Component.
//Get the components in the panel
Component[] componentList = panelName.getComponents();
//Loop through the components
for(Component c : componentList){
//Find the components you want to remove
if(c instanceof JCheckBox){
//Remove it
clientPanel.remove(c);
}
}
//IMPORTANT
panelName.revalidate();
panelName.repaint();

Using the method Container.remove(Component), you can remove any component from the container. For example:
JPanel j = new JPanel();
JButton btn1 = new JButton();
JButton btn2 = new JButton();
j.add(btn1);
j.add(btn2);
j.remove(btn1);

Related

Creating Buttons during runtime in Java

I want to add a number of Buttons to my Java application based on an array. Say if there are 10 objects in an array, I want to create 10 buttons. If I delete 2 objects in the array the buttons should also get deleted. I thought about 3 things to go on about this problem.
A for loop - but I think the buttons would just exist inside the loop and also I would not know how to name the buttons (the variable name not the label).
A Thread
A seperate class
I have no idea how I would do that though.
Can I actually name variables through loops?
Are any of my ideas practicable?
If you add a button to a JPanel it will survive outside the for loop, so don't worry about it. Create a JPanel just for your buttons and keep track of those you add using an ArrayList<JButton>, so you'll be able to delete them as you need. To delete them from the panel, refer to this answer. Remember to repaint (=refresh) the JPanel.
JButton button1 = ...;
// Add it to the JPanel
// https://stackoverflow.com/questions/37635561/how-to-add-components-into-a-jpanel
ArrayList<JButton> buttons = new ArrayList<>();
buttons.add(button1);
// Other stuff...
// It's time to get rid of the button
JButton theButtonIWantToRemove = buttons.get(0);
buttons.remove(0);
//Get the components in the panel
Component[] componentList = panel.getComponents();
//Loop through the components
for(Component c : componentList){
//Find the components you want to remove
if(c == theButtonIWantToRemove){
//Remove it
panel.remove(c);
}
}
//IMPORTANT
panel.revalidate();
panel.repaint();

Refreshing JLabel - Java

I have some problems with JLabels and Frames..
I have the following code:
list.addListSelectionListener(
new ListSelectionListener() {
#Override
public void valueChanged(ListSelectionEvent e) {
//System.out.println(e.getFirstIndex());
String selectedFile = list.getSelectedValue().toString();
System.out.println("Selected file " + selectedFile);
JLabel label;
ImageIcon icon = new ImageIcon("C:\\Users\\danie\\Pictures\\" + selectedFile);
// frame.setSize(1047, 680);
label = new JLabel(icon);
//label.setSize(100,100);
frame.getContentPane().add(label, BorderLayout.CENTER);
frame.revalidate();
frame.repaint();
}
});
I want to refresh the label in the center of the borderlayout if a item in a JList is selected. But with this code, the old image is futher displayed and the new image is only drawed behind the existing image.
Could anyone help me? :)
First you are creating a new JLabel instance instead of working on the existing one. What you actually want to do is:
labe.setIcon(icon);
This will automatically refresh the element.
Suggestions:
Don't create a new JLabel, give it an ImageIcon and expect the existing JLabel to change. The two JLabels, the original one and the one created here, are two completely different objects, and changing the state of one (the icon it's displaying) will not magically change the state of the other.
Do make sure that the original JLabel has an instance variable in the class (not in your listener class), a field, refer to it, and then in your listener code, change the icon displayed in that JLabel by calling its setIcon(...) method
No need to call revalidate() or repaint() here as this should be done if you change components held within a container, such as if you removed the original JLabel from the JFrame's contentPane and swapped in a new one. Note that I do not recommend that you do this as it is over-complicating what should be a simple thing -- swapping icons.
To simplify things, I suggest that you read all your images in at program startup, create ImageIcons at that time, and then put them into an array or collection (such as an ArrayList<Icon> or a HashMap<String, Icon>), and then in your listener code, extract the correct icon, and put it into the existing JLabel.
You are not using the same JLabel it seems. You should alter the label you already have, not create a new one.

Does removeAll() also remove the layout manager on a JPanel?

Simple question that I could not find a simple answer to:
I have a JPanel filled with different components. If i do the following
JPanel panel = new JPanel();
//Code to add componenets to the panel.
panel.setLayout(new MigLayout("wrap 5");
panel.removeAll();
Does this also remove the layout manager? Or are just the componenets removed?
Best regards, Goatcat
Docs saying
Removes all the components from this container. This method also notifies the layout manager to remove the components from this container's layout via the removeLayoutComponent method.
This method changes layout-related information, and therefore, invalidates the component hierarchy. If the container has already been displayed, the hierarchy must be validated thereafter in order to reflect the changes.

not displaying all the buttons

I have an array with buttons:
JButton[] commandButtons = {
new JButton("Add Chair"),
new JButton("Add Table"),
new JButton("Add Desk"),
new JButton("Clear All"),
new JButton("Total Price"),
new JButton("Save"),
new JButton("Load"),
new JButton("Summary")
};
I want to put them all in the panel, but it is displaying only the last button.
so if anyone know how to fix it or have an advice it would be great.
Also I am not sure how to do the for loop as a for each.
for(int i=0; i<commandButtons.length; i++)
{
westPanel.add(commandButtons[i]);
commandButtons[i].addActionListener(this);
}
Set a FlowLayout manager on the westPanel JPanel and they will all show up.
I believe that you have not set layout, so the default one is BorderLayout. When you are adding elements to this layout without telling the parameter (where to put the element) it is added by default to the center. But there can be only one element in the center, so you see only the last button.
The fast fix is define flow layout:
pannel.setLayout(new FlowLayout());
Do it before adding the buttons. Now you will see all buttons. If you do not see enlarge the window.
Now, if the layout is not what you really want, read about layouts and decide which one (or combination of them) do you need.
Yeah it depends on the layout manager. If you want no layout manager you have to set the location and size yourself, otherwise they'll all be 0,0.
setLayout(null); //gives no layout manager
Always try to use a layout manager though.

Adding to JPanel in application

When a particular button is clicked I want another set of buttons to be added to the Panel, however at the moment when I do this, I can add them as many times as I want, I need this to be only possible once. Would the best way to do this be set the adding of the buttons and fields in a while loop?
if(e.getSource() == selectScript){
while(scriptB < 1 ){
imageID = new JTextField("INT");
imageDescription = new JTextField("imgDescription");
imagePath = new JTextField("imagePath");
manageImageTab.add(imageID);
manageImageTab.add(imageDescription);
manageImageTab.add(imagePath);
insertImage = new JButton("Add an Image");
insertImage.addActionListener(new dbaccess());
manageImageTab.add(insertImage);
manageImageTab.revalidate();
validate();
scriptB++;
}
}
Perhaps rather than add and remove the JButtons, you could add the buttons once at the code start, just don't make them visible until you need them, or perhaps better place them all on a JPanel that is not visible and then made visible when desired. Just don't forget to call revalidate() and repaint() on the container that holds the buttons and their panel.
If I understand you correctly, I would use a flag alreadyAdded that starts out false, gets set to true after the controls have been added, then don't allow it to add after that.

Categories

Resources