I'm writing a Java application that will have an on-screen number pad available for touch-input. Normal key input will also be available, but I'd like the keypad there for tablets and such. I've made a class that extends JPanel. It has 10 buttons laid out in the normal keypad configuration. Now I'm trying to figure out how to make it act like a regular keypad.
I just don't know how to issue KeyEvents. Here's what I've tried so far:
I tried adding a new KeyListener. In the JPanel, when a button was pressed, the action listener called a method that created a new KeyEvent and sent it to all the KeyListeners that were added to the JPanel. However, no matter how many times I added KeyListeners, the didn't seem to be any associated with the panel.
Another thing I tried was passing the target JTextField to the JPanel and setting a member object to the JTextField. But every time I try to append text to it, the member object is null. It's really perplexing to me.
I'm hoping someone could point me in the correct direction with how to implement this keypad to make it as modular is possible so it can be used inside several different screens.
Thanks in advance!
Brent
You dont need the KeyListener you can associate yourself the outcome effect of pressing a button (its not a key) on the JTextField.
Maybe something like:
New JButton button = new JButton(new KeyPressedAction(mTextField,"0"));
Where
public class KeyPressedAction extends Action{
JTextField tf;
String num;
public KeyPressedAction(JTextField textField,String num){
this.tf = textField;
this.num = num;
}
public void actionPerformed(ActionEvent e){
textField.setText(textField.getText+num);
}
}
I'm writing a Java application that
will have an on-screen number pad
available for touch-input.
So I assume that when the button is "touched" an ActionEvent will be generated. Then I assume you will want to add the character related to the button to a text field. If so, then the following examples should get you started. You don't need to generated KeyEvents, you just respond to the ActionEvents:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
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) );
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);
}
}
If that doesn't solve your problem, then you should be looking into Key Bindings instead of using KeyEvents.
Related
I am new to java and creating a Simple gui App. In this simple app, I am trying to write a e-commerce letter for Firms. So, I planned my app something like this..
First i ask to user if he want to write an letter to British Firm or American. For this i use two radio buttons(one for american firm and second for british) and JButton. When user Trigger jbutton then i want to get radiobutton command(which type of letter user want to write).
The problem is I don't have any idea to get Radiobutton command when i trigger jButton. Please give me an Simple Idea(if possible with exapmle not complicated for begginers) to get RadioButtons value..
Here is my java Code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class englet{
static public JFrame f;
static public JPanel p;
static class getTypeOfLetter implements ActionListener{
public void actionPerformed( ActionEvent e){
String btnInput = e.getActionCommand();
System.out.println(btnInput);
}
}
public static void askletter(){
JRadioButton btnRadio1;
JRadioButton btnRadio2;
ButtonGroup btngrp;
JButton btnGo = new JButton("Write");
btnRadio1 = new JRadioButton("Write Letter For American Firm");
btnRadio1.setActionCommand("Amer");
btnRadio2 = new JRadioButton("Write Letter For British Firm");
btnRadio2.setActionCommand("Brit");
btngrp = new ButtonGroup();
btnGo.setActionCommand("WriteTest");
btnGo.addActionListener(new getTypeOfLetter());
btngrp.add(btnRadio1);
btngrp.add(btnRadio2);
p.add(btnRadio1);
p.add(btnRadio2);
p.add(btnGo);
}
englet(){
f = new JFrame("English Letter");
p = new JPanel();
askletter();
f.add(p);
f.setSize(400,200);
f.setVisible(true);
}
public static void main (String[] argv ){
englet i = new englet();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
I am using Notepad++ and CMD.. Not any another tools like netbeans initllli ecplisse.
**RE-EDIT ** I want a possible solution and can satisfy me.. this app works but i am not able to get radiobuttons commmand with jubtton..
You've got several issues:
Over-use of static. Most of the fields and methods of your code should be non-static
You're missing key fields that will be necessary to transmit the information needed. To get the selected JRadioButton, you need to make JRadioButton fields and check which is selected, or (and my preference), you need to make the ButtonGroup variable a field and check which JRadioButton has been selected based on the ButtonModel returned by the ButtonGroup.
You're currently using local variables and these won't be visible throughout the class, which is why either the JRadioButtons or the ButtonModel most be fields (declared in the class).
If you go with ButtonModel above, you must give each JRadioButton an appropriate actionCommand String.
For example:
import java.awt.Component;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class GetRadio extends JPanel {
private static final String[] FIRMS = {"American Firm", "British Firm"};
// You need this field to access it in your listener
private ButtonGroup buttonGroup = new ButtonGroup();
public GetRadio() {
// create JButton and add ActionListener
JButton button = new JButton("Select");
button.addActionListener(new ButtonListener());
// JPanel with a grid layout with one column and variable number of rows
JPanel radioButtonPanel = new JPanel(new GridLayout(0, 1));
radioButtonPanel.setBorder(BorderFactory.createTitledBorder("Select Firm")); // give it a title
for (String firm : FIRMS) {
// create radiobutton and set actionCommand
JRadioButton radioButton = new JRadioButton(firm);
radioButton.setActionCommand(firm);
// add to button group and JPanel
buttonGroup.add(radioButton);;
radioButtonPanel.add(radioButton);
}
// add stuff to main JPanel
add(radioButtonPanel);
add(button);
}
private class ButtonListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
// get button model of selected radio button from ButtonGroup
ButtonModel model = buttonGroup.getSelection();
// if null, no country selected
if (model == null) {
Component component = GetRadio.this;
String message = "You must first select a country!";
String title = "Error: No Country Selected";
int type = JOptionPane.ERROR_MESSAGE;
JOptionPane.showMessageDialog(component, message, title, type);
} else {
// valid country selected
String country = model.getActionCommand();
System.out.println("Letter to " + country);
}
}
}
private static void createAndShowGui() {
GetRadio mainPanel = new GetRadio();
JFrame frame = new JFrame("Get Radio Btn");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
my program has a calculator layout, theres 9 buttons with clear , negative and convert. and 2 radio buttons that when you select one it converts the numbers you entered.
i have designed it, but im not sure how to do the action listener part.
i think i just need help starting off the code .
// import packages
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
// class
public class Lab31Panel extends JPanel implements ActionListener
{
// data declarations
private JRadioButton k2pButton;
private JRadioButton p2kButton;
private ButtonGroup weight;
private JPanel selectConversion;
private JButton jb0,jb1,jb2,jb3,jb4,jb5,jb6,jb7,jb8,jb9,jbminus,jbclear,jbconvert;
private JTextArea display;
//constructor to initiate data and set up GUI
public Lab31Panel()
{
setLayout( new BorderLayout() );
// organizing radio buttons and their behaviours
k2pButton = new JRadioButton( "Kilograms to Pounds" );
p2kButton = new JRadioButton( "Pounds to Kilograms" );
weight = new ButtonGroup();
weight.add( k2pButton );
weight.add( p2kButton );
// adding components to panel to be south of the GUI
selectConversion = new JPanel();
selectConversion.add( k2pButton );
selectConversion.add( p2kButton );
add( selectConversion, BorderLayout.SOUTH );
//setting up west area of GUI
JPanel westPanel = new JPanel();
JPanel convert = new JPanel();
// setting up components for the west of the GUI
westPanel.setLayout(new GridLayout(5,3));
westPanel.add(jb0 = new JButton("0"));
westPanel.add(jb1 = new JButton("1"));
westPanel.add(jb2 = new JButton("2"));
westPanel.add(jb3 = new JButton("3"));
westPanel.add(jb4 = new JButton("4"));
westPanel.add(jb5 = new JButton("5"));
westPanel.add(jb6 = new JButton("6"));
westPanel.add(jb7 = new JButton("7"));
westPanel.add(jb8 = new JButton("8"));
westPanel.add(jb9 = new JButton("9"));
westPanel.add(jbminus = new JButton("-"));
westPanel.add(jbclear = new JButton("clear"));
westPanel.add(jbconvert = new JButton("convert"));
add(westPanel, BorderLayout.WEST);
//setting up east components
JPanel eastPanel = new JPanel();
eastPanel.setLayout(new BorderLayout());
display = new JTextArea();
eastPanel.add(display,BorderLayout.CENTER);
add(eastPanel);
// add listeners to radio buttons
p2kButton.addActionListener(this);
k2pButton.addActionListener(this);
//add listeners to all textfields
} //end constructor
public void actionPerformed(ActionEvent e)
{
}
} // end class
Suggestions:
First and foremost, don't use the same ActionListener for all the buttons.
In that vein, don't have your program implement ActionListener.
Instead, create one ActionListener for the numeric buttons
And one or perhaps better, three, for the operations buttons.
In the numeric buttons, the code should be clear -- put the numbers into the display.
In the operations button listeners, the actions will depend on which operation was pressed.
If the convert button is pressed, then extract your numeric data from the field holding it,
Convert text to number using a parsing method.
Calculate your conversion
And then display it.
ALSO
I would not add any ActionListener to the JRadioButtons since you really don't want any action to occur when pressed.
Instead have the convert button's ActionListener check to see which JRadioButton is selected, and base the conversion equation on this selection.
Something like:
// add listeners to radio buttons // **** no, don't do this
// p2kButton.addActionListener(this);
// k2pButton.addActionListener(this);
jbclear.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// TODO code to clear the JTextField
// usually this will involve setText("")
}
});
jbconvert.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// TODO code to convert
// first get JRadioButton selection -- which one is set
// then get data from text component
// convert it to number (but catching for NumberFormatException)
// do conversion based on the selected JRadioButton
// and display usually with a call to setText(...)
}
});
I'm wondering if its possible to make a button in JButton Press a key?
So for example If I have a button titled New Button, and I click it with the mouse. I want it to press my left arrow key.
Also is it possible to make it so that it keeps pressing it until I let go of the mouse? So more or less I click it and It presses my left arrow key continuously until I release the mouse then it stops?
I click it and It presses my left arrow key continuously until I release the mouse then it stops?
What is the point of this?
If you use the keyboard to press the left arrow, the KeyStroke is dispatched to the component that has focus. So if focus is on a text field, the left arrow will move the caret back one character.
If you click on a button, focus is now on the button and if you dispatch the left arrow to the button nothing will happen.
Maybe you are trying to use the left arrow key to do some kind of animation. If so, then you need to create an Action. Then you need to add code so that a button click or the pressing of the left arrow key can invoke this Action.
For the basic concepts of this approach you can read the Swing Tutorial. There are sections on:
How to Use Actions
How to Use Key Bindings
For a working example of this approach you can check out Motion Using the Keyboard. The MotionWithKeyBindings.java code does animation using the keyboard or the button.
Are you trying to do something like this? Here is a simple "Calculator" keyboard:
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();
}
});
}
}
You click a button and the value is displayed in a text field.
Do this with the java.awt.Robot class. Do this like so:
//Creating a new robot:
Robot r = new Robot();
//Pressing a key (Put inside click handler method):
r.keyPress(KeyEvent.VK_LEFT /*VK_RIGHT, VK_TOP, and VK_BOTTOM are also acceptable.*/
//Releasing a key (Put inside release handler method):
r.keyRelease(KeyEvent.VK_LEFT /*VK_RIGHT, VK_TOP, and VK_BOTTOM are also acceptable.*/); //Release key
When doing this, you may want to hold the value of the key being pressed. Do this by defining a global variable with the KeyEvent.VK_* value, like so:
//In global space
public static /*Can be private, or protected.*/ int keyPressed = null;
//In click handler body:
keyPressed = KeyEvent.VK_LEFT /*VK_RIGHT, VK_TOP, and VK_BOTTOM are also acceptable.*/; //Set this to the value of the key you are pressing.
//In mouse release handler body:
r.keyRelease(keyPressed);
I'm programming Java with NetBeans. I have a strange problem. In a class Mouse Listener, I do getComponents of a panel, and it returns a array of components that I put(?) in one array JButton (whit cast) so..
JButton[] b= (JButton[])Main.p1.getComponents();
IDE doesn't show an error.
I do, for example:
b[0].setBackground(Color.yellow);
and in output I see an error.
But if I do
JButton b= (JButton) Main.p1.getComponents()[0];
b.setBackground(...);
And all works but I don't understand why. Can somebody explain please?
2015-01-18
Thank to all for the answer.
I want take Components of a Panel, not only for change background's color, but also for the Ordinates; I need all Buttons in a array to compare all at the same time .. Why I cant convert 'Components' in 'Buttons'? Panel has a pointer to Buttons in Ram Memory..
Patryk Dobrowolski thank's you, i try this: (i use class Button extends JButton)
Button[] button = new Button[Main.p1.getComponents().length];
for (int i = 0; i < Main.p1.getComponents().length; i++) {
button[i] = (Button) Main.p1.getComponents()[i];
}
but in output I see this error:
Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException: javax.swing.JLabel cannot be cast to Button
why JLabel?
Hovercraft Full Of Eels, thank's you for your answer, I could create an array and insert the pointer of all Button into it. But I said: JPannel has a Array where insert pointer.. I can use it. Why not?
Thank's you very much!
Alessandro Amedei
In the first case, you are lying to the compiler. By stating
JButton[] b= (JButton[])Main.p1.getComponents();
you are telling the compiler that you know that this is an array of JButtons, when in fact it really is an array of Components. Therefore you get no compile-time errors, but you do get one at runtime.
In the other case it works, since then you are telling the compiler that the Component you want to work with is a JButton, which is true.
It's because array of JComponent is not the same as array of JButton. You need to cast one by one in the loop if you want to finally get array of buttons:
JButton[] buttons = new JButton[components.length];
for (int i = 0; i < components.length; i++) {
buttons[i] = (JButton) components[i];
}
I am concerned that you are trying to extract your selected JButton by iterating through an array of components and thereby basing your program logic on the GUI component structure, which is a very fragile way to do things. If you change components around, or later decide to nest a container that holds your JButtons into another container (i.e., into another JPanel), you would have to take care to update this listener and all similar listeners, again making your code quite fragile.
Rather than do this, a better solution might be to add a listener to the individual components that need them. For instance, if you want to change the background of a JButton to yellow if a mouse is hovering over it, consider adding a ChangeListener to each JButton, extracting the involved button via the ChangeEvent's getSource() method and then testing the button's model to see if it is in a roll-over state. For example:
import java.awt.Color;
import java.awt.GridLayout;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
#SuppressWarnings("serial")
public class SetButtonBackground extends JPanel {
public static final Color ROLLOVER_COLOR = Color.yellow;
public SetButtonBackground() {
int rows = 5;
int cols = rows;
setLayout(new GridLayout(rows, cols, 5, 5));
ButtonChangeListener btnChngListener = new ButtonChangeListener();
for (int i = 0; i < rows * cols; i++) {
String text = "Button " + (i + 1);
JButton button = new JButton(text);
button.addChangeListener(btnChngListener);
add(button);
}
}
private class ButtonChangeListener implements ChangeListener {
#Override
public void stateChanged(ChangeEvent e) {
JButton btn = (JButton) e.getSource();
ButtonModel model = btn.getModel();
if (model.isRollover()) {
if (!btn.getBackground().equals(ROLLOVER_COLOR)) {
btn.setBackground(ROLLOVER_COLOR);
}
} else if (btn.getBackground().equals(ROLLOVER_COLOR)) {
btn.setBackground(null); // change back to default state
}
}
}
private static void createAndShowGui() {
SetButtonBackground mainPanel = new SetButtonBackground();
JFrame frame = new JFrame("Set Button Background");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
I've looked around quite a lot on google and followed several examples however I can't seem to get my JScrollPane working on a textarea in a JPanel.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.lang.*;
import javax.swing.event.*;
class main
{
public static void main(String Args[])
{
frame f1 = new frame();
}
}
class frame extends JFrame
{
JButton B = new JButton("B");
JButton button = new JButton("A");
JTextArea E = new JTextArea("some lines", 10, 20);
JScrollPane scrollBar = new JScrollPane(E);
JPanel grid = new JPanel ();
frame()
{
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(500,800);
setTitle("Mobile Phone App");
setLocationRelativeTo(null);
E.setLineWrap(true);
E.setEditable(false);
grid.add(button);
button.addActionListener(new action());
grid.add(B);
B.addActionListener(new action());
//grid.add(E);
grid.getContentPane().add(scrollBar);
add(grid);
setVisible(true);
}
class action implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
String V = E.getText();
if(e.getSource() == button)
{
E.setText(V + "A is pressed");
}
if(e.getSource() == B)
{
E.setText(V + "B is pressed");
}
}
}
}
Would be great if someone can see where I am going wrong. I added JscrollPane in which I added the text area "e" in it.
E.setColumns(10);
E.setRows(5);
E.setPreferredSize(new Dimension(10,5)); // delete this
Don't hardcode a preferred size. The preferred size is overriding your attempt to set the rows/columns. So get rid of that line.
Note, you can also specify the row/columns when you create the text area:
JTextArea textArea = new JTextArea(5, 10);
to provide a hint to the intial size of the text area. Now the text area can change in size as text is added or removed and the scrollbar will appear when needed.
Also follow standard java naming conventions. Variable names should NOT start with an upper case character.
Right I got it!
Basically I had to add it in differently...the way I was approaching it was wrong!
grid.add(scrollBar, BorderLayout.CENTER);