All I can think is that there's something fundamentally wrong with how I programmed my GUIs. I have a program that initially displays a GUI which has 6 buttons. Each of these buttons, when clicked, displays a GUI. One of these GUIs in particular is a JTable of "Teams". Each of these Teams has "Games played". You can click on the Team and click a button, "Display Games", to pop open another GUI that shows what games the team has played. When the user clicks "display games", anywhere from 1-7 copies of the SAME GUI are being displayed. In addition, when the user 'deletes' the games from the GUI (if he/she entered a game by accident) the number of times the program attempts to delete the game = the number of copies of the GUI that popped up. This happens despite the user only clicking "delete game" once. Everything in my program is scheduled on the Event Dispatch Thread. Java Sun says that the EDT for displaying GUIs and Worker Threads (for more time intensive tasks) are recommended.

I have spent over 75 hours building this GUI, all the background code/code that runs when the user makes entries is what I want it to be. I seem to be having problems with my GUIs though, I'm not sure exactly what the problems are. One of my users has complained that her Teams were completely lost, despite her not telling the GUI to 'delete' any of them. This seems like a memory consistency error to me, but I'm not sure. I've posted all of my code to the web at

http://www.esnips.com/web/ProgramForums


Its a lot of code, but if anyone would care to run the program (the .jar is on the second page) then take a look that would be awesome.

Recommended Answers

All 27 Replies

generally, we help solving problems that occur in code people post here.
we give hints about which way to go, without (in the most cases) to run the code.

since there is a GUI being displayed several times, my guess is that the problem lies in the code of the gui itself, or the place where it is called.

paste those codes here, preferably using Code tags, it'll be a lot easier for us to figure out the problem in your code.

I'm 99.9% sure this isn't the case, having checked myself numerous times, but I will paste the code anyway.

The actionPerformed method where the GUI is called:

