Java GUI Input Dialogs are showing up twice - java

I have an assignment for class, and I made a simple accounting program in Java with a GUI. This is my first time working with a GUI in Java, and i'm not that good a programmer.
When the program runs, the user can select five JButtons which when clicked takes them to a new JFrame with some input dialogs, which are saved as Strings and Doubles.
My variables are set to something like
variable = JOptionPane.showInputDialog("TEXTGOESHERE");
My Problem is that after entering values into the dialogs, they will pop up a second time, like in a loop. The user has to enter an input into every dialog twice.
Code for one of the buttons:
pcButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
JFrame pcframe = new JFrame("Choosing a File Menu");
pcframe.setSize(760,500);
pcframe.add( new JPanel()
{
public void paintComponent( Graphics g )
{
super.paintComponent(g);
//ACTION BEGIN-----------------------------------------
The input dialogs which are showing up twice:
compName = JOptionPane.showInputDialog("What is the name of your business?");
firstName = JOptionPane.showInputDialog("What is your first name?");
lastName = JOptionPane.showInputDialog("What is your last name?");
day = JOptionPane.showInputDialog("What is the day?");
month = JOptionPane.showInputDialog("What is the month?");
year = JOptionPane.showInputDialog("What is the year?");
String filename = JOptionPane.showInputDialog("Would you like file 1, 2, or 3? (Type in 1, 2, or 3");
filename = (filename + ".txt");
//Storing File into array
//Calculations
g.drawString("" + compName, 330, 15);
//More drawStrings
//ACTION END-------------------------------------------
}
});
pcframe.setVisible( true );
}
});
modePanel.add(pcButton);
When the pcButton is pressed, the user is supposed to enter their name, file, etc. However, every dialog input shows up twice. I want the inputs to show up just once.
Any help would be greatly appreciated, thanks.

Sorry, but that's all wrong. You should never call JOptionPanes or do anything other than painting from within a paintComponent method. You never have full control over when or even if that method gets called, and your program's perceived responsiveness is partly dependent on how fast that method completes its jobs. So my main recommendation -- get all non-painting code out of that method and into a method that you can fully control.
Myself, rather than throw a bunch of JOptionPanes at the user, I'd create a JPanel that has all the fields that I want the user to fill out, and then show one single JOptionPane that holds this JPanel, and get all the input all at once.
Next, your secondary dialog window should be a true dialog, and for Swing that means a JDialog (or JOptionPane which is a type of modal JDialog) and not a JFrame.

Related

How to return variable from actionPerformed?

I'm not looking for direct answers. Just a general direction where I'm supposed to search or little hints, as this is an assignment for a class.
I am supposed to create a game, and in order for the user to start the game, they must enter their name through a JOPtionPane, at the moment, I have coded this:
JButton nameBtn = new JButton("NAME");
nameBtn.setBounds(25, 10, 250, 30);
nameBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String name;
do{
name = JOptionPane.showInputDialog(frame, "ENTER YOUR NAME", "", JOptionPane.QUESTION_MESSAGE);
if(name != null)
;
else
JOptionPane.showMessageDialog(frame, "No name entered");
}while(name == null);
}
});
What I want to do is then display that user entered name unto another panel. How would one go about doing that?
If I am understanding the question correctly, then you want to use the name result from the input dialog and display it in an existing label in the outer class. You can simply create a method in the outer class that takes the name as a String argument and that adds it to any of the components in that outer class. You can call this method from within the ActionListener. Without including the element where the name should end up in your question, I cannot go more specific than this.
Nvm, I found my own answer
// buttons
JButton nameBtn = new JButton("NAME");
nameBtn.setBounds(25, 10, 250, 30);
nameBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String name;
do{
name = JOptionPane.showInputDialog(frame, "ENTER YOUR NAME", "", JOptionPane.QUESTION_MESSAGE);
if(name != null)
;
else
JOptionPane.showMessageDialog(frame, "No name entered");
}while(name == null);
//take user input (name) and assign it into a JLabel, which will be added
to my desired Panel
JLabel userName = new JLabel(name);
botPan.add(userName);
userName.setBounds(400, 20, 55, 30);
}
});
Execution continues uninterrupted immediate on from the call to addActionListener. So the code following the listener registration is executed at the wrong time to receive such a returned value.
The action to be performed should be initiated within the actionPerformed method or methods that it calls. And that's about it. In an anonymous inner class, as used in the question, access is available to the enclosing scope.
As a note of style, listener implementations should usually be short, just removing the necessary information from the event (often only that it happened at all) and calling an uncluttered method that does the useful work.
For tasks that may block the AWT Event Dispatch Thread (EDT), work can be done on another thread. Any resultant manipulation to AWT/Swing object need then be performed with a java.awt.EventQueue.invokeLater call to run on the EDT.
Some methods dealing with modal dialogues, such as presumably showInputDialog, use a hack whereby EDT events are processed within the method call. You can see this in stack traces. Modal dialogues are generally considered poor UI.

