So, this is really annoying, and an incredible magic show at the same time. So I have a global string called setAnagram. I'm making a GUI with Eclipse, and so what I'm trying to do, is have the user click a button, it start another thread, and on that thread it gets the value of a text field. The way I did this was to set setAnagram to the value of the text field.
However, that didn't actually work, and setAnagram had a blank value (""). So then I thought okay well what if I set the variable to null. Well then I get a NullPointerException.
I thought well, what if the variable actually doesn't change, and it starts the thread before it can change the variable? Well I made it so you press the button once and it changes it, then you press it again, and then it starts the thread. Here's where the weird stuff comes in. I print out the value of setAnagram on the first button click after it has been changed. However, when I start the thread on the next button click, it's back to the what it was initialized as ("test"). Here's the code for the button click:
decodeAnagramButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
if (buttonPresses == 0) {
setAnagram = chosenAnagram.getText(); // chosenAnagram is the text field
buttonPresses++;
decodeAnagramButton.setText("Click again");
System.out.println(setAnagram); // These two lines output the same thing
System.out.println(chosenAnagram.getText());
}
else {
titleText.setText("Decoding anagram...");
decodeAnagramButton.setVisible(false);
MainWindow thread = new MainWindow();
thread.start();
}
}
});
And then to minimize, I won't add the thread code because it's kinda long, just know that all it does with setAnagram is get the value. Any ideas on why this is changing unexpectedly?
MainWindow thread = new MainWindow();
thread.start();
So... you create a new instance of MainWindow (which is apparently a thread?!?). That means that new instance of MainWindow also has its own setAnagram member variable, right?
Try adding thread.setAnagram = this.setAnagram; between these two lines of code.
(Also, something about your design smells fishy, why is your main window a thread?)
Related
I'm trying to switch between two frames in my main program.
The trigger to switching to the second frame from the first one, is one condition to be met and one button to be pressed in the first frame.
This is one example that I've tried so far, but the actionPerformed method only accepts a parameterized local variable e for ActionEvent so I'm unable to use this .getEvent() method in my main which access an empty ActionEvent field.
Do you have any idea on how i could proceed to achieve this?
pb = progress bar
next = button
if(gui.getEvent().getSource()==gui.getNext()&&gui.getpb().getValue()==100){
gui.dispose();
TrainingGui tgui = new TrainingGui();
}
I have a screen which has list. By right click, I can open a small pop up and add new records to the that list by choosing some record and clicking OK button from pop up.
OK button which is on pop up has an action listener like below:
okButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
setVisible(false);
}
});
And that is all the actionPerformed method does and I do not understand how this method is adding new record to the list on main window. There should be another part of code which is connected to this part but I do not know what is that. Do you have any idea what I do not see on that logic?
The ActionListener is not empty and in fact it is changing the state of the window that holds the JButton, making it no longer visible.
No one can say with 100% confidence what logic is being used here since you've yet to show enough code for that, but our guess is that this button is being held within a modal JDialog -- a window that freezes code flow in the calling code once the dialog window is visible, and (here's the key) that releases the block on code flow once this dialog is no longer visible. So in this situation, making the dialog no longer visible will allow the calling code, the code that initially told the dialog to display itself, to resume flow of its logic. Presumably in the subsequent code, it will query the dialog for data that was entered, and extract it, again the details of which are in code not yet shown to us.
I seem to have a fairly unique problem, and I searched for a while for an answer on here without finding one. I have a class that has a simple JFrame with two buttons. Each button calls the Main method of a different class, as such:
checkRuling = new JButton("Check Your Deck's Rulings");
checkRuling.addActionListener(new ActionListener() {
public void actionPerformed (ActionEvent e) {
ReadHtmlCardDatabase.main(null);
}
});
One calls a class that takes a series of inputs into a text field and creates a formatted html document from the inputs, and the other loads the html document into a JEditorPane. My problem is that when I close one of the JFrames for the subclasses (either the input or html loader one), it exits my program completely, and I want to keep the main class (with the two buttons) open. I've tried using:
close = new JButton("CLOSE");
close.addActionListener(new ActionListener() {
public void actionPerformed (ActionEvent e) {
System.exit(1);
}
});
On a button in the subclasses, to no avail. When the button is clicked it simply exits everything. I've also tried using:
JFrame.DISPOSE_ON_EXIT
For the subclasses, but this causes the JFrames to go away without the subclasses actually closing, so the first one that saves the html document never actually saves it, and the second subclass that opens that same html document won't work, because it wasn't saved. Any help would be appreciated, because I can't figure out how to do this.
As Fast Snail says in the comments, you shouldn't be calling a main method. Instantiate a class that does each functonality. Set the frame to visible using setVisible(true) when you start using it, then setVisible(false) when you're done. So, in the action listener, just change the visibility.
Then, assuming you don't have anything too wild going on, the frame you just set to invisible should go out of scope and get freed so that memory isn't chewed up. You just instantiate a new copy of the ReadHtmlCardDatabase class each time you need one. Or you could have one static copy that you set visible/invisible as needed.
one of the JFrames
You should use only one JFrame in Your GUI. For other windows You can use for example JDialog or JWindow.
This should help, if not You can always use frame.setVisible(false) instead of dispose on close, but it' s not very neat.
Thanks to someone who posted a comment and then deleted it, I've figured out my own problem. I just had to replace my main call with this:
setDeck = new JButton("Set Deck");
setDeck.addActionListener(new ActionListener() {
public void actionPerformed (ActionEvent e) {
WriteHtmlCardDatabase w = new WriteHtmlCardDatabase();
w.main(null);
}
});
Thank you!
I'm making a small game and I've already implemented a save function in which the game is saved (by writing information to a new XML file). The saving takes a couple of seconds and I want to do the following: while the program is saving the game, I want to change the look of the JPanel, and when it is done saving, I want to go back to another page(show another JPanel).
I have the following code:
confirm.addActionListener(new ActionListener () {
#Override
public void actionPerformed(ActionEvent e){
String fileNaam = saveGame.getText();
//This method changes the look of the panel
changePanel();
//This method saves the game
model.saveGame(fileNaam);
//This method takes the user back to a previous page
controller.viewTeamPage();
}
});
What happens is that the game is saved and the user is taken back to the teampage, but the panel is never changed. The changePanel() method does work, so that is not the problem but it seems like it is never executed. I was wondering if somebody knows how I can fix this.
EDIT:
private void changePanel () {
panel.removeAll();
panel.repaint();
panel.revalidate();
}
This is the method to change the look of the panel, for now I just remove everything on the panel to keep it simple.
Also, the saving is not done in a separate Thread, is that something I should look at?
EDIT 2: I fixed it by using a thread to save the game and return to the teampage after the saving is done. See the code below.
confirm.addActionListener(new ActionListener () {
#Override
public void actionPerformed(ActionEvent e){
final String fileNaam = saveGame.getText();
changePanel();
Thread t = new Thread (new Runnable () {
#Override
public void run() {
model.saveGame(fileNaam);
controller.viewTeamPage();
}
});
t.start();
}
});
If you are changing the same panel and not intializing a new panel then the problem i think is that you need to call the panel.revalidate or panel.repaint i think. I made a demo for a Procedural generation project and i had to do this to make my panel change.
Call your save game method from a new thread but don't "join" or "try" to wait for this thread to finish from inside the method actionPerformed();
Make the call to controller.viewTeamPage() after the save game thread is done saving the game. One simple way of doing that would be passing the "controller" object to the constructor of your custom thread so you can make that call after saving the game.
The step 1 is very important in this case because all the calls you are making in the method actionPerformed() are being made in the UI thread, preventing the entire UI from refreshing until the method returns. Even calling repaint() alone, in changePanel(), wont be enough because it just "schedules" a refresh on you panel that will only happen after actionPerformed() returns. If you put the most time consuming call in a separate thread however, the actionPerformed() returns quickly allowing the UI to be refreshed while the game saving thread is doing its job.
Each time the user presses a button a counter amountWrongGuessed gets incremented by 1. (works correctly with testing with System.prinln)
But how exactly do i get this to update in my label each time i press the button?
I have made a property that returns this value.
public int getAmountGuessed(){
return amountGuessed;
}
Next i try to get the value of the label, but the value always remains at 0.
lblAmountGuessDisplay = new JLabel(String.valueOf(hg.getAmountGuessed()));
private void UpdateComponents()
{
lblAmountGuessDisplay.setText(String.valueOf(hg.getAmountGuessed()));
}/*updateComponents*/
This example shows one way to update a label each time a button is clicked.
It might be a threading issue. Please take a look here.
I agree with Fredrick -- that you've not posted enough information for your question to be answerable and that it may be a reference issue -- that the JLabel you are changing is not the one that is displayed in the program. If you post more code, we'll have a better chance of giving your a decent answer. Also, this doesn't smell like a threading issue.
You need to add an ActionListener to your button. When the ActionListener is notified that the button is pressed, you can increment the counter and update the JLabel. The actionPerformed method will be triggered in the EDT, so you should be ok with threading.
lblAmountGuessDisplay.addActionListener( new ActionListener() {
public void actionPerformed(ActionEvent ae) {
hg.incrementAmountGuessed();
lblAmountGuessDisplay.setText(String.valueOf(hg.getAmountGuessed()));
}
}
You will probably need to implement the incrementAmountGuessed method (which may be the root of your problem in the first place).