public void actionPerformed(ActionEvent ae){
	  Object source = (JButton)ae.getSource();
	  if (source == viewStats){
		  int row = -1;
		  int[] allrows = table.getSelectedRows();
		  if (allrows.length != 0)
		  row = allrows[0];
		  
		  if (allrows.length == 0 || row == -1 || row < 0 || row > Matchups.allTeams.size()){
			  return;
		  }
		  else{
			  String name = (String)table.getValueAt(row, 0);
			  for (int i = 0; i < Matchups.allTeams.size(); i++){
				  if (Matchups.allTeams.get(i).name.equals(name)){
					  DisplayTeamsPlayed.setTeam(Matchups.allTeams.get(i));
					  DisplayTeamsPlayed.main(new String[0]); 
				  return;
				  }
			  }
		  }
	  }

The line where it says DisplayTeamsPlayed.setTeam passes in a 'Team' as an argument, and sets the static variable Team in DisplayTeamsPlayed to the argument that was passed in. When DisplayTeamsPlayed.main() is called, it creates a JTable which consists of a list of all the 'Games' (another object) that the Team (the static variable I described earlier) has played. In main, a new Runnable() is created and then createAndShowGUI, shown below, is called.

public static void createAndShowGUI(){
		frame = new JFrame("Matches the team \"" + team.name + "\" has played:");
		frame.setSize(550, 600);
		frame.setLocation(200, 100);
		frame.setUndecorated(true);
		frame.getRootPane().setWindowDecorationStyle(JRootPane.PLAIN_DIALOG);
		frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
      
		//Add contents to the window.
		frame.add(new DisplayTeamsPlayed(team));
   
		//Display the window.
		frame.setVisible(true);
	}

The DisplayTeamsPlayed constructor that is called from createAndShowGUI:

public DisplayTeamsPlayed(Team getStats){
	  super();
	setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
	print.addActionListener(this);
	deleteGame.addActionListener(this);
    int index = Matchups.allTeams.indexOf(getStats);
    int rows = Matchups.allTeams.get(index).gamesPlayed.size(); 
    int columns = 6;
    String data[][] = new String[rows][columns];
    String col[] = {"Team Played", "Your score", "Their Score", "Game Spread", "Point Spread", "Week Number"};
    
    for (int i = 0; i < Matchups.allTeams.get(index).gamesPlayed.size(); i++){
    	data[i][0] = Matchups.allTeams.get(index).gamesPlayed.get(i).theirTeamName;
    	data[i][1] = Integer.toString(Matchups.allTeams.get(index).gamesPlayed.get(i).ourScore);
    	data[i][2] = Integer.toString(Matchups.allTeams.get(index).gamesPlayed.get(i).theirScore);
    	data[i][3] = Integer.toString(Matchups.allTeams.get(index).gamesPlayed.get(i).gameSpread);
    	data[i][4] = Integer.toString(calculatePointspread(Matchups.allTeams.get(index),i));
    	data[i][5] = Integer.toString(Matchups.allTeams.get(index).gamesPlayed.get(i).weekID);
    }
    
    table = new JTable(data,col);
    table.setRowSelectionAllowed(true);
    JTableHeader header = table.getTableHeader();
    header.setBackground(Color.yellow);
    JScrollPane pane = new JScrollPane(table);
    table.setRowHeight(20);
    print.setPreferredSize(new Dimension(100, 50));
    deleteGame.setPreferredSize(new Dimension(100,50));
    JPanel buttons = new JPanel();
    buttons.setLayout(new BoxLayout(buttons, BoxLayout.X_AXIS));
    buttons.add(print);
    buttons.add(deleteGame);
    JPanel panePanel = new JPanel();
    panePanel.setLayout(new BoxLayout(panePanel, BoxLayout.Y_AXIS));
    panePanel.add(pane);
    buttons.setPreferredSize(new Dimension(200, 100));
    add(panePanel, BorderLayout.CENTER);
    add(buttons);
  }

I have no problem with posting more code, but I don't see how anyone could possibly sift through all of it. Over the past 6 months I have pretty much lived on Java Sun's tutorials, so I've been trying to follow their examples as closely as possible. I thought that the other problem my user experienced with her Teams disappearing might be some kind of memory inconsistency error, but I looked at all of my code for a few more hours, THEN I checked to make sure everything was scheduled on the Event Dispatch Thread, and it all is. Is this practice of having everything on the EDT wrong? Because Java Sun says the only problem that can occur with that is 'freezing' or non-responsiveness of the GUI, but I have not experienced that at all, so I haven't created any worker threads.

Also, one more question: how should I go about updating my JTable after a Game is deleted? I was using frame.dispose and then simply re-creating the entire window, but this seems to cause problems?


Also, if the problem you were describing above was really the problem, one would expect that there would be consistency: such as the GUI always displaying a certain number of times. There is no consistency - sometimes it displays once, sometimes twice, sometimes 5 times.

you should check the place where createAndShowGUI() is called, and whether there is something that influences the number of time it's called.

could be the length of an array, could be an element of an array that you put in an integer, but it appears that, instead of, for instance you press a button to show the gui, you somehow send a variable, and based on that variable, your application calls the createAndShowGUI() n times.

there are ways to keep your code the way it is, just by making a couple of fixes in your GUI, but the best for your program is to make it so that that method is only called once

Hmm

Actually, I just found a relationship between the number of times that window is displayed & my code. The amount of times that the window which displays all the teams is closed and re-opened, is the number of times that a Team's games are displayed when I click show game stats.

WTF

Could this be because I'm using the wrong ways of updating the contents of the window? Because when the window is closed, its DISPOSE_ON_CLOSE. So when its reopened, how do I update the contents so that the new Teams that I want are displayed... ? So far I was doing it by simply re-calling createAndShowGUI, but this must be the wrong way to do it

I doubt that's the problem..
if it was (and if I read your explanation correctly) the GUI is shown several times while the data is not being changed, so without changes in the data, there's no reason to update it into the frame, so there's no update causing the several pop-ups from the JFrame

what exactly do you mean by "So when its reopened, how do I update the contents so that the new Teams that I want are displayed... ?"

I'm a bit tired, so maybe I'm not seeing the obvious, but my first guesses would be:
either you pass the data that you want to display as an argument to the JFrame you're going to show, or you get the data from within the class holding the JFrame, but I don't think you're using a database or data that's stored into a seperate file, so I believe the passing as argument is the way to think

I'm saying that whenever the user clicks on a certain JButton, I'm displaying a list of Teams in a GUI, lets call it firstWindow. So once the user clicks 'X' the GUI disappears. But when they go back into it by clicking the JButton again, it reappears again. Each time it appears, it is doing so through createAndShowGUI. On the GUI I have just mentioned, there is another JButton to show the team's games. When THAT Jbutton is clicked, the number of windows it displays is EQUAL to the number of times I opened and closed firstWindow. So it would seem that my method of 'updating' the GUI by closing the window, then re-displaying it, is not an acceptable way to do things.

I'm saying that whenever the user clicks on a certain JButton, I'm displaying a list of Teams in a GUI, lets call it firstWindow. So once the user clicks 'X' the GUI disappears. But when they go back into it by clicking the JButton again, it reappears again.

seems logical, or your app would stop to function after the first choice made

When THAT Jbutton is clicked, the number of windows it displays is EQUAL to the number of times I opened and closed firstWindow.

I figure this is more a problem with the calling of createAndShowGUI than with the GUI itself. does that call to createAndShowGUI is placed within a loop of some kind?

No, there is no loop. Since a call to pack() re-shows something thats been hidden or disposed, what must be happening is that I'm ending up w/ multiple copies of the same window on top of each other.


So basically I have to either switch from a static variable to a normal one, or simply stop re-creating the entire GUI and just update the information thats currently in it.

No, there is no loop. Since a call to pack() re-shows something thats been hidden or disposed, what must be happening is that I'm ending up w/ multiple copies of the same window on top of each other.

have to say, made quite a lot Swing-apps during college, used Dispose() all the time, but never had the problem of one frame popping up more than once caused by one click on the button.

what's disposed, is disposed, if I'm not mistaken, that's just gone. what's hidden, isn't shown, unless you access that instance of the object and give it the order "visible(true)", which I doubt you're doing.

pack(), as far as I know, only applies to that instance of the object on which you apply it, not on every instance of it.

There is certainly no reason to dispose of a frame and re-display it to update data, and main() should only be called once in a program as an entry point to minimally set up the object(s) your program needs to run.

To update data in a table, update the table model that is bound to that JTable. If you're using a DefaultTableModel, then you can simply call removeRow(int) and it will remove the row entry and fire the appropriate notification event. If you are using your own table model implementation then you will need to handle that yourself.

So if my application has numerous GUIs, but only one is shown when the program starts, how does that figure into what you just said?

(which of the following things should I be doing)?

1. When the application is first launched, I set up all GUIs that can possibly be used at any point in the program, but I set them all to setVisible(false) except the one that I want to show up initially.
2. When the application is first launched, I only set up the first GUI. Then, if I open a different GUI, it is set up using that GUI's main method. But after it is set up initially, it will never be set up again & will only be hidden then redisplayed (possibly with information changed).


To me, the second one makes more sense, since I don't see any point in having all of the GUIs set up if the user isn't going to use them. However, if you recommend the other way, that is what I will do. The second way I described might be implemented something like this (where frame is a static variable):

public static void main(String[] args){

if (frame != null){
// code to update whatever is in the GUI
frame.setVisible();
} else if(frame == null){
// code to set up the GUI using invokeLater(), new Runnable()
}

}

Anyway, many thanks to you guys, you've both been very helpful.

you can have twenty GUI's shown together, but you should have just one instance of every JFrame (max) shown at the same time
so, which one should you do? neither..
don't use visible(false);
of this.hide();

use the dispose() method. it should end the existence of the instance (I can be wrong, but I don't think so)
but you're right.. the first option is a big no-no, unless you have a lot of RAM that you're sure you will never use and just want to use even if just once.
using that logic would mean to use resources you don't need, to perform tasks that don't need performing

The Java API says that the pack() method causes something that is dispose()'d to reappear.

Instead, I'm just going to hide the window when the user clicks out of it, then set it to visible when they click back into it. Each GUI class will have a method that gets called each time the user wants to view that GUI. This method will update the contents of the GUI before displaying it. While this might take more time to do (updating everything, every time) than simply updating something when the user makes changes... it doesn't matter to me because this application takes very little time to run anyway.

I'm just asking if this way of doing things will lead to funny results.

Also, one last question for now: Any code that interacts with the GUIs or is part of the GUIs apparently needs to be run on the event dispatch thread or a worker thread. How do I know if my code is running on the EDT other than using a method to determine it (I know there's a method that will tell me this)? Are any methods invoked from actionPerformed or other event handling methods guaranteed to be run on the EDT?

if you just use the hide and setVisible methods: you'l just do that, hide and show, the data showed by the form won't be updated

I realize that... thats why I'm saying that when the user opens the GUI, I will update the information first. I haven't quite figured out how I'm going to update the information, but I'm sure there are adequate means to do so. Ezzaral gave me one way to do it with a JTable - I guess there are also ways to do it with JComboBoxes etc


If this isn't how I should be doing it, then how should I be updating the changes?

just like we suggested earlier, update that on which you base your JTables, JTextFields, Jlabels, ...
since you want to update the info first when you open the gui... don't see the logic behind that, since when you just open it, you should only pass the current data.
on the other hand, if you would get it out of a DB, it seems normal, to get the data, but updating might sound wrong..

the point is, where do you get the data from.. if it's from another JFrame, there isn't much you can do to "update" it while running, unless you go and access the setters of the JFrame by the calling class/JFrame. if you get your data from a DB or input file, use a thread to detect if the data got changed and to check if the data has to be updated

Data is initially gotten out of a file by the first GUI. When the program is closed, it is written back into the file by the same GUI. The user can enter data that manipulates the data originally gotten out of the file. In addition, the user can enter data that will be added to the file when the program closes. So yes, it is necessary to check for 'new' data every time some of my GUIs are opened, since the user could've entered new data or changed the data we currently have. So I don't see why I can't do what I described above and update the data every time the user opens a GUI. I'm sorry if I'm being confusing.

what I asked was: do you have to check every time you create a new instance of the gui, or even while the gui exists.
just make sure that every time you create a gui and pass data as argument, the data you pass as argument is very up to date :)

Only when a new instance is created. Or, rather, when the current instance is 'un-hidden'. But it doesn't really matter since all of my GUIs will simply supply an error message if the user enters something inconsistent with whats in the ArrayList that they all use. So I'm pretty sure that the worst that can happen is that there is incorrect information being displayed on screen. Of course, I am going to try to prevent that. But at this point, my main concern is making sure the data that is IN the ArrayList remains intact.

take a look at thisl and check out what it has to say about dispose(). it goes a bit further then just to hide the screen.

if the user inserts wrong data, maybe that should be shown, but preferably during the input process, not while showing the data. Of course it's allowed to put as output "invalid data entered" or something like that, but the best is to catch/correct errors like that while entering the data

Man, I'm so confused still. I can't even figure out a way to have multiple GUIs interact when each class extends JPanel & has a static JFrame variable. I've been trying a variety of different things but nothing really works. If anyone has any source code of multi-GUI projects that you have built or someone else has built, where each GUI is able to 'update' itself based on changes made to Objects (could be in a list or otherwise) through another GUI, please provide it.

I don't have any trouble building a stand-alone GUI like the ones in the Java Sun tutorials. Ugh.

Man, I'm so confused still. I can't even figure out a way to have multiple GUIs interact when each class extends JPanel & has a static JFrame variable.

if you want to interact between different JFrame's, there is always the option to pass on the parent GUI as an argument while creating a new one.

for instance:

//this is in the mainGUI, where you can open both a InputData frame and a ShowData frame
InputData inputScreen = new InputData(this);
...
ShowData showScreen = new ShowData();

now, let's say you've got the ShowData screen open. you can't change anything to the data there, but you can do so in InputData. and you want any changes you make, to be immediately showed in the active ShowData screen.

now, in the InputData constructor, you add an argument with type MainGui

MainGui parentObject =  null;

public InputData(MainGui parent){
parentObject = parent;
}

now, if you make any changes in InputData, you can send it through the MainGui to an open instance of ShowData

//in InputData, in the method that is called if you push the button that accepts changes 
//the data

...
parentObject.changeNameInData(newName);

and in MainGui:

public void changeNameInData(String newName){
  try{
    showData.setNameLabel(newName);
 }
  catch(Exception ex){
     // jup, it'll fail if there's no showData
  }
}

Ahh. I see. Thank you, I will do that. It'll be a bit harder considering I have 5 or 6 GUIs but I get the idea, I think.

Yeah, I figured as much after your (Ezzaral) and Stul made your posts. I got the GUI working already in light of what you guys told me. Thanks for the articles though, I'll def. check those out. And thanks for all the help.

commented: Wow. An actual thank you. +9
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.