So I'm having trouble trying to change the background color of the keys pressed and I'm not entirely sure on how to go about it?
It works as a keyboard, the only issue I have is the method to change the background color when any key is typed
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.Panel;
import java.awt.TextArea;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.AbstractAction;
public abstract class OnScreenKeyboard extends JFrame implements KeyListener
{
String firstRow[] = {"~","1","2","3","4","5","6","7","8","9","0","-","+","Back\nSpace"};
String secondRow[] = {"Tab","Q","W","E","R","T","Y","U","I","O","P","[","]","|"};
String thirdRow[] = {"Caps\nLock","A","S","D","F","G","H","J","K","L",";","'","Enter"};
String fourthRow[] = {"Shift","Z","X","C","V","B","N","M",",",".","?","Space"};
JButton first[] = new JButton[14];
JButton second[] = new JButton[14];
JButton third[] = new JButton[13];
JButton fourth[] = new JButton[12];
Panel keys = new Panel();
Panel text = new Panel();
TextArea textArea = new TextArea();
String strText = "";
private JLabel label1;
private JLabel label2;
private JTextField textField;
public OnScreenKeyboard()
{
super("Typing Application");
label1 = new JLabel("Type some text using your keyboard. The keys you press will be "
+ "highlighed and the text will be displayed");
add(label1);
label2 = new JLabel("Note: clicking the buttons with your mouse will not perform any action");
add(label2);
textField = new JTextField(80);
textField.setEditable(true);
TextFieldHandler handler = new TextFieldHandler();
this.setLayout(new BorderLayout(1,1));
keys.setLayout(new GridLayout(4,14));
text.setLayout(new BorderLayout(1,1));
text.add(textArea);
for(int i=0; i<14; i++)
{
first[i] = new JButton(firstRow[i]);
first[i].setBackground(Color.white);
keys.add(first[i]);
first[i].addKeyListener(this);
}
for(int i=0; i<14; i++)
{
second[i] = new JButton(secondRow[i]);
second[i].setBackground(Color.white);
keys.add(second[i]);
second[i].addKeyListener(this);
}
for(int i=0; i<13; i++)
{
third[i] = new JButton(thirdRow[i]);
third[i].setBackground(Color.white);
keys.add(third[i]);
third[i].addKeyListener(this);
}
for(int i=0; i<12; i++)
{
fourth[i] = new JButton(fourthRow[i]);
fourth[i].setBackground(Color.white);
keys.add(fourth[i]);
fourth[i].addKeyListener(this);
}
add(text, BorderLayout.NORTH);
add(keys,BorderLayout.CENTER);
}
private class TextAreaHandler implements ActionListener
{
public void actionPerformed( ActionEvent event )
{
String string = ""; // declare string to display
if ( event.getSource() == textField )
string = String.format( "%s",
event.getActionCommand() );
}
}
public void actionPerformed(ActionEvent event) {
if (event.getSource() instanceof JButton) {
System.out.println((((JButton) event.getSource()).getActionCommand()));
((JButton) event.getSource()).setBackground(Color.BLUE);
((JButton) event.getSource()).setContentAreaFilled(false);
((JButton) event.getSource()).setOpaque(true);
}
}
#Override
public void keyTyped( KeyEvent event )
{
int keyCode = event.getKeyCode();
strText = String.format( "%s", event.getKeyCode() );
}
private class TextFieldHandler implements ActionListener
{
public void actionPerformed( ActionEvent event )
{
String string = ""; // declare string to display
// user pressed Enter in JTextField textField1
if ( event.getSource() == textField )
string = String.format("%s", event.getActionCommand());
}
}
}
It takes no Java knowledge to know that you don't need 4x14 buttons, and lables and textfilelds to demonstrate a change of background color in one JButton.
Doesn't this MCVE demonstrate it ?
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
public class OnScreenKeyboard extends JFrame{
public OnScreenKeyboard()
{
super();
JButton button = new JButton("T");
add(button,BorderLayout.CENTER);
pack();//"size to fit the preferred size and layouts of its subcomponents"
setVisible(true);//make Jframe show
}
public void actionPerformed(ActionEvent event) {
if (event.getSource() instanceof JButton) {
System.out.println((((JButton) event.getSource()).getActionCommand()));
((JButton) event.getSource()).setBackground(Color.BLUE);
((JButton) event.getSource()).setContentAreaFilled(false);
((JButton) event.getSource()).setOpaque(true);
}
}
//a main is needed to make your code runnable (google MCVE)
public static void main(String[] args) {
new OnScreenKeyboard();
}
}
When it is short and concise, it also help you debug the problem.
Hint: You wrote an ActionListener but you never use it.
If you need more help don't hesitate to ask.
Related
I have discovered class javax.swing.Popup. I wrote code to test its behavior. Code is shown below. When I run the code, after the JFrame is displayed, I click the SHOW button and the Popup is displayed. After that I click the HIDE button and the Popup disappears. But then if I click the SHOW button again, nothing happens. The Popup only appears after clicking the SHOW button for the first time. Also, if I click the HIDE button first, before clicking the SHOW button, then when I click the SHOW button, the Popup does not appear.
Am I missing something?
Am I doing something wrong?
I admit I haven't investigated this behavior. I haven't searched the Internet and I haven't looked at the code for class Popup nor PopupFactory, simply due to laziness and in the hope that someone can explain it to me.
Here is my MCVE.
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Point;
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.Popup;
import javax.swing.PopupFactory;
import javax.swing.SwingConstants;
import javax.swing.WindowConstants;
public class PopupTest implements ActionListener, Runnable {
private static final String HIDE = "HIDE";
private static final String SHOW = "SHOW";
private Popup popup;
public void actionPerformed(ActionEvent actionEvent) {
String actionCommand = actionEvent.getActionCommand();
switch (actionCommand) {
case HIDE:
popup.hide();
break;
case SHOW:
popup.show();
break;
}
}
public void run() {
showGui();
}
private void showGui() {
JFrame frame = new JFrame("Popup");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
JLabel centerLabel = new JLabel("CENTER LABEL", SwingConstants.CENTER);
frame.add(centerLabel, BorderLayout.CENTER);
JPanel buttonsPanel = new JPanel();
JButton showButton = new JButton(SHOW);
showButton.addActionListener(this);
buttonsPanel.add(showButton);
JButton hideButton = new JButton(HIDE);
hideButton.addActionListener(this);
buttonsPanel.add(hideButton);
frame.add(buttonsPanel, BorderLayout.PAGE_END);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
JLabel popupLabel = new JLabel("Popup_Label");
PopupFactory factory = PopupFactory.getSharedInstance();
Point pt = centerLabel.getLocationOnScreen();
int x = pt.x + 10;
int y = pt.y - 10;
popup = factory.getPopup(centerLabel, popupLabel, x, y);
}
public static void main(String[] args) {
PopupTest instance = new PopupTest();
EventQueue.invokeLater(instance);
}
}
https://docs.oracle.com/javase/7/docs/api/javax/swing/Popup.html#hide()
The documentation that you have chosen not to read is very clear that hide() disposes of the Popup and any further method calls on that Popup will result in indeterminate behaviour.
You must create a new Popup instance each time.
From the docs for hide():
"Hides and disposes of the Popup. Once a Popup has been disposed you
should no longer invoke methods on it. A disposed Popup may be
reclaimed and later used based on the PopupFactory."
As such, here is a quick and dirty modified version that works.
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Point;
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.Popup;
import javax.swing.PopupFactory;
import javax.swing.SwingConstants;
import javax.swing.WindowConstants;
public class PopupTest implements ActionListener, Runnable {
private static final String HIDE = "HIDE";
private static final String SHOW = "SHOW";
private Popup popup;
private JLabel centerLabel;
private JLabel popupLabel = new JLabel("Popup_Label");
private PopupFactory factory = PopupFactory.getSharedInstance();
public void actionPerformed(ActionEvent actionEvent) {
String actionCommand = actionEvent.getActionCommand();
switch (actionCommand) {
case HIDE:
if (popup == null) {
return;
}
popup.hide();
popup = null; // necessary to avoid using the disposed popup
break;
case SHOW:
if (popup != null) { // it's already showing
return;
}
Point pt = centerLabel.getLocationOnScreen();
int x = pt.x + 10;
int y = pt.y - 10;
popup = factory.getPopup(centerLabel, popupLabel, x, y);
popup.show();
break;
}
}
public void run() {
showGui();
}
private void showGui() {
JFrame frame = new JFrame("Popup");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
centerLabel = new JLabel("CENTER LABEL", SwingConstants.CENTER);
frame.add(centerLabel, BorderLayout.CENTER);
JPanel buttonsPanel = new JPanel();
JButton showButton = new JButton(SHOW);
showButton.addActionListener(this);
buttonsPanel.add(showButton);
JButton hideButton = new JButton(HIDE);
hideButton.addActionListener(this);
buttonsPanel.add(hideButton);
frame.add(buttonsPanel, BorderLayout.PAGE_END);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
PopupTest instance = new PopupTest();
EventQueue.invokeLater(instance);
}
}
We have a legacy piece of software that runs on Java 1.6. When we finally got the green light to upgrade it to Java 1.8, the following problem manifested itself.
We have a set of radio buttons with accelerator keys. If a JTextComponent of any sort has the focus, and you hit one of the radio button accelerators (say, ALT-s), and you release the "s" before you release the ALT, the UIManager will activate the menu bar. (This only happens with the Windows look and feel)
Looks like a bug, and I've been thinking of writing a workaround by "consuming" the ALT release in those cases, but maybe someone has a better idea? Using a different look and feel is not an option, nor is switching off the standard Alt behavior in the UI Manager.
Here's a short code sample. Note there are no accelerator/mnemonic conflicts of any sort.
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;
import javax.swing.UIManager;
public class MnemonicTest extends JFrame {
public MnemonicTest() {
super("MnemonicTest");
init();
}
public static void main(String[] args) throws Exception {
MnemonicTest test = new MnemonicTest();
test.setVisible(true);
}
private void init() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e1) {
e1.printStackTrace();
}
setSize(new Dimension(500,400));
JButton stopButton = new JButton("Stop");
stopButton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
System.exit(0);
}});
this.getContentPane().setLayout(new BorderLayout());
this.getContentPane().add(stopButton, BorderLayout.SOUTH);
JMenuBar jMenuBar = new JMenuBar();
JMenu menu = new JMenu("XXX");
JMenuItem a1 = new JMenuItem("a1", 'A');
JMenuItem b1 = new JMenuItem("b1", 'B');
JMenuItem c1 = new JMenuItem("c1", 'C');
menu.add(a1);
menu.add(b1);
menu.add(c1);
jMenuBar.add(menu);
this.setJMenuBar(jMenuBar);
JPanel p = new JPanel();
ButtonGroup group = new ButtonGroup();
p.add(new JTextField("XXXXXXXXXX"), BorderLayout.CENTER);
JRadioButton but1 = new JRadioButton("test");
but1.setMnemonic('s');
JRadioButton but2 = new JRadioButton("2222");
p.add(but1);
p.add(but2);
group.add(but1);
group.add(but2);
getContentPane().add(p, BorderLayout.CENTER);
}
}
I did manage to find a solution that works, even if it's not exactly a beauty contest winner. If you have a better one, please post it!!
The problem seems to be that the KeyEvent is sent to the radio button and not to the pane or the text field. And when the system sees that the ALT key has been released, it invokes the default action.
Of course, a plain vanilla Alt when a radio button has the focus should still do what it is supposed to do: activate the menu bar.
If you press, say, Alt-S (our accelerator), the radio button will receive: keyPressed(Alt) -> keyPressed("S") -> keyReleased("S") -> keyReleased(Alt).
Thus, if we save the value of the last key pressed, we'll consume the last event (keyReleased(Alt)) unless the last key pressed was also an Alt.
This is a workaround, and not a pretty one, but it works. The code is as follows (I've left my debug statements in the code):
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;
import javax.swing.UIManager;
public class MnemonicTest extends JFrame {
int codeLast = 0;
private final class RadioButtonKeyAdapter extends KeyAdapter {
private static final int NO_CODE = 0;
private int lastCode = 0;
#Override
public void keyPressed(KeyEvent e) {
System.out.println("pressed source: " + e.getSource() + "\n" + e.getKeyCode());
this.setLastCode(e.getKeyCode());
}
#Override
public void keyReleased(KeyEvent e) {
System.out.println("released source: " + e.getSource() + "\n" + e.getKeyCode());
if (e.getKeyCode() == KeyEvent.VK_ALT && this.getLastCode() != e.getKeyCode()) {
e.consume();
}
this.setLastCode(NO_CODE);
}
private int getLastCode() {
return lastCode;
}
private void setLastCode(int lastCode) {
this.lastCode = lastCode;
}
}
private static final long serialVersionUID = 1L;
public MnemonicTest() {
super("MnemonicTest");
init();
}
public static void main(String[] args) throws Exception {
MnemonicTest test = new MnemonicTest();
test.setVisible(true);
}
private void init() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e1) {
e1.printStackTrace();
}
setSize(new Dimension(500,400));
JButton stopButton = new JButton("Stop");
stopButton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
System.exit(0);
}});
this.getContentPane().setLayout(new BorderLayout());
this.getContentPane().add(stopButton, BorderLayout.SOUTH);
JMenuBar jMenuBar = new JMenuBar();
JMenu menu = new JMenu("XXX");
JMenuItem a1 = new JMenuItem("a1", 'A');
JMenuItem b1 = new JMenuItem("b1", 'B');
JMenuItem c1 = new JMenuItem("c1", 'C');
menu.add(a1);
menu.add(b1);
menu.add(c1);
jMenuBar.add(menu);
this.setJMenuBar(jMenuBar);
JPanel p = new JPanel();
ButtonGroup group = new ButtonGroup();
JTextField textField = new JTextField("XXXXXXXXXX");
p.add(textField, BorderLayout.CENTER);
JRadioButton but1 = new JRadioButton("test");
but1.setMnemonic('s');
JRadioButton but2 = new JRadioButton("2222");
p.add(but1);
p.add(but2);
group.add(but1);
group.add(but2);
getContentPane().add(p, BorderLayout.CENTER);
but1.addKeyListener(new RadioButtonKeyAdapter());
but2.addKeyListener(new RadioButtonKeyAdapter());
}
}
There is the code of my simple Program.
There are four textFields.
when cursor is on first textField JOptionPane is Created and when I press ok
cursor moves to next field and OptionPane is created again
and so on
when cursor is on fourth field and I click OK on OptionPane,cursor moves to fifth field "f".
when cursor is in field,I print the possition of the field in array: System.out.println("first or Second or Third or Fourth")
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class Hello extends JFrame implements ActionListener, FocusListener {
public JTextField[] fields = new JTextField[4];
public JPanel panel = new JPanel();
public JTextField f = new JTextField(12);
public static void main(String[] args) {
new Hello();
}
public Hello() {
for (int i = 0; i < 4; i++) {
fields[i] = new JTextField(12);
fields[i].addFocusListener(this);
panel.add(fields[i]);
}
add(panel);
add(f);
setTitle("Hello World");
getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.PAGE_AXIS));
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(920, 420);
setLocation(100, 100);
setVisible(true);
}
#Override
public void actionPerformed(ActionEvent ae) {
}
#Override
public void focusGained(FocusEvent fe) {
if (fe.getSource() == fields[0]) {
JOptionPane.showMessageDialog(null, "HELLO");
fields[1].requestFocus();
System.out.println("FIRST");
} else if (fe.getSource() == fields[1]) {
JOptionPane.showMessageDialog(null, "HELLO");
fields[2].requestFocus();
System.out.println("SECOND");
} else if (fe.getSource() == fields[2]) {
JOptionPane.showMessageDialog(null, "HELLO");
fields[3].requestFocus();
System.out.println("THIRD");
} else if (fe.getSource() == fields[3]) {
JOptionPane.showMessageDialog(null, "HELLO");
f.requestFocus();
System.out.println("FOURTH")
}
}
#Override
public void focusLost(FocusEvent fe) {
}
}
When there is no OptionPane,the cursor moves forward from first field to the fourth and prints:
FIRST
SECOND
THIRD
FOURTH
but when there is JOptionPane
the output is :
FIRST
SECOND
FIRST
SECOND
THIRD
SECOND
THIRD
FOURTH
THIRD
FOURTH
FOURTH
One can see that after second field it comes back to first,
after third field it comes back to second,instead of to go to fourth
after fourth field it comes back to third.
I want to know why? and how can I fix this
The problem is that every time you click OK on the JOptionPane, the focus is returned to the last JTextField active before the JOptionPane was shown, so a new requestFocus event is added to the event queue for that control. Actually after the first time you click OK while executing your code, several dialogs are fire, you just don't see it because you show the same text (HELLO) every time. I have changed your code to make it work. Hope it helps!
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.util.ArrayList;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class testOptionPane extends JFrame implements ActionListener, FocusListener {
public ArrayList<JTextField> fields = new ArrayList<>();
public JPanel panel = new JPanel();
public JTextField f = new JTextField(12);
private int currentField = 0;
private boolean focusReturned = false;
public static void main(String[] args) {
new testOptionPane();
}
public testOptionPane() {
for (int i = 0; i < 4; i++) {
JTextField tf = new JTextField(12);
fields.add(tf);
tf.addFocusListener(this);
panel.add(tf);
}
add(panel);
fields.add(f);
add(f);
setTitle("Hello World");
getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.PAGE_AXIS));
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(920, 420);
setLocation(100, 100);
setVisible(true);
}
#Override
public void actionPerformed(ActionEvent ae) {
}
#Override
public void focusGained(FocusEvent fe) {
if (fe.getSource() == fields.get(currentField)) {
if (!focusReturned) {
JOptionPane.showMessageDialog(this, "focus on field " + String.valueOf(currentField));
System.out.println(currentField);
focusReturned = true;
} else {
currentField++;
focusReturned = false;
if (currentField < fields.size()) {
fields.get(currentField).requestFocus();
}
}
}
}
#Override
public void focusLost(FocusEvent fe) {
}
}
I'm trying to create a hangman program. The phrase they have to guess is "bad hair day", and they see "* * **". When the user inputs a character nothing changes. I'm not 100% sure were I am going wrong but maybe it's in the passwordlabel2 or somewhere in the loop.
Demo Class
public class SecretPhrase {
int wrong = 0; //ignore for now
String phrase = "Bad hair day"; //hidden, what the user has to guess
String hiddenPhrase = "*** **** ***"; //what the user originally sees
public void changeLetter(char input)
{
StringBuilder checker = new StringBuilder(input);
StringBuilder(hiddenPhrase);
boolean wrongGuess = true;
for (int i=0; i<phrase.length(); i++)
{
if (phrase.charAt(i) == input){
checker.setCharAt(i, input);
wrongGuess = false;
}
}
hiddenPhrase = checker.toString();
if (wrongGuess){
wrong++;
}
}
private void StringBuilder(String hiddenPhrase) {
// TODO Auto-generated method stub
}
}
UI Class
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JApplet;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JTextField;
public class SecretPhraseUI extends JApplet implements ActionListener {
SecretPhrase phrase = new SecretPhrase();
JLabel passwordLabel = new JLabel("Enter a letter to guess the phrase." ); //sets label to display message
JLabel passwordLabel2 = new JLabel( phrase.hiddenPhrase ); //sets label to display message
JTextField inputBox = new JTextField(40); //sets text field
JButton runButton = new JButton("Run"); //button that starts program
Container con = getContentPane(); //gets container
public void init()
{
con.setLayout(new FlowLayout());//sets flowlayout
con.add(new JLabel()); //jlabel container
con.add(inputBox); //input box container
con.add(runButton); //run button container
con.add(passwordLabel); //password label container
con.add(passwordLabel2); //password label container
runButton.addActionListener(this);//looks to see if run is clicked
inputBox.addActionListener(this);//looks to see if input box is used
}
public void actionPerformed(ActionEvent e)
{
String userInput = inputBox.getText(); //gets input from user
}
}
You have to make label.setText("The text you want to be displayed after action") . So when you do check the char, then do passwordLabel2.setText(phrase.hiddenPhrase) if the char is guessed right. :)
Working example
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JApplet;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JTextField;
public class SecretPhraseUI
extends JApplet
implements ActionListener {
SecretPhrase phrase = new SecretPhrase();
JLabel passwordLabel = new JLabel("Enter a letter to guess the phrase."); //sets label to display message
JLabel passwordLabel2 = new JLabel(
phrase.hiddenPhrase ); //sets label to display message
JTextField inputBox = new JTextField(40); //sets text field
JButton runButton = new JButton("Run"); //button that starts program
Container con = getContentPane(); //gets container
public void init() {
con.setLayout(new FlowLayout());//sets flowlayout
con.add(new JLabel()); //jlabel container
con.add(inputBox); //input box container
con.add(runButton); //run button container
con.add(passwordLabel); //password label container
con.add(passwordLabel2); //password label container
runButton.addActionListener(this);//looks to see if run is clicked
inputBox.addActionListener(this);//looks to see if input box is used
}
public void actionPerformed(ActionEvent e) {
if (!inputBox.getText().isEmpty()) {
phrase.changeLetter(
inputBox.getText().charAt(0)); //gets input from user
passwordLabel2.setText(phrase.hiddenPhrase);
}
}
}
public class SecretPhrase {
int wrong = 0; //ignore for now
String phrase = "Bad hair day"; //hidden, what the user has to guess
String hiddenPhrase = "*** **** ***"; //what the user originally sees
public void changeLetter(char input) {
StringBuilder checker = new StringBuilder(hiddenPhrase);
boolean wrongGuess = true;
for (int i=0; i<phrase.length(); i++) {
if (phrase.charAt(i) == input){
checker.setCharAt(i, input);
wrongGuess = false;
}
}
hiddenPhrase = checker.toString();
if (wrongGuess){
wrong++;
}
}
}
It doesn't look like you've done anything with the user input. You could do something with the user input. Append the user input to another String and use the setText method of a label to update a label with the user input.
Description of the problem: I have a JFrame, inside this JFrame there is a JPanel with a button, when I press the button an action listener change the current JPanel with a new JPanel, which contains other two JPanels, those two have an inputMap that when the user press the key "up" make something on both of them. The problem is: when I change the JPanel with the new one the "up" key won't do anything.
Here is the code: is a SSCCE, so you just have to copy and paste to see what it does.
This modified code comes from another question that I "solved" sometimes ago. How to make two JPanels listen to the same event?
(the code is in the answer that I selected).
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.util.Arrays;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
public class TwoPanelsTest extends JFrame {
private static MyPanel one = new MyPanel("One");
private static MyPanel two = new MyPanel("Two");
private static List<MyPanel> list = Arrays.asList(one, two);
private PanelsController panelsController;
public TwoPanelsTest() {
super("TwoPanelsTest");
panelsController= new PanelsController(this);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setSize(400,400);
this.setLocationRelativeTo(null);
this.setVisible(true);
}
private static class MyPanel extends JPanel {
private String string = " will be updated though its action.";
private Action action = new UpdateAction(this);
private String name;
private JLabel label;
public MyPanel(String name) {
this.name = name;
this.label = new JLabel(name + string, JLabel.CENTER);
this.setLayout(new GridLayout());
this.setFocusable(true);
this.add(label);
}
public Action getAction() {
return action;
}
private void update() {
label.setText(name + ": " + System.nanoTime());
}
private static class UpdateAction extends AbstractAction {
private MyPanel panel;
public UpdateAction(MyPanel panel) {
this.panel = panel;
}
#Override
public void actionPerformed(ActionEvent ae) {
panel.update();
}
}
}//MyPanel
private static class ButtonPanel extends JPanel{
private JButton button ;
private PanelsController panelsController;
public ButtonPanel(PanelsController panelsController){
this.panelsController=panelsController;
button = new JButton("Button");
button.setActionCommand("buttonPressed");
button.addActionListener(this.panelsController);
this.setFocusable(true);
add(button);
}
}//ButtonPanel
private static class PanelsController implements ActionListener {
private TwoPanelsTest twoPanelsTest;
public PanelsController(TwoPanelsTest twoPanelsTest){
this.twoPanelsTest=twoPanelsTest;
this.twoPanelsTest.getContentPane().add(new ButtonPanel(this));
}
#Override
public void actionPerformed(ActionEvent ae) {
if (ae.getActionCommand().equals("buttonPressed")){
twoPanelsTest.getContentPane().removeAll();
twoPanelsTest.getContentPane().invalidate();
JPanel panel = new JPanel(new GridLayout(0, 1, 10, 10));
panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
panel.add(one);
panel.add(two);
panel.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), "up");
panel.getActionMap().put("up", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
for (MyPanel panel : list) {
panel.getAction().actionPerformed(e);
}
}
});
twoPanelsTest.getContentPane().add(panel);
twoPanelsTest.validate();
twoPanelsTest.repaint();
}
}//ActionPerformed
}//PanelsController
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
TwoPanelsTest t = new TwoPanelsTest();
}
});
}
}
Well, its pretty simple - if you have those two panels without any components inside and want them to listen the hotkey use:
panel.getInputMap ( JComponent.WHEN_IN_FOCUSED_WINDOW )
.put ( KeyStroke.getKeyStroke ( KeyEvent.VK_UP, 0 ), "up" );
JComponent.WHEN_IN_FOCUSED_WINDOW instead of JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT.
Otherwise you need to have somthing focused inside the panel so it could catch the key events.
By the way, there is also another way to listen global hotkeys inside Java application windows:
Toolkit.getDefaultToolkit ().addAWTEventListener ( new AWTEventListener ()
{
public void eventDispatched ( AWTEvent event )
{
// All application key events will be passed here
}
}, AWTEvent.KEY_EVENT_MASK );