Trying to create 3x password checker (using buttons and GUI)

Im having problems creating a GUI. I want to make a program that allows users to enter their password through buttons, and it takes 3 chances before the GUI closes. I have attempted a few different methods but cannot get it to fully work.
JTextField1 is where the instructions are shown.
JTextField2 is where the password is input (correct password should be 1234)
After putting in the wrong password for the 3rd time I want it to shut.
I think the issue is that it is taking the same password 3 times and will automatically end, but I am not sure how to fix or loop properly as I am quite new to java and gui's.
This is what I have so far:
final String PASSWORD = "1234";
int attempts = 3;
String password = "";
while (attempts-- > 0 && !PASSWORD.equals(password))
{
jTextField1.setText("Enter your password");
password = jTextField2.getText();
if (password.equals(PASSWORD))
jTextField1.setText("Welcome ");
else
jTextField1.setText("Incorrect Pin, please try again");
}
Consider these two lines:
jTextField1.setText("Enter your password");
password = jTextField2.getText();
The second line executes immediately after the first line. There is no code here which waits for the user to type anything.
Graphical user interfaces are event-based. A program must respond to events based on user behavior. It is not possible to handle GUI interactions a single sequential function.
You respond to events in Java by adding an event listener to an object which is capable of generating certain kinds of events. A JTextField fires an action event when the user presses Enter while it has focus. JButtons fire an action event when activated (by user doing a mouse press and release inside it, or by the user pressing space while it has focus).
You want to add an ActionListener only once, typically right after you create the component to which it will be added. Since the ActionListener is a separate method, you will need to keep track of your attempts in an instance field:
private static final String PASSWORD = "1234";
private int attempts = 3;
// ...
private void buildWindow() {
// ...
jTextField2 = new JTextField(20);
jTextField2.addActionListener(e -> checkPassword());
// ...
}
private void checkPassword() {
if (password.equals(PASSWORD)) {
jTextField1.setText("Welcome ");
} else if (--attempts > 0) {
jTextField1.setText("Incorrect Pin, please try again");
} else {
System.exit(0);
}
}

Java Swing: Swing Worker, invokeAndWait and Overlapping JLabels

