How do I create an on screen keyboard in java? - java

I'm working on a school project where we have to create a virtual smartphone, to run on a computer.
My problem is that I need to create a keyboard on the screen (like on an smartphone), which you can then use by clicking with your mouse. I could just create every single JButton, but that will take a really long time. So I was hopping that someone knew some sort of algorithm that creates all the buttons and places them correctly on the screen.
Thank you in advance :)

You could construct the buttons through the use of for loops. One loop for every keyboard row is a plausible approach.
String row1 = "1234567890";
String row2 = "qwertyuiop";
// and so forth
String[] rows = { row1, row2, .. };
for (int i = 0; i < rows.length; i++) {
char[] keys = rows[i].toCharArray();
for (int j = 0; i < keys.length; j++) {
JButton button = new JButton(Character.toString(keys[j]));
// add button
}
}
// add special buttons like space bar
This could be done more elegantly through a more OOP approach, but this basic loop system will work.

This simple example might help you:
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
#SuppressWarnings("serial")
public class MainFrame extends JFrame
{
private JTextField txt;
private PopUpKeyboard keyboard;
public MainFrame()
{
super("pop-up keyboard");
setDefaultCloseOperation(EXIT_ON_CLOSE);
txt = new JTextField(20);
keyboard = new PopUpKeyboard(txt);
txt.addMouseListener(new MouseAdapter()
{
#Override
public void mouseClicked(MouseEvent e)
{
Point p = txt.getLocationOnScreen();
p.y += 30;
keyboard.setLocation(p);
keyboard.setVisible(true);
}
});
setLayout(new FlowLayout());
add(txt);
pack();
setLocationByPlatform(true);
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
new MainFrame().setVisible(true);
}
});
}
private class PopUpKeyboard extends JDialog implements ActionListener
{
private JTextField txt;
public PopUpKeyboard(JTextField txt)
{
this.txt = txt;
setLayout(new GridLayout(3, 3));
for(int i = 1; i <= 9; i++) createButton(Integer.toString(i));
pack();
}
private void createButton(String label)
{
JButton btn = new JButton(label);
btn.addActionListener(this);
btn.setFocusPainted(false);
btn.setPreferredSize(new Dimension(100, 100));
Font font = btn.getFont();
float size = font.getSize() + 15.0f;
btn.setFont(font.deriveFont(size));
add(btn);
}
#Override
public void actionPerformed(ActionEvent e)
{
String actionCommand = e.getActionCommand();
txt.setText(txt.getText() + actionCommand);
}
}
}

/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
String alphabet = "abcdefghijklmnopqrstuvwxyz";
JFrame myFrame = new JFrame();
JPanel myPanel = new JPanel();
for (int i = 0; i < alphabet.length(); i++) {
myPanel.add(new JButton(alphabet.substring(i, i + 1)));
}
myFrame.add(myPanel);
myFrame.pack();
myFrame.setVisible(true);
}
This is a fast example of how to do it :).

Related

Why does my ActionListener will not work?

