Search code examples
javakeyboardshiftuikeyboardcapslock

I need help on making a touch screen keyboard for an application that only uses touch screen. I am specifically having problems with shift and caps


I am not sure where to go with shift and caps key, I don't know whether I can make different values on what I am already working on for this or not. I am new to Jpanel, so any help would be much appreciated.

This is my current code in VSCode right now. It will pull up a 5 by 12 keyboard that reads inputs and will output into the console on enter. Tab, Caps, Shift, and delete currently don't work. I am mostly focused on caps and shift right now, as I can get the other two pretty easily.

import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Arrays;

import javax.lang.model.util.ElementScanner6;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.plaf.ComponentUI;

public class Keyboard extends JFrame implements ActionListener {
    private JButton[] buttons;
    private JPanel keyboardPanel;
    public String userInput = "";
    public ArrayList<String> keyboardKeys = new ArrayList<>(Arrays.asList("1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "-", "=",
    "q", "w", "e", "r", "t", "y", "u", "i", "o", "p", "\\", "delete",
    "a", "s", "d", "f", "g", "h", "j", "k", "l", ";", "'", "enter",
    "shift", "z", "x", "c", "v", "b", "n", "m", ",", ".", "/", "shift",
    "caps", "tab", "space", "`", "~", "!", "@", "(", ")", "?", "[", "]"));
    public static ComponentUI newUI = new ComponentUI() {
        
    };

    public Keyboard() {
        super("Keyboard");
        keyboardPanel = new JPanel();
        keyboardPanel.setLayout(new GridLayout(5, 12));
        buttons = new JButton[60];
        for (int i = 0; i < buttons.length; i++) {
            buttons[i] = new JButton(keyboardKeys.get(i));
            buttons[i].addActionListener(this);
            keyboardPanel.add(buttons[i]);
        }
        add(keyboardPanel, BorderLayout.CENTER);
        setSize(900, 300);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);
    }

    public void actionPerformed(ActionEvent event) {
        JButton source = (JButton) event.getSource();
        //System.out.println(source.getText());
        //collect inputs into a String
        if(source.getText() == "shift")
        {
            //change keyboard for shift and caps keystrokes
            System.out.println("shift key");
        }
        else if(source.getText() == "caps")
        {
             //change keyboard for caps keystrokes
             System.out.println("caps key");
        }
        else if((source.getText() == "enter"))
        {
            //on enter, send the input array out
            //System.out.println("enter key");
            System.out.println(userInput);
        }
        else if(source.getText() == "space")
        {
            System.out.println("space bar");
            userInput = userInput + " ";
        }
        else
        {
            userInput = userInput + source.getText();
        }
        // Do something with the button press, such as sending a value to the PLC or
        // updating a display
    }

    public static void main(String[] args) {
        new Keyboard();
    }
}

Solution

  • As was mentioned in the comments, have boolean variables to represent the states of the Caps Lock and Shift keys.

    For letters, it's easy to shift a letter to uppercase or lowercase. For punctuation, my suggestion is to have code that maps characters between lowercase and uppercase for punctuation and digits. A Map would be useful:

    private boolean shiftOn = false, capsLockOn = false;
    private final String [] shifted = {"1!","2@","3#","4$","5%","6^","7&","8*"
          ,"9(","0)","-_","=+","`~","[{","]}","\\|",";:","'\"",",<",".>","/?"};
    private Map <Character, Character> shiftMap;
    

    with a method:

        private void loadShiftMap () {
           shiftMap = new HashMap <> ();
           for (String c: shifted) { 
               shiftMap.put (c.charAt(0), c.charAt(1));
           }
        }
    

    Call loadShiftMap () within the constructor.

    Note: You will have make changes to match your keyboard layout. For example, to type !, I use (<shift> 1). But you have a separate key for ! and other characters for your keyboard. This solution, therefore, has to be adapted.

    If the String passed to the following method contains exaclty one character, it will return a result based on that character and the state of the Shift and Caps Lock keys. Otherwise, it will return what was passed:

    private String getShiftedCharacter (String input) { 
        if (input.length() != 1) return input;
        char theChar = input.charAt(0);
        char result = theChar;
        if (Character.isLetter(theChar)) { 
            if (shiftOn || capsLockOn) { 
                result = Character.toUpperCase(theChar);
            } else { 
                result = Character.toLowerCase(theChar);            
            }
        } else { 
            if (shiftOn) { 
                result = shiftMap.get(theChar);
            }
        }
        return Character.toString (result);
    }
    

    When the Shift key or Caps Lock key is pressed, toggle the state of the appropriate Boolean variable. For example, shiftOn = ! shiftOn;. In addition, after any letter, digit, or punctuation key is pressed, clear shiftOn to false. Otherwise, it will act as the Caps Lock key.

    If you want to redraw the keyboard whenever the state of the Shift key or Caps Lock key is changed, change the labels on the buttons, and then repaint:

    private void showShift () { 
        for (int i = 0; i < buttons.length; ++i) {
            buttons [i].setText(getshiftedCharacter(keyboardKeys.get(i)));
        }
        getContentPane().repaint();
    }
    

    Because the "source" comes from the label (text) on the button, and the labels on the button are updated when the state of a Shift Key or Caps Lock key is changed, the only place getShiftedCharacter is called is within the showShift method.

    Note: This code uses char / Character autoboxing and autounboxing.

    Comment: I don't like parallel arrays. I might avoid parallel arrays by doing something like this:

     String [][] keyboardKeys = {{"`","~"}, {"1","!"}, {"2","@"}, {"3","#"}, ... 
     ,{"Tab","Tab"},{"q","Q"},{"w","W"}, ... {"[","{"},{"]","}"},{"\","|"}
     ,{"Caps","Caps"},{"a","A"},{"s","S"}, ... };