I have a dilema. This might sound stupid but i have no idea how to do this.
I have a password class and a main screen. My main screen has a button that when pressed pops up the password class. Here is the call to the passwordClass from an actionlistener on my main class.
public PasswordClass login(){
pressMe.setVisible(true);
String player="?";
final String playerT = player;
boolean nameCorrect = false;
final PasswordClass hold = new PasswordClass(null);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
//Turn off metal's use of bold fonts
UIManager.put("swing.boldMetal", Boolean.FALSE);
PasswordClass.createAndShowGUI();
}
});
return hold;
}
the return statement isn't anything related to this I never used it but I had it their for testing purposes. In my password class i have a boolean that tells me if the user input matches the correct login info. i call it worked i run the password class and i had the problem that while the window is popping up my code to check if it worked is running simultaneously. This is a problem because i only want to check if it worked after the user has pressed ok. Here is the code
public void actionPerformed(ActionEvent ae)
{
else if(ae.getActionCommand().equals("Login")){
login();
}
else if(ae.getActionCommand().equals("Press Me To Continue")){
if(PasswordClass.worked){
//worked is a static variable from the PasswordClass class
}
pressMe.setVisible(false);
}
}
So whenever OK is pressed on The PasswordClass JFrame a little button pops up and asks a SECOND time for it to save. I want it to save from the first OK button. The reason i make another button is because i don't know how to stop and wait for the OK button to be pressed. My if loop to check if it worked already returns false automatically before the user presses OK. That is my problem and I am really confused on how to solve it.
Any help? If any more code is needed I will provide it but i think this is enough.
The reason i make another button is because i don't know how to stop and wait for the OK button to be pressed
Use a modal dialog of some kind, see How to Make Dialogs for more details
Conceptually, you want to display a modal dialog, which prompts the user for some information, while blocking at the point in your code that the dialog was made visible. When the dialog is dismissed (for what ever reason), you'll want to check the results from the dialog and take appropriate actions based on what the user did
There needs to be some form of synchronization between the objects (not necessarily related to the statement of that name).
If the code that wants to check the result wants to block until the result is set, you could use a CountDownLatch: the actionPerformed method calls CountDownLatch.countDown() while the other code calls CountDownLatch.await().
On the other hand, if the code checking the result does not want to block, then a simple two-boolean approach would work well. Have one boolean indicate whether the button press complete and the other to tell whether OK was the button pressed.
Related
I'm new to Java and I'm learning it for my computing coursework in college.
I have a button which is initially set to off(btn_state = false) while it displays the "off.png",
when the button is pressed I want the boolean var "btn_state" to set to true and display "on.png" and that if I press the button while it's set to true I want it to to set to false and display the "off.png"
If you didn't get what I said basically:
While boolean var button state = off display "off.png"
While state = on display "on.png"
When button is pressed,
if state = true then display "off.png" and set state = false
if state = false then display "on.png" and set state = true
I've tried making the button do as described above but failed D:, it seems pretty simple but I'm somehow incapable of coding it, maybe I'm just being stupid and going the complete wrong way about it lol, sorry if my explanation is still unclear :P
Here is the actual code:
JButton Gravity_btn = new JButton("");
boolean Gravity_btn_state = false;
while (Gravity_btn_state = false) {
Gravity_btn.setIcon(new ImageIcon("off.png"));
}
while (Gravity_btn_state = true) {
Gravity_btn.setIcon(new ImageIcon("on.png"));
}
Gravity_btn.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
System.out.println("Button has been pressed");
// I want it so that if "on.jpg" is showing and button is pressed then display "off.jpg" & vice versa
}
});
You are going about this in completely the wrong way.
Swing uses an Event Dispatching Thread (EDT), which calls methods to handle any generated events (including user button presses). When (and only when) those methods have returned control to the EDT will "painting" occur, which will redraw the user interface, including the any new icons on buttons.
while (Gravity_btn_state == false) {
Gravity_btn.setIcon(new ImageIcon("off.png"));
}
This loop will never end, locking up the user interface, and causing the application to never draw anything ever again. Nor will it respond to any user inputs. The button state cannot be changed, because control never returns to the EDT to accept new input from the user. And the UI will never be drawn because control never returns to the EDT.
What you want is to install an ActionListener on the button. When the button is clicked, the ActionListener will be invoked. In that listener, you would toggle gravity.
Since you've talking about gravity, you probably want things moving on the screen, being pulled "down". This means you want animation. Which, with Swing, means you want a Swing Timer. Again, the Timer would have an ActionListener which will be called when the timer expires (again, only if control always returns to the EDT). That timer should move things (i.e., change x,y variables), and call repaint() on the appropriate surface ... and return control to the EDT. The EDT will see that something needs repainting, and (if the event queue has nothing else in it) send the paint message to that thing, so it can draw itself.
There are plenty of tutorials on the Web for "Swing Animation". Do a search on that to find the tutorials, and try to redesign your application. If you get stuck, you can always return here for additional help.
I noticed a behavior that I can't explain. In my GUI, on a button click I display a custom Jdialog that has panel and bunch of textfield. I populate these textfields.
Here is the scenario I am seeing using pseduo code.
public void actionPerformed(ActionEvent e) {
CustomDialog viewDialog = new CustomDialog (Jframe, true);
viewDialog.setVisible(true);
viewDialog.populateInfo();
}
When the code above runs then all textfields are empty. However if I move the setVisible to after the populateInfo method then all the textFields are populated. Basically the JTextField.setText inside the populate info does not seem to have an affect if the setVisible happens before
Why is this!
Likely your CustomDialog class is a modal JDialog (also as suggested by the true 2nd constructor parameter). If so, then program flow in the calling code is blocked by the setVisible(true) call, and so your populateInfo() method will only be called after the dialog is no longer visible. The solution is as you already know -- call the method before displaying the dialog.
This is not a bug but a feature. :)
Seriously, since now you know for a fact when program code flow will be halted and when it will resume, and so you can safely query the dialog for its state after the setVisible(true) has been called, and feel confident that in the very least the dialog has been presented to the user, and the user has had time to interact with it and dispose of it.
In a Java Swing desktop app. I have a number of smaller classes, all of which are made use of in an overarching App Class. One of such smaller classes is a JPanel that represents my login page. I've added a mouselistener to the login button on this page, that goes thus:
Public class loginPage extends JPanel{
String username;
boolean capturedName=false;
JTextField nameField;
...
loginButton.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
username = nameField.getText();
capturedName=true; //for redundant checking of mouse click event
System.out.println(username); //error checking
System.out.println(capturedName); //error checking
}
});
}
In a separate display class that represents my JFrame, I make the login page an attribute of said class and I instantiate this display class in my app class, after adding the login page to it. I am trying to capture the login page username attr in the App class and pass it to other methods. But when I run the code, and click on the login button, the value in the textbox isn't captured.
To error check, I tried the ff:
//Set login page GUI up
while(display.loginPage.username==null){ //this is initially true
if (display.loginPage.capturedName){ //boolean to check if button has been clicked
display.loginPage.username=display.loginPage.nameField.getText(); //intentional redundancy
String username=display.loginPage.username;
System.out.print(username);
//pass username to other methods
}
}
When I run the code, enter a name on the username textfield, and click login, the typed name and a true value for the capturedName boolean are both printed, but the
if (display.loginPage.capturedName)
condition is never fulfilled. Also when I add in print display.loginPage.username, I get a null value . What could be the reason for this discrepancy between the same values?
What could be the reason for this discrepancy between the same values?
You could have two objects of the same type, one displayed, whose state is being changed, and one not displayed that you're checking in the if block.
But again, for better help, consider creating and posting a Minimal, Complete, and Verifiable Example Program. We don't want to see your whole program, but rather you should condense your code into the smallest bit that still compiles, has no extra code that's not relevant to your problem, but still demonstrates your problem. As an aside, you will never want to use a MouseListener with a JButton as you're doing. Instead use an ActionListener as that is what it was built for.
"I've added a mouselistener to the login button" - Not a good idea, buttons should use ActionListener, see How to Write an Action Listeners and How to Use Buttons, Check Boxes, and Radio Buttons;
while(display.loginPage.username==null){ is a REALLY, REALLY bad idea which could lock up your UI and suggests that you violating the single thread rules of Swing. See Concurrency in Swing for more details.
What it sounds like you need is a modal dialog, which can block the execution of the code at the point the dialog is made visible...
See How to Make Dialogs for more details
Take a look at Java and GUI - Where do ActionListeners belong according to MVC pattern? for an example of a Login dialog/form using the MVC paridigm (Model-View-Controller)
Turns out as #MadProgrammer suggested, that I was creating two different loginPage objects in my display class. It's curious, however, that the mouselistener on the login page GUI that was visible actually listened for, and returned expected results of the better defined login page object (which was invisible).
i have a small program where an element is draged and dropped, when the drop is performed i open a dialog (extends Jframe) where some text should be entered. The Problem is, that i want to wait for this dialog to be closed (actually the ok button to be pressed so i can read out the data from the textfield), than analyse what the user has entered and based on that i will decide if the drop is rejected or allowed.
public void drop(DropTargetDropEvent e) {
try{
//popup
Popup p = new Popup();
p.setParmeter("enter a new name: ");
p.setVisible(true);
//programm wont wait before the user has pressed ok in the popup
System.out.println("value: " + p.getValue());
repaint();
} else {
e.rejectDrop();
}
}
I hope you get the idea. Popup is a dialog extended from a JFrame. The problem is, that p.getValue() is executed before the User gets to press the ok button. I tried using a boolean variable and a loop to check if something was entered in the popup but it doesnt work, the dialog is desplayed but there is not textfield or ok button, so the only thing i can do is to kill it. I'm pretty new to gui's so i really would appreciate the help. Thanks in advance.
If possible you should re-implement Popup to inherit from JDialog instead of JFrame, and call JDialog's setModal(true) method, which will prevent subsequent code from running until the dialog is dismissed.
Alternatively, check out the static convenience methods in JOptionPane, which eliminate the need to implement your own bespoke dialog class in many cases. For example (from the JOptionPane API):
Show an information panel with the options yes/no and message 'choose one':
JOptionPane.showConfirmDialog(null, "choose one", "choose one", JOptionPane.YES_NO_OPTION);
Java has built-in dialog support. Yon don't want to extend JFrame. See the tutorial on how to make dialogs.
Now, I'm not sure if this is possible or even the best way to accomplish what I'm trying to do, but basically I'm creating a very simple simulation program with a very simple Swing GUI.
After each round of the simulation, some buttons on the interface are enabled for the user to make changes and then the user can press the "continue" button to start the simulation again. The simulation itself is basically a while loop that needs to wait for the user action before continuing. My question is how can I have the program stop and wait until the user presses the "continue" button? Please let me know if there are any more details I can provide if this is unclear!
Edit:
I'm going to add some simplified code here so maybe this will make more sense. The program is in two parts, the simulation class and the view. So the button to be pressed is in the view class while the simulation is happening in its class.
Simulation class:
SimulationView view = new SimulationView(); // extends JFrame
while (!some_condition) {
// code
// need user action via button press here before continuing!
}
Most likely the best way to go is enclose one round of the simulation in a method, that would then be executed from the action listener attached to the button you want.
After edit:
Somebody needs to control the simulation in the first place, so you could do the following:
SimluationClass
{
public int startSim()
{
...
}
}
class SimulationView
{
SimulationClass sim = new SimulationClass();
private void init()
{
JButton button = new JButton("Start");
button.addActionListener(new ActionListener() {
void actionPerformed(...)
{
sim.startSim()
}
});
}
}
Keep in mind though that this will freeze your gui as the sim method will be executed from the event thread.