I am creating a simple app that codify a text but i am struggling with some ActionListeners. When I'm choosing something from JComboBox there must happen things (if you choose Caesar's Cipher, an offset must appear, if you choose Beaufort, the offset will dissapper; the offset is a JTextField) and according to the choose the execute button will get the according ActionListener implementation. The thing is, When I'm choosing the Caesar's Cipher nothing happens, even if i add CaesarsCipher that implements ActionListener to codify the text, nothing will work.
MyFrame.java
package cipher;
import java.awt.BorderLayout;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
#SuppressWarnings("serial")
class MyFrame extends JFrame {
private JButton executeButton;
private ComboBoxPanel leftPanel;
private TextPanel rightPanel;
public MyFrame(String title) {
super(title);
//Initiate the frame
initFrame();
//Initiate the button that need to be pressed to execute a cipher
initButton();
//Init the panels
initPanel();
//Pack everything together;
packing();
//Make the frame visible to the user
setVisible(true);
}
//////////PACKING EVERYTHING TOGETHER//////////
private void packing() {
add(executeButton,BorderLayout.SOUTH);
add(leftPanel, BorderLayout.WEST);
add(rightPanel, BorderLayout.EAST);
}
//////////INITIATING THE FRAME WITH ALL COMPONENTS//////////
private void initPanel() {
leftPanel = new ComboBoxPanel();
rightPanel = new TextPanel();
}
private void initButton() {
executeButton = new JButton("Execute cipher");
}
private void initFrame() {
setSize(800,400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setLayout(new BorderLayout());
setResizable(false);
}
//////////HIDE THE OFFSET WHEN CHOOSING ALGORITHMS THAT DO NOT REQUIRE OFFSET//////////
public void hideOffset() {
leftPanel.hideOffset();
}
public void showOffset() {
leftPanel.showOffset();
}
//////////UPDATE LEFT PANEL AFTER HIDING OFFSET//////////
public void updateLeftPanel() {
leftPanel.updatePanel();
}
//////////LISTENERS//////////
/////COMBO BOX/////
public void addComboBoxListener(ActionListener comboBoxListener) {
leftPanel.addComboBoxListener(comboBoxListener);
}
/////EXECUTE BUTTON/////
public void addExecuteButtonListener(ActionListener executeButtonListener) {
executeButton.addActionListener(executeButtonListener);
}
//////////GETTERS//////////
/////OFFSET GETTER/////
public Integer getOffset() {
return Integer.parseInt(leftPanel.getOffset());
}
/////INPUT GETTER/////
public String getInputText() {
return rightPanel.getInputText();
}
//////////SETTERS//////////
/////OUTPUT TEXT SETTER/////
public void setOutputText(String text) {
rightPanel.setOutputText(text);
}
}
ComboBoxPanel.java
package cipher;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JComboBox;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.Border;
#SuppressWarnings("serial")
class ComboBoxPanel extends JPanel {
private final String []CIPHERS = {"Caesar's Cipher", "ROT13", "Beaufort Cipher", "Autokey Cipher"};
#SuppressWarnings("rawtypes")
private JComboBox comboCiphers;
private JTextField offset;
public ComboBoxPanel() {
initSize();
initComboBox();
initBorder();
initLayout();
initTextField();
packing();
}
private void initTextField() {
offset = new JTextField(10);
}
private void initLayout() {
setLayout(new GridBagLayout());
}
private void packing() {
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.ipadx = 10;
add(comboCiphers,gbc);
gbc.gridy = 1;
add(offset,gbc);
}
private void initBorder() {
Border outer = BorderFactory.createEmptyBorder(5, 5, 5, 5);
Border inner = BorderFactory.createTitledBorder("Choose the cipher");
setBorder(BorderFactory.createCompoundBorder(outer, inner));
}
#SuppressWarnings({ "unchecked", "rawtypes" })
private void initComboBox() {
comboCiphers = new JComboBox(CIPHERS);
}
//Remainder: delete this, let the layout to do its job.
private void initSize() {
Dimension size = getPreferredSize();
size.width = 390;
setPreferredSize(size);
}
public void hideOffset() {
offset.setVisible(false);
}
public void showOffset() {
offset.setVisible(true);
}
public void updatePanel() {
revalidate();
repaint();
}
public void addComboBoxListener(ActionListener comboBoxListener) {
comboCiphers.addActionListener(comboBoxListener);
}
public String getOffset() {
return offset.toString();
}
}
TextPanel.java
package cipher;
import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.border.Border;
import javax.swing.border.LineBorder;
#SuppressWarnings("serial")
class TextPanel extends JPanel {
private JTextArea inputArea, outputArea;
private JScrollPane inputScroll, outputScroll;
public TextPanel() {
//////////PANEL METHODS///////
/*
//Initiate the size of the panel
initSize();
*/
//Initiate the border of the entire panel
initBorder();
//Setup the layout of the panel
initLayout();
//////////TEXT AREAS METHODS///////
//Initiate the text areas
initTextArea();
//Initiate the borders for the 2 text areas
initTextAreaBorder();
//Create scrolls for both text areas
initScrollPane();
//Pack everything together
packing();
}
private void packing() {
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weightx = 1;
gbc.weighty = 1;
gbc.fill = GridBagConstraints.BOTH;
add(inputScroll,gbc);
gbc.gridx = 0;
gbc.gridy = 1;
gbc.weightx = 1;
gbc.weighty = 1;
add(outputScroll,gbc);
}
private void initScrollPane() {
inputScroll = new JScrollPane(inputArea);
outputScroll = new JScrollPane(outputArea);
}
private void initTextAreaBorder() {
inputArea.setBorder(new LineBorder(Color.black));
outputArea.setBorder(new LineBorder(Color.black));
}
private void initBorder() {
Border outer = BorderFactory.createEmptyBorder(5, 5, 5, 5);
Border inner = BorderFactory.createTitledBorder("Text");
setBorder(BorderFactory.createCompoundBorder(outer,inner));
}
private void initLayout() {
setLayout(new GridBagLayout());
}
private void initTextArea() {
inputArea = new JTextArea(10,77);
outputArea = new JTextArea(10,77);
outputArea.append("Output...");
outputArea.setEditable(false);
}
public void addComboBoxListener(ActionListener comboBoxListener) {
//.addActionListener(comboBoxListener);
}
/*private void initSize() {
//setPreferredSize sets the minimum
Dimension size = getPreferredSize();
size.width = 390;
setPreferredSize(size);
}*/
public String getInputText() {
return inputArea.toString();
}
public void setOutputText(String text) {
outputArea.append(text);
}
}
ApplicationController.java
package cipher;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JComboBox;
public class ApplicationController{
private MyFrame frame;
public ApplicationController(MyFrame frame) {
this.frame = frame;
this.frame.addComboBoxListener(new ComboBoxListener());
}
class ComboBoxListener implements ActionListener {
#SuppressWarnings("rawtypes")
#Override
public void actionPerformed(ActionEvent e) {
JComboBox c = (JComboBox) e.getSource();
String selected = c.getSelectedItem().toString();
if(selected.equalsIgnoreCase("Caesar's Cipher")) {
frame.addExecuteButtonListener(new CaesarsCipher());
frame.showOffset();
frame.updateLeftPanel();
} else if(selected.equalsIgnoreCase("ROT13")) {
frame.showOffset();
frame.updateLeftPanel();
} else if(selected.equalsIgnoreCase("Beaufort Cipher")) {
frame.hideOffset();
frame.updateLeftPanel();
} else if(selected.equalsIgnoreCase("Autokey Cipher")) {
frame.hideOffset();
frame.updateLeftPanel();
}
}
}
class CaesarsCipher implements ActionListener {
public void actionPerformed(ActionEvent e) {
int offset = frame.getOffset();
char []text = frame.getInputText().toCharArray();
for(int i = 0 ; i < text.length ; i++) {
text[i] = (char)(((int)text[i] + offset) % 26);
}
String newText = new String(text);
frame.setOutputText(newText);
}
}
}
Please someone explain what is wrong. I am ready to learn from mistakes. Thanks.
You didn't create an instance of your applicationController so your comboBox Listener was never created.
In the future, you should not be extending JFrame. All you need is an instance of it. You have also added complexity by putting in those extra add listener methods.

Having selected JButton from a 2d array perform an action

I have a 2 dimensional array of JButtons, and I would like to be able to have the button that my mouse is over to perform an action, such as change color. How can I do this? Thanks.
Here is how I am creating the buttons:
for(int r = 0;r<10;r++){
for(int c = 0;c<10;c++){
buttonArray[r][c] = new JButton();
}
}
Here is an example using a loop and a MouseAdapter (since you don't need all the methods from MouseListener ) :
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class JButtonHighlighter extends JPanel {
public static void main(final String[] args) {
JFrame frame = new JFrame();
JPanel contentPanel = new JPanel();
contentPanel.setLayout(new GridLayout(10, 10));
JButton[][] buttonArray = new JButton[10][10];
for (int r = 0; r < 10; r++) {
for (int c = 0; c < 10; c++) {
final JButton newButton = new JButton();
final Color originalColor = newButton.getBackground();
final Color highlightColor = Color.GREEN;
newButton.addMouseListener(new MouseAdapter() {
#Override
public void mouseEntered(final MouseEvent e) {
newButton.setBackground(highlightColor);
}
#Override
public void mouseExited(final MouseEvent e) {
newButton.setBackground(originalColor);
}
});
buttonArray[r][c] = newButton;
contentPanel.add(newButton);
}
}
frame.setContentPane(contentPanel);
frame.setSize(100, 100);
frame.setVisible(true);
}
}

delete/empty gridLayout from Panel

I have a grid layout that is 9x9 and generates Jtextareas to fill it. If the user presses a button i want the grid layout to become empty again so i can refill it again but with no relation to what it previously was filled with.
is there some sort of command like gridlayout.delete() or something?
I'm guessing that you want to clear the text components that are held by the GridLayout-using container (you don't tell us, and please understand that this is key information about your question). If so, put them into a collection such as an ArrayList and iterate through the list calling setText("") within the loop.
If you're using Java 8, then this "for loop" can be replaced with a forEach(...) call on a Stream. For example, if you have an ArrayList like so:
List<JTextComponent> textComponentList = new ArrayList<>();
Then you can clear all the text components it holds with this call:
textComponentList.stream().forEach(tc -> tc.setText(""));
For example:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
import javax.swing.text.JTextComponent;
#SuppressWarnings("serial")
public class ClearGrid extends JPanel {
private static final int ROWS = 9;
private static final int COLS = ROWS;
private static final int GAP = 2;
private static final Font FONT = new Font(Font.SANS_SERIF, Font.BOLD, 32);
private static final int FIELD_COLS = 2;
List<JTextComponent> textComponentList = new ArrayList<>();
public ClearGrid() {
JPanel gridPanel = new JPanel(new GridLayout(ROWS, COLS, GAP, GAP));
gridPanel.setBackground(Color.BLACK);
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
JTextField textField = new JTextField(FIELD_COLS);
textField.setFont(FONT);
textField.setHorizontalAlignment(JTextField.CENTER);
textComponentList.add(textField);
gridPanel.add(textField);
}
}
JPanel buttonPanel = new JPanel();
buttonPanel.add(new JButton(new ClearAllAction("Clear All", KeyEvent.VK_C)));
setLayout(new BorderLayout());
add(gridPanel);
add(buttonPanel, BorderLayout.PAGE_END);
}
private class ClearAllAction extends AbstractAction {
public ClearAllAction(String name, int mnemonic) {
super(name);
putValue(MNEMONIC_KEY, mnemonic);
}
#Override
public void actionPerformed(ActionEvent e) {
textComponentList.stream().forEach(tc -> tc.setText(""));
}
}
private static void createAndShowGui() {
JFrame frame = new JFrame("ClearGrid");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new ClearGrid());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
createAndShowGui();
});
}
}

