0Calories 0Calories - 5 months ago 8
Java Question

JPanel not visible

I've been having a problem with my program that has been driving me crazy and I cannot understand why this is happening. I have a GUI that when the "Add" button is pressed, a new system listing appears (Which is a class called SystemPanel that extends JPanel and cotains system details, which is created and then put into the Frame's main panel.)

To put it shortly, when I try to add a new SystemPanel, it does not appear for whatever reason. I have code using JSch that connects to the system and verifies whether its processes are online or not, but the line of code that does this is after the creation of the SystemPanel. It is only after the code for testing the processes of the system are executed that the SystemPanel becomes visible, and I can't understand why this is the case. Here is the code for adding a new SystemPanel:

public void actionPerformed(ActionEvent e) {
//If the "Add" button is pressed
if (e.getActionCommand() == "Add") {

PopupWindow popup = new PopupWindow(this);
popup.setVisible(true);
String[] results = popup.getResults();
if (results[0] != null && results[1] != null && results[2] != null && results[3] != null && results[4] != null) {

SystemPanel newSystem = new SystemPanel(this, results[0], results[1], results[2], results[3], results[4]);

systemsPanel.add(newSystem);
revalidate();
systemsList.add(newSystem);
System.out.println("Did the stuff");

boolean[] status = SystemChecker.checkOnline(results[0], results[1], results[2], results[3]);
}
}
}


The PopupWindow is a custom JDialog that allows the user to enter the required information which is returned in a String array and is used to create a new SystemPanel. The checkOnline function grabs the user's inputs and uses them to connect to the system and determine whether the processes are working or not, and returns the results into a boolean array, true for working, false for not.

What's even weirder is that I have another part of my program that reads from an .ini file to obtain existing systems and then creates SystemPanels based on the data that it reads. Through this method, the SystemPanels are added the way I want and work perfectly for some reason, even though the code for adding the panels is hardly any different. Code:

for (int i = 0; i < systems.size(); i++) {
SystemPanel newSystem = new SystemPanel(this, systems.get(i)[0], systems.get(i)[1], systems.get(i)[2], systems.get(i)[3], systems.get(i)[4]);
systemsPanel.add(newSystem);
revalidate();
systemsList.add(newSystem);
}

for (int i = 0; i < lineNum; i++) {
boolean[] status = SystemChecker.checkOnline(systems.get(i)[0], systems.get(i)[1], systems.get(i)[2], systems.get(i)[3]);
systemsList.get(i).updateIcons(status);
}


This code grabs the details from the file and then makes the SystemPanels based on those details. Here, all of the SystemPanels are added and show up before the connection is tested, which is what I want to happen when I add one normally.

Why is it that the SystemPanel doesn't appear until the connection is tested, even though the code for displaying the SystemPanel is executed before the connection test? Any help would be greatly appreciated, thanks.

Answer

Try it of the current event queue handling, on which actionPerformed is done.

public void actionPerformed(ActionEvent e) {
    EventQueue.invokeLater(() -> { ... your code here ... });
}

Also you cannot add the same component to two parents, every component object has a single parent (container).

(Java 8 notation)