I want the user to type a name for player one and press enter and then for the textfield to be blank again so that the user can type in a name for player 2. so far I can only get player one's name as input but not player two. For some reason my code isn't working. Any help would be greatly appreciated. Thanks in advance.
import java.lang.*;
import java.util.*;
import java.util.List;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import javax.swing.*;
public class mainClass extends JPanel implements ActionListener {
//constant variables to use
static String playerOneName;
static String playerTwoName;
static boolean playerOneNameSet;
static boolean playerTwoNameSet;
private static final long serialVersionUID = 1L;
public mainClass() {
}
public void paintComponent(Graphics g) {
//set background color to white
g.setColor(Color.white);
g.fillRect(0, 0, getWidth(), getHeight());
}
public static void initializeBoard() {
}
public static void main(String[] args) {
// title of frame
JFrame frame = new JFrame("Risk");
JTextField textField = new JTextField(20);
frame.add(textField, BorderLayout.SOUTH);
JLabel welcome = new JLabel("");
welcome.setText("Please Enter name for Player 1 in the text box at the bottom");
frame.add(welcome,BorderLayout.NORTH);
//action listener listens for enter key
textField.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
playerOneName= textField.getText();
System.out.println(playerOneName);
playerOneNameSet = true;
System.out.println(playerOneNameSet);
}
});
if(playerOneNameSet == true) {
JTextField textField2 = new JTextField(20);
frame.add(textField2, BorderLayout.SOUTH);
JLabel welcome2 = new JLabel("");
welcome2.setText("Please Enter name for Player 2 in the text box at the bottom");
frame.add(welcome2,BorderLayout.NORTH);
//action listener listens for enter key
textField2.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
playerTwoName= textField2.getText();
System.out.println(playerTwoName);
playerTwoNameSet = true;
System.out.println(playerTwoNameSet);
}
});
}
// make sure it closes correctly
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//frame size in pixels
final int FRAME_WIDTH = 1000;
final int FRAME_HEIGHT = 700;
frame.setSize(FRAME_WIDTH,FRAME_HEIGHT);
// makes sure the frame is visible
frame.setVisible(true);
mainClass main = new mainClass();
frame.add(main);
}
#Override
public void actionPerformed(ActionEvent e) {
}
}
There is one logical error in your code.
If you want to use only one JTextField for two inputs, you do not need to create
two JTextField. Just handle the ActionEvent and update only that JTextField. Here is the code for that:
textField.addActionListener(new java.awt.event.ActionListener()
{
public void actionPerformed(java.awt.event.ActionEvent evt)
{
if (!playerOneNameSet)
{
playerOneName = textField.getText();
textField.setText("");
welcome.setText("Please Enter name for Player 2 in the text box at the
bottom");
playerOneNameSet = true;
}
else
{
playerTwoName = textField.getText();
textField.setText("");
}
}
});
The if part after that is not required. It will also eliminate the use of playerTwoNameSet.
If you want to use two JTextField, then you have to do it in the start properly without any logical flaw.
Logical Error in Detail:
Let me try to show you the flow of your program.
public static void main(String[] args)
{
// title of frame
JFrame frame = new JFrame("Risk");
.
.
.
.
//action listener listens for enter key
textField.addActionListener(new java.awt.event.ActionListener()
{
public void actionPerformed(java.awt.event.ActionEvent evt)
{
playerOneName= textField.getText();
System.out.println(playerOneName);
playerOneNameSet = true;
System.out.println(playerOneNameSet);
}
});
Your code is all good till here. After the above line, this happens
if(playerOneNameSet == true) //It is never executed
The reason this happens because playerOneNameSet is a static variable and its default value is false. This line is only executed once. Once your GUI is created, the main() method will not be called again until you run it again. After that, the control passes to the one JTextField that was created, that too when any ActionEvent is generated. It will never go to the if line after that.
I hope I have helped you. Do comment for any further problems.
Related
I am still learning how to code in java and I could use a bit of help right now.
This is the current code I wrote. As you can see, it's a simple panel with a bunch of buttons and a slider. I want to make a different console output whenever I hit a different button. So if I hit Back, it's supposed to write Back in the console. If I scroll a bit on the slider, it's supposed to write the new value in the console. Stuff like that. I know it has to be done with actionListener and actionPerformed but after some experimenting I couldn't get it to work.
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Gui implements ActionListener {
// Adding all the goods
JFrame frame;
JPanel panel;
JButton endButton;
JButton backButton;
JButton calcButton;
JSlider maxIterations;
JLabel view;
Gui() {
// General
this.frame = new JFrame("Trying my best, I swear");
this.frame.setSize(500, 500);
this.frame.setVisible(true);
this.panel = new JPanel();
// Buttons
this.backButton = new JButton("Back");
this.calcButton = new JButton("Calc");
this.endButton = new JButton("End");
this.panel.add(this.endButton);
this.panel.add(this.calcButton);
this.panel.add(this.backButton);
this.frame.add(this.panel);
// Label
JLabel label1 = new JLabel();
label1.setText("Space Holer");
panel.add(label1);
// Slider
JSlider slider = new JSlider(JSlider.HORIZONTAL, 0, 30, 15);
panel.add(slider);
slider.setMinorTickSpacing(2);
slider.setMajorTickSpacing(5);
slider.setPaintTicks(true);
slider.setPaintLabels(true);
// Make the buttons do something
this.endButton.addActionListener(this);
}
public void actionPerformed(ActionEvent ae) {
System.out.println("End");
}
public static void main(String[] args) {
#SuppressWarnings("unused")
Gui m = new Gui();
}
}
You could...
Take advantage of the actionCommand property of the button, which is set to the ActionEvent when it's created. If you don't supply an actionCommand to the button yourself, it will default to the text value, so you could do something like
public class ButtonActionHandler implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
switch (e.getActionCommand()) {
case "Back":
System.out.println("Back");
break;
case "Calc":
System.out.println("Calc");
break;
case "End":
System.out.println("End");
break;
}
}
}
This is good if the ActionListener is external to the class where the buttons are defined, because you won't have access to the button references. It's also good, because you could have a number of buttons (including toolbar buttons and menu items) which do the same thing
You could...
Make use of the ActionListener's source property
public class ButtonActionHandler implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == backButton) {
System.out.println("Back");
} else if (e.getSource() == calcButton) {
System.out.println("Calc");
} else if (e.getSource() == endButton) {
System.out.println("End");
}
}
}
This is useful if the ActionListener in defined as a inner class to the parent class from where the buttons are defined
You could...
Use an anonymous class registered directly against the button...
endButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("End");
}
});
This is good where the button does a single, isolated task
You could...
Make use of the Action API which allows you to define a self contained unit of work, which can be used by buttons to configure themselves completely from it. This is useful where you have a repeated action which can be executed from different locations of the UI, like a "open file" action contained in the menu bar, tool bar and some wizard. You can even use it with the key bindings API for extended functionality
See How to use actions for more details
Need to add ActionListener to all buttons,
calcButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("calcButton");
// calculation for slider.
}
});
backButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("backButton");
}
});
then u get the different console output.
Call setVisible on jframe after you placed all components into it.
Add ActionListener to each button. Add ChangeListener to slider as it cannot have ActionListener.
See full code:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
public class Gui implements ActionListener {
// Adding all the goods
JFrame frame;
JPanel panel;
JButton endButton;
JButton backButton;
JButton calcButton;
JSlider maxIterations;
JLabel view;
Gui() {
// General
this.frame = new JFrame("Trying my best, I swear");
this.frame.setSize(500, 500);
this.panel = new JPanel();
// Buttons
this.backButton = new JButton("Back");
this.calcButton = new JButton("Calc");
this.endButton = new JButton("End");
this.panel.add(this.endButton);
this.panel.add(this.calcButton);
this.panel.add(this.backButton);
this.frame.add(this.panel);
// Label
JLabel label1 = new JLabel();
label1.setText("Space Holer");
panel.add(label1);
// Slider
JSlider slider = new JSlider(JSlider.HORIZONTAL, 0, 30, 15);
panel.add(slider);
slider.setMinorTickSpacing(2);
slider.setMajorTickSpacing(5);
slider.setPaintTicks(true);
slider.setPaintLabels(true);
// Make the buttons do something
this.endButton.addActionListener(this);
this.backButton.addActionListener(this);
this.calcButton.addActionListener(this);
slider.addChangeListener(e -> {
Object source = e.getSource();
if (source instanceof JSlider) {
int value = ((JSlider) source).getValue();
System.out.println(value);
}
});
frame.pack();
this.frame.setVisible(true);
}
public void actionPerformed(ActionEvent ae) {
Object source = ae.getSource();
if (source instanceof JButton) {
String text = ((JButton) source).getText();
System.out.println(text);
}
}
public static void main(String[] args) {
#SuppressWarnings("unused")
Gui m = new Gui();
}
}
I'm tying to make a program that acts similar to the Windows Command Prompt, or a terminal. It's basically just a JFrame with a JTextArea as output, and a JTextField as input. It looks like this:
I want to be able to get input from the JTextField whenever my program calls a method that returns a String, something like:
public static String getInput() {
//Wait for user to enter something, then press the enter key
}
I added an AbstractAction so I can do stuff when the enter key is pressed, but I still could figure out how to return the input as a String whenever I call the method.
Action action = new AbstractAction(){
#Override
public void actionPerformed(ActionEvent e) {
//Clears the JTextField
input.setText("");
}
};
I could put something like userInput = input.getText() in public void actionPerformed(), so it would just set a variable to whatever has been entered every time, and use userInput whenever I want to, but I want the user to have time to read whats on the screen, then have the program wait for a response, instead of just using the last thing they entered right away.
I tried to use a userInput variable and a boolean variable like this:
private static String userInput = "";
private static boolean enterPressed = false;
Action action = new AbstractAction(){
#Override
public void actionPerformed(ActionEvent e) {
userInput = input.getText()
enterPressed = true;
input.setText("");
}
};
...
public static String getInput() {
enterPressed = false;
while(!enterPressed){
//Do Nothing
}
enterPressed = false;
return userInput;
}
When I called output.setText(getInput());, it worked like I wanted to, except that the while(!enterPressed){} made my processor work a lot harder than it should need to. I'm pretty sure there's probably a lot better way of doing this.
Here's my whole code right now:
public class ConsoleFrame {
//Objects for Console Frame
JFrame frame = new JFrame();
JTextArea output = new JTextArea();
JTextField input = new JTextField();
BoxLayout boxLayout = new BoxLayout(frame.getContentPane(), BoxLayout.Y_AXIS);
JScrollPane scrollPane = new JScrollPane(output);
DefaultCaret caret = (DefaultCaret)output.getCaret();
Action action = new AbstractAction(){
#Override
public void actionPerformed(ActionEvent e) {
input.setText("");
}
};
ConsoleFrame(){
input.addActionListener(action);
caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
frame.setLayout(boxLayout);
frame.add(scrollPane);
frame.add(input);
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500, 250);
frame.setLocationRelativeTo(null);
input.setMaximumSize(new Dimension(Integer.MAX_VALUE, 10));
output.setEditable(false);
output.setAutoscrolls(true);
}
public static String getInput() {
return null;
}
}
So, how could I stop the program until the user presses enter, every time I call getInput();?
I want to be able to get input from the JTextField whenever my program
calls a method that returns a String, something like:
I added an AbstractAction so I can do stuff when the enter key is
pressed, but I still could figure out how to return the input as a
String whenever I call the method.
public String getInput() {
return input.getText();
}
So, how could I stop the program until the user presses enter, every time I call getInput();?
You don't. Swing, like most UI frame works is event driven, that is, something happens and your respond to it.
So, with that in mind you should consider using some kind Observer Pattern, where you use a call back to be notified of some kind of change which you are interested in, like your ActionListener for example.
Instead, you could provide some kind of listener, which interested parties would register with and when the field changes you would notify them, for example...
import java.util.EventListener;
import java.util.EventObject;
public class InputEvent extends EventObject {
private final String text;
public InputEvent(Object source, String text) {
super(source);
this.text = text;
}
public String getText() {
return text;
}
}
public interface InputObsever extends EventListener {
public void inputChanged(InputEvent evt);
}
So, we now have an observer who will be notified when ever the input is changed/updated.
Then we simply need a way to un/register and fire the event...
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.event.EventListenerList;
import javax.swing.text.DefaultCaret;
public class ConsoleFrame {
//Objects for Console Frame
JFrame frame = new JFrame();
JTextArea output = new JTextArea();
JTextField input = new JTextField();
BoxLayout boxLayout = new BoxLayout(frame.getContentPane(), BoxLayout.Y_AXIS);
JScrollPane scrollPane = new JScrollPane(output);
DefaultCaret caret = (DefaultCaret) output.getCaret();
Action action = new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
fireInputChanged(input.getText());
input.selectAll();
}
};
private EventListenerList listenerList = new EventListenerList();
ConsoleFrame() {
input.addActionListener(action);
caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
frame.setLayout(boxLayout);
frame.add(scrollPane);
frame.add(input);
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500, 250);
frame.setLocationRelativeTo(null);
input.setMaximumSize(new Dimension(Integer.MAX_VALUE, 10));
output.setEditable(false);
output.setAutoscrolls(true);
}
public String getInput() {
return input.getText();
}
public void addInputObsever(InputObsever obsever) {
listenerList.add(InputObsever.class, obsever);
}
public void removeInputObsever(InputObsever obsever) {
listenerList.remove(InputObsever.class, obsever);
}
protected void fireInputChanged(String text) {
InputObsever[] listeners = listenerList.getListeners(InputObsever.class);
if (listeners.length > 0) {
InputEvent evt = new InputEvent(this, text);
for (InputObsever obsever : listeners) {
obsever.inputChanged(evt);
}
}
}
}
Now, the point here is, when you want to know when the text has been input/changed, you register an observer to the instance of the ConsoleFrame
console.addInputObsever(new InputObsever() {
#Override
public void inputChanged(InputEvent evt) {
// Do what ever you need to do...
}
});
EDIT: First half removed. It was brought to my attention that it was erroneous.
The best option is to enclose a call to whatever you need your computer to execute after the user inputs text inside your actionPerformed method. So when the user inputs text and presses enter, the program automatically continues from there.
Action action = new AbstractAction(){
#Override
public void actionPerformed(ActionEvent e) {
userInput = input.getText()
enterPressed = true;
input.setText("");
//call next method;
}
};
This requires some more formatting work on your behalf, but it could be helpful depending on your project. This link has more information on this strategy.
Hope this helped.
jTextField1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
yourFunction(jTextField1.getText());
jTextField1.setText("");
}
});
Btw just a tip, you may append the JTextArea to get the feel of a console window
I want to close my JDialog by hitting the "enter" key on my keyboard. how can I do that? thank you!
NOTE:
I want to do this, without any button involved.
THank you!
One way:
You could give it a close JButton
whose ActionListener has code that closes the dialog,
And make that button the default button for the dialog's rootpane.
e.g.,
myDialog.getRootPane().setDefaultButton(exitButton);
Option two:
Use Key Bindings to bind the enter key to exit code in an AbstractAction.
e.g.,
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.*;
public class DemoDialog {
public static void main(String[] args) {
JFrame frame = new JFrame("Frame");
frame.add(Box.createRigidArea(new Dimension(400, 300)));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
final JDialog dialog = new JDialog(frame, "Dialog", true);
// set binding
int condition = JPanel.WHEN_IN_FOCUSED_WINDOW;
InputMap inputMap = ((JPanel) dialog.getContentPane()).getInputMap(condition);
ActionMap actionMap = ((JPanel) dialog.getContentPane()).getActionMap();
String enter = "enter";
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), enter);
actionMap.put(enter, new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
dialog.dispose();
}
});
dialog.add(Box.createRigidArea(new Dimension(200, 200)));
dialog.pack();
dialog.setLocationRelativeTo(frame);
dialog.setVisible(true);
}
}
I would like to say first that 'Hovercraft Full Of Eels' solution is more elegant than this one and more closely in the spirit of the JDialog and Swing API. However, to offer an alternative here is a basic example of using a KeyListener on your JDialog that will do as you need without adding a button;
public class Test {
public static void main(String[] args) {
JDialog jd = new JDialog();
// Add and define the KeyListener here!
jd.addKeyListener(new KeyListener(){
#Override
public void keyTyped(KeyEvent e) {
// Nothing
}
#Override
public void keyPressed(KeyEvent e) {
// Nothing
}
#Override
public void keyReleased(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_ENTER){
JDialog d = (JDialog)e.getSource();
d.dispose();
}
}
});
// End key listener code
jd.setVisible(true);
}
}
The important/relevant code is between the two main comments. This is a compilable example, so you can copy paste this into a new file and run it to view the effects.
I am using Netbeans, and I want it so a text field is only editable when the user clicks the check box. I have it so when they select the check box it makes the text field editable, but how do I make it so when they de-select the check box the text field becomes un-editable again?
The code I used to make it editable is -
private void chk4By6MouseClicked(java.awt.event.MouseEvent evt) {
txt4By6.setEditable(true);
}
Use ItemListener, so that you can enable or disable the JTextField depending on if JCheckBox is SELECTED or DESELECTED respectively.
A sample program :
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ModifyTextField
{
public static void createAndDisplayGUI()
{
JFrame frame = new JFrame("MODIFY TEXTFIELD");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationByPlatform(true);
final JPanel contentPane = new JPanel();
final JTextField tfield = new JTextField(10);
tfield.setEnabled(false);
final JCheckBox cbox = new JCheckBox("Enable TEXTFIELD", false);
ItemListener itemListener = new ItemListener()
{
public void itemStateChanged(ItemEvent ie)
{
tfield.setEnabled(ie.getStateChange() == ItemEvent.SELECTED)
}
};
cbox.addItemListener(itemListener);
contentPane.add(cbox);
contentPane.add(tfield);
frame.getContentPane().add(contentPane);
frame.pack();
frame.setVisible(true);
}
public static void main(String... args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
createAndDisplayGUI();
}
});
}
}
Outcome :
and
See: http://docs.oracle.com/javase/tutorial/uiswing/events/actionlistener.html
Read the whole thing if you really want to learn how this works.
Have you considered:
private void chk4By6MouseClicked(java.awt.event.MouseEvent evt) {
txt4By6.setEditable(!txt4By6.isEditble());
}
Or maybe even... (assuming chk4By6 is a swing checkbox)
private void chk4By6MouseClicked(java.awt.event.MouseEvent evt) {
txt4By6.setEditable(chk4By6.isSelected());
}
And a third method might be:
private void chk4By6ActionPerformed(ActionEvent evt) {
txt4By6.setEditable(chk4By6.isSelected());
}
I have 2 JTabbedPane. I am unable to refresh the data. PLease help, here is my code:
pane1:
//.. some codes...
// This is the ButtonListener
private class ButtonListener implements ActionListener
{
public void actionPerformed (ActionEvent event)
{
userInput = tf.getText(); // tf is JTextField
//System.out.println("the input is "+ finalInput);
pane2.updateData(userInput);
}
}
pane2:
public void updateData(String s){
System.out.println("Update data function is called");
labelUser.setFont(new Font("Arial", Font.BOLD, 30));
labelUser.setText("Updated text here " + s);
}
Here is my main class:
import java.awt.*;
import javax.swing.*;
public class Main {
public static Pane2 p2 = new Pane2();
public static void main(String[] args) {
JFrame f= new JFrame ("My Frame");
f.setDefaultCloseOperation (JFrame .EXIT_ON_CLOSE);
JTabbedPane tp = new JTabbedPane();
p2 = new Pane2();
tp.addTab("Pane1", new PaneFirst(p2));
tp.addTab("Pane2", new PaneSecond());
f.add(tp);
f.pack();
f.setVisible(true);
}
}
The labelUser never updates, but I trace the updateData function, its being called. Why is the text in labelUser not being updated?
EDIT:
"labelUser" come from pane2.java class.
Note: Apparently this didn't fix the problem.
One thing to try would be:
public void updateData(String s){
System.out.println("Update data function is called");
labelUser.setFont(new Font("Arial", Font.BOLD, 30));
labelUser.setText("Updated text here " + s);
repaint(); // add this line to tell your pane to repaint itself
}
There is a chance that your panel is just not getting repainted.
Might be a typo but - in actionPerformed() you store the content of the textfield in userInput but use finalInput to update pane2.