How to keep Focus on JTextField while clicking input number buttons? - java

I am new to GUI stuff and am having trouble with the following problem. I have 3 JTextFields, credit card number, expiration date, and security number. I am able to input information into the fields. I also implemented the focus listener for each button. If I click it, it says gained focus, if I click anywhere else, it loses focus. Under these text fields, I have a number pad (touch screen/mouse click) to enter the numbers. How do I keep focus on that particular text field until ONLY and SPECIFICALLY one of the other two textfields are clicked? The textfield that currently has focus will lose focus once I try to click to input numbers. I don't want this to happen. I searched online and wasn't able to find something specific to my case. Any help or tips would be appreciated.

myJButton.setFocusable(false);
or if a bunch of buttons held in an allMyButtons collection:
for (JButton button: allMyButtons) {
button.setFocusable(false);
}
That's it.

In additions to #Hovercrafts suggestion (+1) you will probably want to extend TextAction for the logic to insert the number into the text field. The TextAction gives you access to the last text field that had focus so the insertion code becomes very generic:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.text.*;
public class NumpadPanel extends JPanel
{
public NumpadPanel()
{
setLayout( new BorderLayout() );
JTextField textField1 = new JTextField(4);
JTextField textField2 = new JTextField(2);
JTextField textField3 = new JTextField(2);
JPanel panel = new JPanel();
panel.add( textField1 );
panel.add( textField2 );
panel.add( textField3 );
add(panel, BorderLayout.PAGE_START);
Action numberAction = new TextAction("")
{
#Override
public void actionPerformed(ActionEvent e)
{
JTextComponent textComponent = getFocusedComponent();
if (textComponent != null)
textComponent.replaceSelection(e.getActionCommand());
}
};
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout( new GridLayout(0, 5) );
add(buttonPanel, BorderLayout.CENTER);
for (int i = 0; i < 10; i++)
{
String text = String.valueOf(i);
JButton button = new JButton( text );
button.addActionListener( numberAction );
button.setMargin( new Insets(20, 20, 20, 20) );
button.setFocusable( false );
buttonPanel.add( button );
}
// Optionally auto tab when text field is full
//SizeDocumentFilter sf = new SizeDocumentFilter();
//sf.installFilter(textField1, textField2, textField3);
}
private static void createAndShowUI()
{
JFrame frame = new JFrame("Numpad Panel");
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.add( new NumpadPanel() );
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible(true);
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowUI();
}
});
}
}
You might also want to consider using Text Field Auto Tab so focus moves from text field to text field as the text field becomes full.

Related

How to make a new line in flow layout [duplicate]

