Как принять ввод с клавиатуры наряду с вводом от JButtons?
Я создал калькулятор, чтобы помочь мне практиковать создание GUI, так как я новичок в этом. До сих пор это работает идеально. Пользователь нажимает на кнопку для соответствующего номера / операции, которую он желает. Однако я хотел бы добавить еще одну функцию, которая позволяет пользователю использовать свою клавиатуру в качестве дополнительного источника ввода. Глядя на примеры Кейлистеров, кажется, что это может быть полезно...но я не могу придумать простой способ использовать его для осуществления своей идеи.
public class Calculator extends JFrame {
private ArrayList<JButton> numbers; // holds numerical buttons
private ArrayList<JButton> operations; // holds math operation buttons
private ArrayList<JButton> aux; // holds equals, clear and delete buttons
private JTextField answerField; // text field which displays current operands/answer
// panels for numerical, math operation and auxillary buttons
private JPanel numberPanel, functionPanel, answerPanel;
private double op1, op2; // numerical value of each operand
private String op1Str, op2Str; // current String value of each operand
private String operation; // current math operation
// true if value is set, false if not
private boolean op1HasValue, op2HasValue, operationHasValue;
private String answer; // holds current equation
public Calculator()
{
super("Java Calculator");
setLayout(new GridLayout(1, 3));
op1HasValue = op2HasValue = operationHasValue = false;
answer = "";
op1Str = "";
op2Str = "";
//create panels
numberPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
functionPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
answerPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
//add number buttons to panel
numbers = new ArrayList<>();
for(int i = 0; i < 10; i++)
{
numbers.add(new JButton("" + i));
numberPanel.add(numbers.get(i));
}
// also add decimal point button
numbers.add(new JButton("."));
numberPanel.add(numbers.get(10));
// add function buttons to panel
operations = new ArrayList<>();
operations.add(new JButton("+"));
operations.add(new JButton("-"));
operations.add(new JButton("*"));
operations.add(new JButton("/"));
for(JButton button: operations)
functionPanel.add(button);
// add auxillary buttons to panel
aux = new ArrayList<>();
aux.add(new JButton("u21D0"));
aux.add(new JButton("Clr"));
aux.add(new JButton("="));
for(JButton button: aux)
functionPanel.add(button);
// add text field to panel
answerField = new JTextField(15);
answerField.setEditable(false);
answerPanel.add(answerField);
add(numberPanel);
add(functionPanel);
add(answerPanel);
// add button listeners
myHandler handler = new myHandler();
for(JButton button: numbers)
button.addActionListener(handler);
for(JButton button: operations)
button.addActionListener(handler);
for(JButton button: aux)
button.addActionListener(handler);
}
private class myHandler implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
if((event.getActionCommand()).equals("Clr"))
{
op1HasValue = op2HasValue = operationHasValue = false;
op1Str = "";
op2Str = "";
operation = "";
answer = "";
answerField.setText("");
}
else if((event.getActionCommand()).equals("u21D0"))
{
if(!operationHasValue)
{
if(!op1Str.isEmpty())
{
op1Str = op1Str.substring(0, op1Str.length() - 1);
answer = answer.substring(0, answer.length() - 1);
if(op1Str.isEmpty())
op1HasValue = false;
answerField.setText(answer);
}
}
else if(operationHasValue && !op2HasValue)
{
operation = "";
operationHasValue = false;
answer = answer.substring(0, answer.length() - 3);
answerField.setText(answer);
}
else
{
op2Str = op2Str.substring(0, op2Str.length() - 1);
answer = answer.substring(0, answer.length() - 1);
if(op2Str.isEmpty())
op2HasValue = false;
answerField.setText(answer);
}
} // wait for integer input event, add integer to operand #1
else if((!op1HasValue || !operationHasValue) && (numbers.contains((JButton)event.getSource())))
{
answer = answer + event.getActionCommand();
answerField.setText(answer);
op1Str = op1Str + event.getActionCommand();
op1HasValue = true;
} // wait for operation input event, save operand #1
else if(!operationHasValue && op1HasValue && operations.contains((JButton)event.getSource()))
{
op1 = Double.parseDouble(op1Str);
answerField.setText(answer + " " + event.getActionCommand() + " ");
answer = answer + " " + event.getActionCommand() + " ";
operation = event.getActionCommand();
operationHasValue = true;
} // wait for integer input event, add integer to operand #2
else if(operationHasValue && numbers.contains((JButton)event.getSource()))
{
answer = answer + event.getActionCommand();
answerField.setText(answer);
op2Str = op2Str + event.getActionCommand();
op2HasValue = true;
} // wait for equals sign input event, save operand #2, calculate answer
else if(op1HasValue && op2HasValue && operationHasValue && (event.getActionCommand()).equals("="))
{
op2 = Double.parseDouble(op2Str);
if(operation.equals("+"))
answerField.setText("" + (op1 + op2));
else if(operation.equals("-"))
answerField.setText("" + (op1 - op2));
else if(operation.equals("*"))
answerField.setText("" + (op1 * op2));
else if(operation.equals("/"))
answerField.setText("" + (op1 / op2));
answer = "";
op1HasValue = op2HasValue = operationHasValue = false;
}
}
}
2 ответа:
Вместо использования
KeyListener
, лучше использовать привязки ключей, особенно если вы работаете с Swing. Следуя примеру учебника, вы можете попробовать что-то вроде этого (например, если пользователь нажал клавишу 1):functionPanel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW) .put(KeyStroke.getKeyStroke("1"),"1 key"); functionPanel.getActionMap().put("1 key",new AbstractAction() { @Override public void actionPerformed(ActionEvent ev) { // perform operation here } });
Вот лучший пример, так как вы можете видеть, что вы должны поместить в метод
actionPerformed
(т. е. если пользователь нажал клавишу C для очистки):InputMap inMap = functionPanel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW); inMap.put(KeyStroke.getKeyStroke("C"),"Clear"); ActionMap actMap = functionPanel.getActionMap(); actMap.put("Clear",new AbstractAction() { @Override public void actionPerformed(ActionEvent ev) { op1HasValue = op2HasValue = operationHasValue = false; op1Str = ""; op2Str = ""; operation = ""; answer = ""; answerField.setText(""); } });
В качестве альтернативы, если вы предпочитаете использовать
KeyListener
, Вы можете рассмотреть возможность создания нового класса, который реализуетKeyListener
, следующим образом. Вы должны понимать, что он будет работать только в том случае, если указанный компонент имеет фокус, что, помимо всего прочего, является недостатком использованияKeyListener
в отличие от привязки ключей.KeyHandler keyHandler = new KeyHandler(); functionPanel.addKeyListener(keyHandler); private class KeyHandler implements KeyListener { @Override public void keyPressed(KeyEvent ev) { if (ev.getKeyCode() == KeyEvent.VK_C) /* C for clear */ { op1HasValue = op2HasValue = operationHasValue = false; op1Str = ""; op2Str = ""; operation = ""; answer = ""; answerField.setText(""); } } @Override public void keyReleased(KeyEvent ev) {} @Override public void keyTyped(KeyEvent ev) {} }
Глядя на примеры Кейлистеров, кажется, что это может быть полезно...
Не использовать KeyListener. Swing был разработан для использования с
Key Bindings
. Проверьте эту другую ссылку привязки ключей, которая показывает все привязки ключей, используемые для существующих компонентов Swing.Добавьте еще одну функцию, которая позволяет пользователю использовать клавиатуру в качестве дополнительного источника ввода.
С помощью
Key Bindings
можно создать простойAction
, который будет использоваться для ввода числа:Конечно, вам нужно будет создать отдельные действия для каждой из ваших арифметических функций.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(); } }); } }