Detect which JLabel is clicked

I have a JLabel[10] and I want to detect which label has been clicked and print which label of the label that has been clicked.
I created a JLabel array of 10.
Wrote a for loop to place an Image to every position of the label.
Added a MouseListener to check which label has been clicked.
The problem is I can't do this to get the source of my jLabelArr. The program will ask me to change my it to final.
if(e.getSource() == jLabelArr[i])
Full code
import java.awt.FlowLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class JavaLabels extends JFrame {
private JLabel[] jLabelArr;
private JPanel jLabelPanel = new JPanel();
public JavaLabels() {
setLayout(new FlowLayout());
jLabelArr = new JLabel[10];
for(int i =0; i < 10; i++) {
jLabelArr[i] = new JLabel(new ImageIcon("resources/image"));
jLabelPanel.add(jLabelArr[i]);
jLabelArr[i].addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
if(e.getSource() == jLabelArr[i]) {
System.out.println("Label" + i + "was clicked");
}
}
});
}
add(jLabelPanel);
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
pack();
setSize(400,600);
setLocationRelativeTo(null);
setVisible(true);
}
public static void main(String[] args) {
new JavaLabels();
}
}
For what you wanted there's nothing more than create a final int variable that will equal to the position of the for cycle
import java.awt.FlowLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class JavaLabels extends JFrame {
private JLabel[] jLabelArr;
private JPanel jLabelPanel = new JPanel();
public JavaLabels() {
setLayout(new FlowLayout());
jLabelArr = new JLabel[10];
for(int i =0; i < 10; i++) {
jLabelArr[i] = new JLabel(new ImageIcon("resources/image"));
jLabelPanel.add(jLabelArr[i]);
final int p = i;
jLabelArr[i].addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
System.out.println("Label" + p + "was clicked");
}
});
}
add(jLabelPanel);
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
pack();
setSize(400,600);
setLocationRelativeTo(null);
setVisible(true);
}
public static void main(String[] args) {
new JavaLabels().setVisible(true);
}
}
-> if(e.getSource() == jLabelArr[i]) is not needed in this case
1
public class JavaLabels extends JFrame {
private JLabel[] jLabelArr;
private JPanel jLabelPanel = new JPanel();
public JavaLabels() {
setLayout(new FlowLayout());
jLabelArr = new JLabel[10];
for (int i = 0; i < 10; i++) {
jLabelArr[i] = new JLabel(new ImageIcon("resources/image"));
jLabelPanel.add(jLabelArr[i]);
jLabelArr[i].addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
onMouseClicked(e);
}
});
}
add(jLabelPanel);
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
pack();
setSize(400, 600);
setLocationRelativeTo(null);
setVisible(true);
}
private void onMouseClicked(MouseEvent e) {
for (int i = 0; i < 10; i++)
if (e.getSource() == jLabelArr[i]) {
System.out.println("Label" + i + "was clicked");
}
}
public static void main(String[] args) {
new JavaLabels();
}
}
2
Implement MouseListener to JavaLabels class and jLabelArr[i].addMouseListener(this);