I am trying to set my JTextArea to take up the max horz length of the screen, so that the next thing, in this case a button, will start on a new line, but I have no clue how to do it. I have messed around by setting the size of the JTextArea to change from, say, 20 to 1000 but that does not do anything.
How can I get my textarea to take up the entire first row and then have the next item that I add to begin on the following row? Here is what I have so far...
MyFrame(){//constructor
super("Simple Calculator");
p = new JPanel();
grid = new GridLayout(4, 4, 3, 3);
p.setLayout(grid);
setSize(400, 500);
setResizable(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setUpTextScreen();
//create buttons
for(int i = 0; i < buttonValues.length; i++){
p.add(new JButton(buttonValues[i]));
}
add(p);
setVisible(true);
}
private void setUpTextScreen() {
textOnScreen = new JTextArea(7, 1000);
textOnScreen.setText("0");//default
textOnScreen.setEditable(false);
p.add(textOnScreen);
}
How can I get my textarea to take up the entire first row and then have the next item that I add to begin on the following row?
Break your layout up into logical pieces. Start with your main panel using a BorderLayout.
First I would use a JTextField for the calculator display, not a JTextArea. Then you can add the text field using: mainPanel.add(textField, BorderLayout.PAGE_START);
Then you create a JPanel using a GridLayout for the buttons. Then you add the buttons to the button panel and use: maonPanel.add(buttonPanel, BorderLayout.CENTER);
For example:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
public class CalculatorPanel extends JPanel
{
private JTextField display;
public CalculatorPanel()
{
Action numberAction = new AbstractAction()
{
#Override
public void actionPerformed(ActionEvent e)
{
// display.setCaretPosition( display.getDocument().getLength() );
display.replaceSelection(e.getActionCommand());
}
};
setLayout( new BorderLayout() );
display = new JTextField();
display.setEditable( false );
display.setHorizontalAlignment(JTextField.RIGHT);
add(display, BorderLayout.NORTH);
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout( new GridLayout(0, 5) );
add(buttonPanel, BorderLayout.CENTER);
for (int i = 0; i < 10; i++)
{
String text = String.valueOf(i);
JButton button = new JButton( text );
button.addActionListener( numberAction );
button.setBorder( new LineBorder(Color.BLACK) );
button.setPreferredSize( new Dimension(30, 30) );
buttonPanel.add( button );
InputMap inputMap = button.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
inputMap.put(KeyStroke.getKeyStroke(text), text);
inputMap.put(KeyStroke.getKeyStroke("NUMPAD" + text), text);
button.getActionMap().put(text, numberAction);
}
}
private static void createAndShowUI()
{
JFrame frame = new JFrame("Calculator Panel");
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.add( new CalculatorPanel() );
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible(true);
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowUI();
}
});
}
}
Hava a look at Nested layouts, you can add one panel with a BorderLayout (there are other options too though) and add the textarea to it. Then you only need one more panel with a GridLayout that displays the buttons. This is an example: (Note that a few lines are unnecessary in this code, but they help understand layouts)
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.border.LineBorder;
public class Example extends JFrame {
Example() {//
super("Simple Calculator");
// The Main Panel where the 2 other panels will be on
JPanel mainPanel = new JPanel(new BorderLayout());
// The textarea will be inside this panel
JPanel areaPanel = new JPanel(new BorderLayout());
JTextArea area = new JTextArea(
"This is a JTextArea -Long text to show it works -Long text to show it works- -Long text to show it works- -Long text to show it works- -Long text to show it works- -Long text to show it works-");
area.setBorder(new LineBorder(Color.BLACK));
area.setWrapStyleWord(true);
area.setLineWrap(true);
// Fill the whole space of the panel with the area
areaPanel.add(area, BorderLayout.CENTER);
// The buttons will be inside this panel
JPanel buttonPanel = new JPanel(new GridLayout(4, 4, 3, 3));
for (int i = 0; i < 16; i++) { // Adding buttons
buttonPanel.add(new JButton("Button" + i));
}
// The textarea-panel should be on top of the main panel
mainPanel.add(areaPanel, BorderLayout.NORTH);
// The panel with the buttons should fill the remaining space
mainPanel.add(buttonPanel, BorderLayout.CENTER);
getContentPane().add(mainPanel);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(500, 500);
setVisible(true);
}
public static void main(String[] args) {
new Example();
}
}
You can also use html tags like:
JButton button = new JButton("<html><b><u>T</u>wo</b><br>lines</html>");
Or in any other JComponent like you got.
So you can use <BR> tag you achieve your need.

Individual class for each Action Listener?

My application has 15 different buttons and I've been wondering if it's a good idea to have a individual class for each button listener?
I currently have only one class that handles all buttons using switch/case but it's hard to maintain and read.
I'm not huge fan of using anonymous classes - again because of the readability.
Any suggestions that can help me resolve this issue would be appreciated.
I'm using Java Swing if this matters.
You can use one class but it is not a good dsign because you need to apply a principle of separation of concerns. You want coherance in a class so that the methods are meaningfull and logical according to the business domain your are dealing with. Also in some cases the same action listener can handle many buttons.
Example: assuming I am building a calculator. I know that the behavior of operators is similar when they are clicked on. And so is it with the digits buttons. Therefore I can have some classes, let's say
public class OperationActionListener {
public void actionPerformed(ActionEvent e) {
// Handle what happens when the user click on +, -, * and / buttons
}
}
public class DigitActionListener {
public void actionPerformed(ActionEvent e) {
// Handle what happens when the user click on a digit button
}
}
etc.
Now in my user interface I will add an instance of the same action listener
JButton buttonPlus = new JButton("+")
JButton buttonMinus = new JButton("-");
...
JButton buttonOne = new JButton("1");
JButton buttonTwo = new JButton("2");
...
OperationActionListener operationListener = new OperationActionListener();
DigitActionListener digitListener = new DigitsActionListener();
buttonPlus.addActionListener(operationListener);
buttonMinus.addActionListener(operationListener);
....
buttonOne.addActionListener(digitListener);
buttonTwo.addActionListener(digitListener);
....
Hope this helps.
Here is an example of the same listener being used by multiple buttons:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
public class CalculatorPanel extends JPanel
{
private JTextField display;
public CalculatorPanel()
{
Action numberAction = new AbstractAction()
{
#Override
public void actionPerformed(ActionEvent e)
{
// display.setCaretPosition( display.getDocument().getLength() );
display.replaceSelection(e.getActionCommand());
}
};
setLayout( new BorderLayout() );
display = new JTextField();
display.setEditable( false );
display.setHorizontalAlignment(JTextField.RIGHT);
add(display, BorderLayout.NORTH);
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout( new GridLayout(0, 5) );
add(buttonPanel, BorderLayout.CENTER);
for (int i = 0; i < 10; i++)
{
String text = String.valueOf(i);
JButton button = new JButton( text );
button.addActionListener( numberAction );
button.setBorder( new LineBorder(Color.BLACK) );
// button.setPreferredSize( new Dimension(50, 50) );
buttonPanel.add( button );
InputMap inputMap = button.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
inputMap.put(KeyStroke.getKeyStroke(text), text);
inputMap.put(KeyStroke.getKeyStroke("NUMPAD" + text), text);
button.getActionMap().put(text, numberAction);
}
}
private static void createAndShowUI()
{
UIManager.put("Button.margin", new Insets(10, 10, 10, 10) );
JFrame frame = new JFrame("Calculator Panel");
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.add( new CalculatorPanel() );
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible(true);
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowUI();
}
});
}
}