Hey guys I've come with 2 problems, both being Java Swing related. I am developing a card game in Java. I use arreays lists of type to hold the values of each card and I have a main Play() method that calls updates to the GUI using invokeLater and a Singleton approach to my GUI class.
The first question is fairly simple. I create the cards on the GUI using JLabels like so; attaching relevent listeners and adding them to the appropriate panel, in this case, the 'Human Hand Panel':
for (int i = 0; i < (HumanHand.size()); i++)
{
Card card = HumanHand.get(i);
BufferedImage cardImage = null;
try {
cardImage = ImageIO.read(new File("card/" + card + ".jpg"));
} catch (IOException e) {
e.printStackTrace();
}
JLabel picLabel = new JLabel(new ImageIcon( cardImage ));
picLabel.addMouseListener((MouseListener) me);
HumanHandDisplay.add(picLabel);
}
//HumanHandDisplay.validate();
HumanHandDisplay.updateUI();
The problem I'm having is that when the human hand is more than 7 cards or so, it creates a larger panel area and starts a new row of cards beneath. What I would like to do is, when the hand reaches a certain size, the cards start to overlap eachother (like you would hold cards in your hand). I've messed about with .validate() but gotten nowhere. Any help you can give here would be most welcome.
My second question is about using a Swing Worker to return the Human player's card selection. I have read a little bit about Swing workers but I'm unsure as to the best way to implement one in my own game. At present, using the console I have a scanner than takes the input of an int as the choice (the place of the specific card in the ArrayList). I would like this int to be selected by clicking on the card in the players hand. At the moment I use:
String name = "" + i;
picLabel.setName(name);
to set the names of the Card JLabels to the int in the for loop creating them (as shown^^), and I use:
public void mouseClicked(MouseEvent e) {
String name = ((JLabel)e.getSource()).getName();
System.out.println("Working " + name);
selection = Integer.parseInt(name);
}
To return that int when one of the cards is clicked. Here is what I've been using to call the GUI methods from Play() aswell:
SwingUtilities.invokeLater(new Runnable() {
public void run() {
GUI.getInstance().UpdateHand();
}
});
My question is, how can I get the Play method to call a method in the GUI class, which sets up the hand with the appropriate listeners (lets call it GUIPlayerSelection() for now) then wait for the player to click a card, which then returns the int to my Play() method in my main class that represents the card selected. I'm unsure as how to use invoke and wait, as in, if I use invoke and wait, will it just wait for the cards to be set up, or will it wait for the mouseClicked() method to finish aswell? Or will I have to do something else to make sure it waits for the mouse to be clicked after the hand set-up? And how then will I return that int? I've been told to use a swing worker but if someone could explain how I can implement that in this case that would be awesome.
Thank-you in advance.
For your first question, are you having an issue getting the frame to repaint or with the layout of the cards?
If the latter, then you may want to have a look at Java Layout Managers, it describes how the content pane inside your JFrame organizes the components added to it.
If none of those will work for you (and I don't think they will with that you describe), you can use the setBounds method to manually align your JLabels.

Java. How to wait?

I call a class that creates a jframe and waits from user to input some values.
The problem that I experience is that I need to wait these values before to continue.
So the code is something simple like this
Jframe frame= new jframe(); //here I want the program to show the frame and then wait till it will be disposed
// I want a pause here
System.out.println(frame.getvalue);
Till now the only I could do is to froze the frame before can even appear totally.
Any help?
Please keep it simple since I am new to Java.
THANK YOU!
I think you should use JDialog instead of JFrame. Please follow this example
What you're probably looking for is JOptionPane. This is a blocking routine that returns only after the user has entered some value, like so:
public class test
{
public static void main ( String args[] )
{
String input = JOptionPane.showInputDialog(null, "Thing: ",
"Enter Stuff", JOptionPane.OK_CANCEL_OPTION);
System.out.println ( "won't reach until got input");
System.out.println ( "My value: " + input );
}
}
The great thing about it is you can add Components to it, so you aren't limited to a single input field, but it is still blocking. The following would add two JTextField's to the frame:
public class test
{
public static void main ( String args[] )
{
JTextField input_box = new JTextField(7);
JTextField input_box2 = new JTextField(7);
JComponent[] inputs = new JComponent[] {
new JLabel("Thing 1:"),
input_box,
new JLabel("Thing 2:"),
input_box2 };
int rval = JOptionPane.showConfirmDialog(null, inputs,
"Enter Stuff", JOptionPane.OK_CANCEL_OPTION);
if ( rval == 0)
{
System.out.printf ("%s and %s!", input_box.getText(),
input_box2.getText());
}
}
}
Instead of using a JFrame, consider using a JDialog with modality set to true.
When it comes time to add an 'OK' button or something like that, check out JRootPane.setDefaultButton()
well as you know swing components are not thread safe though you can use SwingWorker to make the waiting in background,
It uses the thread way but it creates a new thread for the waiting ,long term operations in general,
instead of pausing the event dispatch thread so the user can interact with the rest of the application or the rest of the application can continue to work while the waiting goes on.
ofcourse you have to define a way for it to stop the waiting.
check out its documentation here http://docs.oracle.com/javase/6/docs/api/javax/swing/SwingWorker.html
This will cause the current thread to wait 5 seconds:
try {
Thread.currentThread().wait(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}

Set keyboard shortcut for a JButton?

I have a type game in which you have to type the words that appear as fast as possible before the time limit runs out, but every time you type a word, you must move the mouse and click enter and click back into the user input to type the next word. I was just hoping if there was way to use "keyCode.VK_Enter" to issue an Action Command called by the JButton.
Some snippets of my code:
The Enter button and user input and output:
enter = new JButton("Enter");
enter.setFont(serif); //serif is specified earlier
enter.setActionCommand("Enter");
enter.addActionListener(this);
container.add(enter);
userOutput = new JTextField(50);
userOutput.setFont(serif);
container.add(userOutput);
userOutput.setEditable(false);
userInput = new JTextField(43);
userInput.setFont(serif);
container.add(userInput);
userInput.setEditable(false);
The actionPerformed method getting the enter button's action command:
if(userInput.getText().equals(userOutput.getText())){
userInput.setText("");
score += 100;
Why don't you just add an actionlistener to the JTextField (which would be triggered when the user hits enter).
userInput.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// Do something
}
});

Categories

Resources