Java JFrame cannot create button(arraylist)

I wanted to create dynamic list of buttons using ArrayList. If I copy the method which is written AddButton in constructor , it works. However, If I run this method in ActionListener, it won't work. How do I resolve this ?
Code:
package HelloJFrame;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextField;
public class Main extends JFrame implements ActionListener {
private static final long serialVersionUID = 1L;
private JTextField text1;
public static void main(String[] args) {
// TODO Auto-generated method stub
new Main().setVisible(true);
}
public Main() {
super("Hello JFrame");// Set Title from JFrame constructor
setSize(600, 600);
setResizable(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLayout(new FlowLayout());
text1 = new JTextField(20);
// text.setSize(200, 20);
add(text1);
JButton submit = new JButton("Add Button");
submit.addActionListener(this);
submit.setActionCommand("ekle");
add(submit);
}
#Override
public void actionPerformed(ActionEvent e) {
AddButton(2);
}
public void AddButton(int number) {
ArrayList<JButton> buttons = new ArrayList<JButton>();
for (int i = 0; i < number; i++) {
buttons.add(new JButton("Button #" + i));
}
/*
* JButton button = new JButton("Click!");
* button.addActionListener(this); add(button);
*/
for (int i = 0; i < buttons.size(); i++) {
this.add(buttons.get(i));
}
}
}
After adding all the buttons to the frame you need to add
revalidate();
repaint();
to make sure the layout manager is invoked.
Also, method names should NOT start with an upper case character. "AddButton" should be "addButton".

Categories

Resources