Clear current FocusOwner (jTextfield)

Developing an application in swing, just a little query :-
I want to clear the current focus owner textfield using a button. It is possible to determine whether a textfield is the current focus owner or not using isFocusOwner() but how to clear the textfield which is currently on focus?
Thanks!!!
You might be able use a TextAction. A TextAction has access to the last text component that had focus. So then in the text action you just clear the text in the component. All the logic is fully contained in the one place.
Here is an example that demonstrates the concept of using a TextAction. In this case the number represented by the button is appended to the text field with focus:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.text.*;
public class NumpadPanel extends JPanel
{
public NumpadPanel()
{
setLayout( new BorderLayout() );
JTextField textField1 = new JTextField(4);
JTextField textField2 = new JTextField(2);
JTextField textField3 = new JTextField(2);
JPanel panel = new JPanel();
panel.add( textField1 );
panel.add( textField2 );
panel.add( textField3 );
add(panel, BorderLayout.PAGE_START);
Action numberAction = new TextAction("")
{
#Override
public void actionPerformed(ActionEvent e)
{
JTextComponent textComponent = getFocusedComponent();
if (textComponent != null)
textComponent.replaceSelection(e.getActionCommand());
}
};
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout( new GridLayout(0, 5) );
add(buttonPanel, BorderLayout.CENTER);
for (int i = 0; i < 10; i++)
{
String text = String.valueOf(i);
JButton button = new JButton( text );
button.addActionListener( numberAction );
button.setMargin( new Insets(20, 20, 20, 20) );
button.setFocusable( false );
buttonPanel.add( button );
}
}
private static void createAndShowUI()
{
JFrame frame = new JFrame("Numpad Panel");
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.add( new NumpadPanel() );
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible(true);
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowUI();
}
});
}
}
In your case instead of using the replaceSelection() method you would just use the setText() method.
If you want to clear a textfield using the clicking of a button, you have to write the code to clear the textfield in the the ActionListener class's ActionPerformed method. This method is called when the button is pressed. But in order to press the button you have to get the focus from other component to this button. So in the method ActionPerformed you would get false to textField.isFocusOwner().
My suggestion to overcome this problem is:
add focus listeners to these 6 text fields.
declare a variable say lastFocused as type JTextField in initialise it to null in the Class that you are implementing all these.
write the following code to the focusListerners Overridden methods
void focusGained(FocusEvent e){
lastFocused = (JTextField) e.getComponent();
}
void focusLost(FocusEvent e){
lastFocused = null;
}
now in the ActionListener overridden method write the following:
void actionPerformed(ActionEvent e){
if(lastFocused != null){
lastFocused.setText("");
}
}
I feel this should solve your problem.

How to display a JButton and give it functionality?

