I've got the problem that I've got the regex check on an input field and if the input is not as it should be and i press tab to check and normally to move to the next element, it should stay at that current field. But because of the normal tab policy it moves to the next element and even if i request focus on the current element it still moves to the next one.
Thanks for the help beforehand :)
This is my Code snippet:
}else if(comp.getName().equals("input_dauer")){
System.out.println("Test3");
final Pattern pattern = Pattern.compile("^[\\d]{0,}[,.]+[\\d]{1,3}$");
if (!pattern.matcher(input_dauer.getText()).matches()) {
lblDauer.setForeground(Color.red);
MandatoryDauer = 0;
comboBox_aktivitaet.requestFocus();
input_dauer.requestFocus();
}
else{
lblDauer.setForeground(Color.decode("#1E2F3F"));
MandatoryDauer = 1;
textArea_beschreibung.requestFocus();
}
You may disable the focus traversal keys of the JTextField (or whatever your Componentis) with setFocusTraversalKeysEnabled(false), and manually transfer the focus when needed.
In the following example, if the text's length is less than 5 characters, it is deemed invalid so we don't transfer the focus.
If it is valid (length>=5), we transfer the focus with transferFocus() if we want to stick with the logical focus order, or requestFocus() to transfer to a particular component .
A dummy button has been added so that you can watch the focus behaviour.
JPanel contentPane = new JPanel();
JFrame fr = new JFrame();
JButton someButton = new JButton("Button");
JTextField textField = new JTextField(10);
textField.setFocusTraversalKeysEnabled(false);
textField.addKeyListener(new KeyAdapter() {
#Override
public void keyPressed(final KeyEvent ke) {
JTextField source = (JTextField) ke.getSource();
if (ke.getKeyCode() == KeyEvent.VK_TAB) {
if (source.getText().length() >= 5) {
System.out.println("Tab with valid text, transferring focus");
source.transferFocus();// or someButton.requestFocus()
} else {
System.out.println("Tab with invalid text");
}
}
}
});
contentPane.add(textField);
contentPane.add(someButton);
fr.setContentPane(contentPane);
fr.pack();
fr.setVisible(true);
Related
When I try to run this, I keep getting an empty frame that cannot be closed, and I have to terminate the program from eclipse. I am fairly certain that the problem is a result of the while loop (about 2/3 of the way down the code block), but I haven't been able to figure out a way to fix this
public Draw()
{
super( "Uno");
JMenuBar bar = new JMenuBar(); // create menu bar
JMenu gameMenu = new JMenu( "Play Game" );
JMenu quitMenu = new JMenu( "Quit" ); //Quit Program
bar.add( gameMenu ); // add Add menu to menu bar
bar.add( quitMenu ); // add quit button to menu bar
setJMenuBar( bar ); // set menu bar for this application
window = new JDesktopPane();
add(window);
gameMenu.addMouseListener(
new MouseListener()
{
public void mouseClicked(MouseEvent e)
{
Dimension size = window.getSize();
double height = size.getHeight();
double width = size.getWidth();
JInternalFrame frame = new JInternalFrame("Uno", true, true, true, true );
JFrame input = new JFrame();
input.setTitle(" ");
input.setSize(350, 155);
input.setLayout(new FlowLayout());
input.setLocationRelativeTo(null);
input.setVisible(true);
JLabel label1 = new JLabel("How many total players? (2-10)");
final JTextField text1 = new JTextField(3);
JLabel label2 = new JLabel("How many computer players? *");
final JTextField text2 = new JTextField(3);
JLabel label3 = new JLabel("* Computer players must be <= total number of players");
JButton confirm = new JButton("OK");
label1.setVisible(true);
label2.setVisible(true);
label3.setVisible(true);
text1.setVisible(true);
text2.setVisible(true);
confirm.setVisible(true);
input.add(label1);
input.add(text1);
input.add(label2);
input.add(text2);
input.add(label3);
input.add(confirm);
while(valid == false)
{
confirm.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
String players = text1.getText();
String computers = text2.getText();
int temp1 = Integer.parseInt(players);
System.out.println("Number of players = " + temp1);
int temp2 = Integer.parseInt(computers);
System.out.println("Number of computers = " + temp2);
if (temp1 >= 2 && temp1 <= 10)
if (temp2 <= temp1 && temp2 >= 0)
valid = true;
} //close actionPerformed
}); //close ActionListener
} //close while loop
} //close mouseClicked
} //close mouseListener
} //close Draw
Initially, I was having an issue where it kept infinitely drawing the frame on top of itself because the while loop kept returning false. That issue was solved by removing the components from the while loop, and placing them before it as they are above. Now when I run it, all I get is this: picture
The goal of this program is to make an Uno game, but the first step is to determine the number of players. This is the only way I know how to do this, and this is only the second program I have done with graphics, so I am by no means an expert at Java. I will appreciate any help I can get because I have been stuck for a few days now.
The problem is that you are not giving the event handlers any chance to do their job. Your while loop continually creates event handlers. However, the actionPeformed() method can never be called because the while loop has control of the CPU and the button will not respond to any clicks.
I suggest that you learn a bit more about event handling. You will need to redesign your code in order to get the behavior you wish. Most likely you need to remove the while loop entirely and just create an event handler which will execute code when the button is clicked.
For future reference:
In general, checking equality with a boolean value is unnecessary. The result of == is a bool, but the variable you are checking is already a bool. So use it directly: instead of while (valid == false), you can do while (!valid). If you read the ! as "not", this actually makes a lot of sense.
In this case, the point is moot, since you need to remove the while loop entirely. However, this might be useful information for you some time in the future.
Simplified: How to make String value to call specific existed JButton variable name in java?
I'm trying to make a non-ordinary Tic-Tac-Toe game...
Anyway, what I will post here is not really the whole concept of that. I just want to make it simple: I have 9 square jButtons named (3 by 3) (and maybe allow user to make 4x4, 5x5, 10x10 etc. via settings in future):
[markbox_00_00] / [markbox_00_01] / [markbox_00_02]
[markbox_01_00] / [markbox_01_01] / [markbox_01_02]
[markbox_02_00] / [markbox_02_01] / [markbox_02_02]
[btnSave] / [btnUndoActions]
where the first two digit represent the row and the next two is the column; and a save button (btnSave) and undo button(btnUndoActions).
Each markbox have default spring value of "0", when I click it turns "1"; and when I click "1" it turns "0". When you press undo button it will reset to last save.
Here is some of my simplified line of codes:
private byte markboxColLimit = 3, markboxRowLimit = 3, row, col;
private byte[][] saveNumber = new byte[markboxRowLimit][markboxColLimit];
private String buttonName;
public Astral_TicTacToe() {
initComponents();
/* I want something like this, but using a for loop based on markboxColLimit and
markboxRowLimit as limits */
markbox_00_00.setText("0");
markbox_00_01.setText("0");
markbox_00_02.setText("0");
markbox_01_00.setText("0");
markbox_01_01.setText("0");
markbox_01_02.setText("0");
markbox_02_00.setText("0");
markbox_02_01.setText("0");
markbox_02_02.setText("0");
/* I know the line below is wrong... what I'm trying is to avoid
* repetitiveness by looping and dynamically calling the variable
* name of JButtons, or in other ways...
*/
/* Attempting to make an alternative code from above (trying to make a loop instead) */
for(row = 0; row < markboxRowLimit; row++){
for(col = 0; col < markboxColLimit; col++){
buttonName = "markbox_0" + Byte.toString(row) + "_0" + Byte.toString(col);
buttonName.setText("0");
}
}
}
private void btnUndoActionsActionPerformed(java.awt.event.ActionEvent evt) {
markbox_00_00.setText(Byte.toString(saveNumber[0][0]));
markbox_00_01.setText(Byte.toString(saveNumber[0][1]));
markbox_00_02.setText(Byte.toString(saveNumber[0][2]));
markbox_01_00.setText(Byte.toString(saveNumber[1][0]));
markbox_01_01.setText(Byte.toString(saveNumber[1][1]));
markbox_01_02.setText(Byte.toString(saveNumber[1][2]));
markbox_02_00.setText(Byte.toString(saveNumber[2][0]));
markbox_02_01.setText(Byte.toString(saveNumber[2][1]));
markbox_02_02.setText(Byte.toString(saveNumber[2][2]));
}
private void btnSaveActionPerformed(java.awt.event.ActionEvent evt) {
saveNumber[0][0] = Byte.parseByte(markbox_00_00.getText());
saveNumber[0][1] = Byte.parseByte(markbox_00_01.getText());
saveNumber[0][2] = Byte.parseByte(markbox_00_02.getText());
saveNumber[1][0] = Byte.parseByte(markbox_01_00.getText());
saveNumber[1][1] = Byte.parseByte(markbox_01_01.getText());
saveNumber[1][2] = Byte.parseByte(markbox_01_00.getText());
saveNumber[2][0] = Byte.parseByte(markbox_02_00.getText());
saveNumber[2][1] = Byte.parseByte(markbox_02_01.getText());
saveNumber[2][2] = Byte.parseByte(markbox_02_02.getText());
}
private void markbox_00_00ActionPerformed(java.awt.event.ActionEvent evt) {
if("0".equals(markbox_00_00.getText()))
markbox_00_00.setText("1");
else
markbox_00_00.setText("0");
}
private void markbox_00_01ActionPerformed(java.awt.event.ActionEvent evt) {
if("0".equals(markbox_00_01.getText()))
markbox_00_00.setText("1");
else
markbox_00_00.setText("0");
}
....
private void markbox_02_02ActionPerformed(java.awt.event.ActionEvent evt) {
if("0".equals(markbox_00_00.getText()))
markbox_02_02.setText("1");
else
markbox_02_02.setText("0");
}
In short: how can I make String a specific variable name of JButton for calling/accessing/editing for their properties?
Example:
buttonName = markbox_01_02;
buttonName.setText("2");
is equavalent to markbox_01_02.getText("2");
I really appreciate the help, thank you...
P.S. I use to make JFrame in NetBeans Design (just click and drag the objects in palette window like JPanel, JButton, etc., so I don't type the code manually except making my own logical Method).
You probably need to redo your program and rephrase your question because it's kind of unclear where you're stuck that's why I wrote this answer as a Community Wiki.
The following program creates a GridLayout for the board and add 2 JButtons below it which contain "Save" and "Undo" buttons.
Whenever you press a button it will change it's text to 0 or 1 depending on the previous state of the button, and "Undo" button will undo last clic the same way, if it was 0 it will become 1 and viceversa.
I guess you should read How to write an ActionListener before copy-pasting this example, understand what it says and try to understand how this program works.
The logic to "Save" button is up to you 'cause I'm not sure what you wanna do there and I'm not gonna write all the code for you. This is made only for you to get an idea on how to handle events.
Also, the logic to end the game is left to you for the same reasons as the "Save" button.
I wish I knew how to record my screen in Ubuntu and save as GIF but here's a screenshot on how this program looks like:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class TicTacToe implements ActionListener {
JFrame frame;
JButton buttons[];
JPanel pane, buttonPane;
boolean pressed[];
JButton save, undo;
int n = -1;
public void actionPerformed(ActionEvent e) {
for (int i = 0; i < buttons.length; i++) {
if(e.getSource() == buttons[i]) {
pressed[i] = !pressed[i];
buttons[i].setText(pressed[i] ? "1" : "0");
n = i;
break;
}
}
}
public TicTacToe () {
frame = new JFrame("Tic Tac Toe Game");
buttons = new JButton[9];
pane = new JPanel(new GridLayout(3, 3));
pressed = new boolean[9];
buttonPane = new JPanel(new FlowLayout());
save = new JButton("Save");
undo = new JButton("Undo");
for (int i = 0; i < buttons.length; i++) {
buttons[i] = new JButton("0");
pressed[i] = false;
}
for (JButton b : buttons) {
b.addActionListener(this);
pane.add(b);
}
undo.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
if (n == -1) {
return;
}
pressed[n] = !pressed[n];
buttons[n].setText(pressed[n] ? "1" : "0");
}
});
buttonPane.add(save);
buttonPane.add(undo);
frame.add(pane, BorderLayout.PAGE_START);
frame.add(buttonPane, BorderLayout.CENTER);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public static void main (String args[]) {
new TicTacToe();
}
}
I have a keypad made up of jbuttons and a jtextfield that has an action listener. When I press the button the number shows in the textfield but the next number overwrites it. Could anyone tell me how to append the text to the length 13 numbers and when it get's there to carriage return.
If I use the keyboard to enter numbers I can enter a String of numbers but not from the buttons.
I am using:
JButton buttonNo2 = new JButton("2");
buttonNo2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
textfield.setText("2");
}
buttonNo1.setBounds(11, 18, 50, 50);
keyboardPanel.add(buttonNo2);
buttonNo1.setForeground(Color.BLUE);
buttonNo1.setFont(new Font("Perpetua", Font.BOLD, 20));
Try using something like
textfield.setText(textfield.getText() + "2");
instead of textfield.setText("2");
setText does just that, sets the text of the text field to the value you specified.
Also buttonNo1.setBounds(11, 18, 50, 50); looks like you're trying to do without a layout manager. Avoid using null layouts, pixel perfect layouts are an illusion within modern ui design. There are too many factors which affect the individual size of components, none of which you can control. Swing was designed to work with layout managers at the core, discarding these will lead to no end of issues and problems that you will spend more and more time trying to rectify
You could also make it much simpler for yourself, and use the Action API instead, which would save you a not lot of repeated typing...
public class NumberAction extends AbstractAction {
private JTextField field;
private int number;
public NumberAction(JTextField field, int number) {
this.field = field;
this.number = number;
putValue(NAME, Integer.toString(number));
}
#Override
public void actionPerformed(ActionEvent e) {
Document doc = field.getDocument();
try {
doc.insertString(doc.getLength(), Integer.toString(number), null);
} catch (BadLocationException ex) {
ex.printStackTrace();
}
}
}
Then you would just need to add each button as required...
add(new JButton(new NumberAction(textfield, 1)));
add(new JButton(new NumberAction(textfield, 2)));
add(new JButton(new NumberAction(textfield, 3)));
See How to Use Actions for more details
You have to get the text first and set the text by appending the previous and current text.
public void actionPerformed(ActionEvent e) {
String str = textfield.getText();
textfield.setText(str+the number printed);
}
As #MadProgrammer already posted How to achieve it with JTextField ,
You can opt for JTextArea#append method
public void append(String str)
Appends the given text to the end of the document. Does nothing if the
model is null or the string is null or empty.
Parameters:
str - the text to insert
I am writing a Blackjack program using JFrame and trying to keep it as simple as possible. My JButton, jbHit works with a single click, however it overwrites the playersHand and playerSide slot with every click. I would like it to work with multiple clicks (3 clicks - since that is the max number of cards you can get after the first two are dealt) options It should count them so to speak so that the array index can record the card image. Here is my ActionListener code that I have so far. I am afraid I am stuck. Should I use some sort of for loop with an int i++?
//Hit Button ActionListener
jbHit.addActionListener( new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if ( playerValue < 21 ) {
//Draw a card
Card c = deck.drawCard();
playersHand.add(c);
playerSide[2].setIcon( new ImageIcon( c.getFilename() ) );
}
//If playerValue > 21, bust
else if ( playerValue > 21 ) {
//Toggle Buttons
jbDeal.setEnabled(true);
jbHit.setEnabled(false);
jbStand.setEnabled(false);
jbDoubleDown.setEnabled(false);
message = "You bust.";
}
}
});
You could create an array of "action commands" and every time you click the button, the action command changes to the next. If you reach the end, set the index back to zero. Perhaps something like this:
public static void main(String[] args)
{
JFrame frame = new JFrame();
JPanel panel = new JPanel();
JButton button = new JButton("Action");
String[] commands = {"command1", "command2", "command3"};
button.setActionCommand(commands[0]);
button.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
JButton btn = (JButton)e.getSource();
String cmd = btn.getActionCommand();
System.out.println("Command: " + cmd);
if(cmd.equals("command1"))
{
btn.setActionCommand(commands[1]);
System.out.println("Command 1 was pressed");
}
else if(cmd.equals("command2"))
{
btn.setActionCommand(commands[2]);
System.out.println("Command 2 was pressed");
}
else if(cmd.equals("command3"))
{
btn.setActionCommand(commands[0]);
System.out.println("Command 3 was pressed");
}
else
System.out.println("Something went wrong!");
}
});
panel.add(button);
frame.add(panel);
frame.setSize(200, 200);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
If you are using Java 7 or later, you can replace the if/else with a Switch statement.
I believe you're looking for a logical flag based on an integer, for example:
if(cardsDealt < 3) {
// DoThings();
} else {
return;
}
Which would require you to do
cardsDealt++;
at the bottom of your button click handle.
If this is not what you're asking, please re-explain the question.
It sounds like you might be a little confused about how jbHit will be called. Realize that it will be called one complete time every time the mouse is clicked. It's not like it inherently knows that it is on the second or third click. Add a class member like int clickCount; that you increment at the appropriate point inside of jbHit. Then you can alter your method's response depending on the value of clickCount.
So I'm trying to write a JButton that will act like an enter key when pressed. It must be able to fool a JTextField that is in focus into calling its action listeners. It can not use the robot framework, because that will make every program think enter is pressed, which is a problem.
Here is the backstory:
I have a program (written in Swing) which allows someone to enter data in many textfields and other things by hitting enter after typing in the data. It works great.
However, most people that use it are using a second program at the same time which automatically listens for an enter key and shuts off a robot (for those of you who are familiar with FIRST robotics, I'm talking about the SmartDashboard and the Driver Station). There have been quite a few complaints about this. People want to enter data without disabling the robot. As it turns out, the SmartDashboard (the program people want to hit enter on) allows custom swing components to be run along with it.
not entirely sure if I understand your requirement correctly (will delete this if not) ...
You can manually dispatch an event to whatever component you want to address. In the case of wanting to dispatch to the focusOwner
find the focusOwner by querying the KeyboardFocusManager
create a keyEvent with the focusOwner as sender
dispatch that event to the focusOwner
Something like:
Action action = new AbstractAction("fake enter") {
#Override
public void actionPerformed(ActionEvent e) {
KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
Component comp = manager.getFocusOwner();
KeyEvent event = new KeyEvent(comp,
KeyEvent.KEY_PRESSED, System.currentTimeMillis(), 0,
KeyEvent.VK_ENTER, KeyEvent.CHAR_UNDEFINED);
comp.dispatchKeyEvent(event);
}
};
JButton button = new JButton(action);
button.setFocusable(false);
Action textAction = new AbstractAction("text") {
#Override
public void actionPerformed(ActionEvent e) {
LOG.info("I'm the text action" + ((Component) e.getSource()).getName());
}
};
JComponent comp = Box.createVerticalBox();
for (int i = 0; i < 5; i++) {
JTextField field = new JTextField(20);
field.setName(": " + i);
field.setAction(textAction);
comp.add(field);
}
comp.add(button);
Edit
added some lines for actually playing with it (#Joe commented it's not working). Clicking the button triggers the action of the focused textField (here simply prints out the field's name) Local context is vista and jdk6u27.
You might try getRootPane().setDefaultButton() on the frame. There's an example here.
Grabbing the element with the focus and manually dispatching an enter event didn't quite work, but because I just wanted to effect various JTextField, I came up with a similar solution:
addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
if (focusOwner instanceof JTextField) {
((JTextField) focusOwner).postActionEvent();
}
}
});
Thanks for pointing me in the right direction.