Two questions.
Firstly I'm trying to display a JButton on a JFrame, so far I've managed to display the JFrame with nothing on it.
Secondly how would one add functionality to a button? Would you pass it a method?
Any feedback is appreciated.
<code>
//imports SWING etc...
//global variables...
public class FahrenheitGUI {
public static void main(String args[]){
prepareGUI();
}
private static void prepareGUI(){
JFrame frame = new JFrame("Temp");
JPanel panel = new JPanel();
JLabel temperatureLabel;
int h = 300; int w = 300;
frame.setSize(h,w);
JButton one = new JButton( "0" );
JButton two = new JButton( "1" );
JButton three = new JButton( "2" );
JButton four = new JButton( "3" );
JButton five = new JButton( "4" );
JButton six = new JButton( "5" );
JButton seven = new JButton( "6" );
JButton eight = new JButton( "7" );
JButton nine = new JButton( "8" );
JButton ten = new JButton( "9" );
JButton negative = new JButton( "-" );
JButton dot = new JButton( "." );
JButton reset = new JButton( "reset" );
one.setBounds(10,10,20,20);
//one.addActionListener(onButtonPress);
//creates an error
frame.setVisible(true);
}
}
class Keypad implements ActionListener{
public void actionPerformed( ActionEvent one){
// guessing
}
public void actionPerformed( ActionEvent two){
// guessing
}
}
You could create JPanel, add buttons to your panel and then and the whole panel to your JFrame like this:
JPanel panel = new JPanel(); //by default it will has FlowLayout
panel.add(yourButton);
frame.add(yourJPanel);
frame.setVisible(true);
Personally I create class that extends JPanel, and inside of it I set size for panel (not for frame) and then, after adding panel to my frame I call pack() method which will resize your frame in reference of the size of your panel.
If you want to change default layout manager just call setLayout(LayoutManager)
Edit:
If you want to add functionality to your button just use:
yourButton.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
//button logic
}
});
call frame.add(Button) for each button. Afterwards frame.pack() once.

jbutton changes text of text field

I am simply trying to make an employee clock. I have a keypad of numbers 0-9 and a text field. I want to be able to click the numbers and the numbers will appear on the text field. This seems so easy but I can't find any answers for it.
I'm using netbeans and I created the design of the Jframe in the Design.
I added action events to all of the buttons.
I'm calling each button like Btn0 (the button with 0 on it, Btn1, etc etc.
You need to retrieve the JButton on which ActionEvent is fired and then append the text retrieved from the JButton to the JTextField. Here is the short Demo:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class EClock extends JFrame
{
JTextField tf;
public void createAndShowGUI()
{
setTitle("Eclock");
Container c = getContentPane();
tf = new JTextField(10);
JPanel cPanel = new JPanel();
JPanel nPanel = new JPanel();
nPanel.setLayout(new BorderLayout());
nPanel.add(tf);
cPanel.setLayout(new GridLayout(4,4));
for (int i =0 ; i < 10 ; i++)
{
JButton button = new JButton(String.valueOf(i));
cPanel.add(button);
button.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent evt)
{
String val = ((JButton)evt.getSource()).getText();
tf.setText(tf.getText()+val);
}
});
}
c.add(cPanel);
c.add(nPanel,BorderLayout.NORTH);
setSize(200,250);
setLocationRelativeTo(null);
setResizable(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
EClock ec = new EClock();
ec.createAndShowGUI();
}
});
}
}
Add action listener on your button first (double click on button in GUI Designer :) ):
button.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
//Set text by calling setText() method for your textfield
textfield.setText("Desired text");
}
});
Regards.
Create an Action that can be shared by all the buttons. Something like:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
public class ButtonCalculator extends JFrame implements ActionListener
{
private JButton[] buttons;
private JTextField display;
public ButtonCalculator()
{
display = new JTextField();
display.setEditable( false );
display.setHorizontalAlignment(JTextField.RIGHT);
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout( new GridLayout(0, 5) );
buttons = new JButton[10];
for (int i = 0; i < buttons.length; i++)
{
String text = String.valueOf(i);
JButton button = new JButton( text );
button.addActionListener( this );
button.setMnemonic( text.charAt(0) );
button.setBorder( new LineBorder(Color.BLACK) );
buttons[i] = button;
buttonPanel.add( button );
}
getContentPane().add(display, BorderLayout.NORTH);
getContentPane().add(buttonPanel, BorderLayout.SOUTH);
setResizable( false );
}
public void actionPerformed(ActionEvent e)
{
JButton source = (JButton)e.getSource();
display.replaceSelection( source.getActionCommand() );
}
public static void main(String[] args)
{
ButtonCalculator frame = new ButtonCalculator();
frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible(true);
}
}
I know nothing of netbeans, however, a search on google gave me this
Netbeans GUI Functionality
it seems to have the data needed, give it a read and no doubt you can figure out what needs to be amended for it to suit your purposes

Categories

Resources