Java: KeyListener Not working - java

I'm fairly new to Java, and I have totally self taught my self to this point.
Right now I am trying to add a KeyListener to my JFrame class, I have no idea what I'm doing wrong and need some help. Any other tips are welcome.
My JFrame class:
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.*;
public class TestJavaFrame implements ActionListener, KeyListener {
private static JFrame frame = new JFrame();
// Componenets
JLabel timeinmslabel = new JLabel("Enter the time in miliseconds:");
JTextField timeinms = new JTextField();
JRadioButton checkBox = new JRadioButton();
JRadioButton checkBox2 = new JRadioButton();
private boolean amountoftimes = false;
public TestJavaFrame(String windowname) {
frame.setName(windowname);
frame.setResizable(true);
frame.setSize(900, 500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocation(150, 50);
// JPanel
JPanel panel = new JPanel();
panel.setLayout(null);
panel.setBounds(frame.getBounds());
// Bounds for components
timeinmslabel.setBounds((int) (frame.getBounds().getX() / 2), 125, 200, 25);
timeinms.setBounds((int) (frame.getBounds().getX() / 2 + 185), 125, 200, 25);
checkBox.setBounds((int) (frame.getBounds().getX() / 2 + 185), 40, 200, 25);
checkBox2.setBounds((int) (frame.getBounds().getX() / 2 + 185), 70, 200, 25);
// Action Listeners
checkBox.addActionListener(this);
frame.addKeyListener(this);
// edit components
checkBox.setText("Use clicked amount of times.");
// add components
panel.add(timeinmslabel);
panel.add(timeinms);
panel.add(checkBox);
panel.add(checkBox2);
frame.add(panel);
frame.setVisible(true);
}
public void actionPerformed(ActionEvent e) {
System.out.println(e);
}
#Override
public void keyPressed(KeyEvent e) {
System.out.println(e.getKeyChar());
}
#Override
public void keyReleased(KeyEvent e) {
System.out.println(e.getKeyChar());
}
#Override
public void keyTyped(KeyEvent e) {
System.out.println(e.getKeyChar());
}
}
If you need my main, I'm perfectly fine with posting it, all it does right now is create this gui though.

So when the user hits the specific key it stops the auto clicker
Yes you can add the Key Binding to the panel.
A better approach is to create a menu bar for the various Actions support by your application. Then you can have menu items to start/stop the clicker. When you create the menu items you can then assign an accelerator to the menu item and the menu item will create the key bindings for you automatically.
This is a better solution because the "key binding" is self documenting since it is part of the menu item.
Read the section from the Swing tutorial on How to Use Menus for more information and working examples to get you started.
as I said I'm trying to learn here.
Keep a link to the tutorial handy for all Swing basics. There are also sections on "Key Bindings" and "How to Use Actions".

Related

Why doesn't mousePress do anything?

I am new to Java and I'm trying to make an auto clicker. It works like this. when you click a button, the application starts clicking (also works when you press s), and when you press "w" the application stops clicking. My main issue currently is I can't manage to make my application click :V. (I also have a "main.java" for startup) Here's my code vvvvvvv
package copy;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.KeyAdapter;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Game
implements ActionListener{
JFrame frame;
JLabel label;
JButton button;
Action ON;
Action OFF;
private static Robot bot;
public static boolean status = false;
Game(){
ON = new statusON();
OFF = new statusOFF();
frame = new JFrame("Bullet Chicken Clicker");
label = new JLabel();
button = new JButton("turn on?");
frame.setSize(400, 400);
frame.setLocation(600, 150);
frame.setVisible(true);
frame.setAlwaysOnTop(true);
frame.add(label);
frame.add(button);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
label.getInputMap().put(KeyStroke.getKeyStroke('w'), "OFF");
label.getActionMap().put("OFF", OFF);
label.getInputMap().put(KeyStroke.getKeyStroke('w'), "upAction");
label.getActionMap().put("upAction", ON);
label.getInputMap().put(KeyStroke.getKeyStroke('s'), "downAction");
label.getActionMap().put("downAction", OFF);
button.setPreferredSize(new Dimension(40, 40));
button.setOpaque(true);
button.setForeground(Color.BLACK);
button.setBounds(125, 150, 150, 30);
button.setVisible(true);
button.addActionListener(this);
button.setFocusable(false);
}
private void clicky() {
while (status == true);
bot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
bot.delay(300);
bot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
bot.delay(300);
}
public static void robot() {
try {
bot = new Robot();
} catch (AWTException e2) {
e2.printStackTrace();
}
}
public class statusON extends AbstractAction{
#Override
public void actionPerformed(ActionEvent e) {
status = true;
System.out.print(status);
}
}
public class statusOFF extends AbstractAction{
#Override
public void actionPerformed(ActionEvent e) {
status = false;
System.out.print(status);
}
}
#Override
public void actionPerformed(ActionEvent e) {
status = true;
System.out.print(status);
}
}
My main issue currently is I can't manage to make my application click :V.
Well, you don't assign a key binding to the "V" key. You define the binding for "W" twice.
Having said that your code is still incorrect and will cause you problems in the future:
you are adding two components to the BorderLayout.CENTER
components should be added to the frame BEFORE the frame is made visible
you are using the wrong InputMap
From the tutorial given to you in your last question there are 3 InputMaps. The default InputMap will only work when the component has focus. In your incorrect example is just happens that the label does have focus. However, if you add more components it will likely not retain focus.
In the case of a game the easiest way to make sure you game responds to the KeyStroke is to bind the KeyStroke to the InputMap of the JRootPane of the frame. Then it doesn't matter which component on the frame has focus, the Action will be invoked.
So your code should be something like:
JRootPane rootPane = frame.getRootPane();
InputMap im = rootPane.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
im.put(KeyStroke.getKeyStroke('v'), "OFF");
rootPane.getActionMap().put("OFF", OFF);
im.put(KeyStroke.getKeyStroke('w'), "upAction");
rootPane.getActionMap().put("upAction", ON);
im.put(KeyStroke.getKeyStroke('s'), "downAction");
rootPane.getActionMap().put("downAction", OFF);
There is no need for the JLabel.

Event dispatch thread exception?

Here is my code, I run it on eclipse and it displays the frame the button and the field, using the button should return the value of the equation typed in the field fe. When i put 2+2 in the field and click "oblicz" it should return 4 but it does not, and it drops some weird exception. Am I missing something?
static JTextField pole1;
public static void main(String[]args)
{
JFrame frame = new JFrame("applet 1.0");
frame.setSize(700, 600);
frame.setLocation(300, 100);
frame.setResizable(false);
frame.setLayout(null);
frame.setVisible(true);
// pole
pole1 = new JTextField();
pole1.setBounds(10, 10, 230, 50);
Font F1 = new Font("Comic Sans",Font.BOLD,20);
pole1.setFont(F1);
pole1.setHorizontalAlignment(JTextField.RIGHT);
frame.add(pole1);
// button
JButton button = new JButton("oblicz");
button.setBounds(10, 80, 100, 70);
button.setBorder(null);
frame.add(button);
button.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent arg0)
{
{
String str = pole1.getText();
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine engine = mgr.getEngineByName("JavaScript");
String foo = str;
try
{
pole1.setText(String.valueOf(engine.eval(foo)));
}
catch (ScriptExecption e)
{
}
}
}
});
Your code as written worked for me.
However, I made some changes to your code to use Swing more effectively.
I removed all the code from the main method and replaced it with a call to the SwingUtilities invokeLater method. The invokeLater method puts the creation and use of the Swing components on the Event Dispatch thread. Oracle and I demand that all Swing applications start on the Event Dispatch thread.
I put the JTextField and JButton on a JPanel. Do not add Swing components other than JPanel or other panel type components to a JFrame.
I separated the creation of a JFrame from the creation of a JPanel. Divide and conquer. Separation of concerns makes the code easier to read and test.
I created the JPanel and JFrame before I made it visible. Call the JFrame methods in the order I posted.
I removed the null layout and the absolute positioning of the Swing components. Swing was designed to be used with Swing layout managers. Learn them. Use them.
I used a couple of empty JPanel borders to add some white space around the components.
I fixed some syntax problem in your action listener. In my Eclipse IDE, I deleted your try / catch block and let Eclipse generate the try / catch block. I added a printStackTrace method call so that any exception would print out as a stack trace.
Here's the code.
package com.ggl.testing;
import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class JavascriptCalculator implements Runnable {
private JButton button;
private JTextField pole1;
public static void main(String[] args) {
SwingUtilities.invokeLater(new JavascriptCalculator());
}
#Override
public void run() {
JFrame frame = new JFrame("Applet 1.0");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createPanel());
frame.pack();
frame.setLocationByPlatform(true);
frame.getRootPane().setDefaultButton(button);
frame.setVisible(true);
}
private JPanel createPanel() {
JPanel panel = new JPanel();
panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
panel.setLayout(new BorderLayout());
// pole
JPanel polePanel = new JPanel();
polePanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 10, 0));
pole1 = new JTextField(20);
Font f1 = new Font("Comic Sans", Font.BOLD, 20);
pole1.setFont(f1);
pole1.setHorizontalAlignment(JTextField.RIGHT);
polePanel.add(pole1);
panel.add(polePanel, BorderLayout.CENTER);
// button
button = new JButton("oblicz");
panel.add(button, BorderLayout.SOUTH);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
String str = pole1.getText().trim();
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine engine = mgr.getEngineByName("JavaScript");
String foo = str;
try {
pole1.setText(String.valueOf(engine.eval(foo)));
} catch (ScriptException e) {
e.printStackTrace();
}
}
});
return panel;
}
}

Java Swing. Opening a new JPanel from a JButton and making the buttons pretty

I am trying to build a little program that has a main GUI with 2 buttons. One button closes the program, the other I want to open a new JPanel that will have text fields etc.
I would like to be able to make the buttons so they look like normal application buttons I guess, nice and square, equal size etc. etc., I am not sure how to do this though.
Also, I am unsure how to open a new JFrame from a button click.
GUI Code:
package practice;
public class UserInterface extends JFrame {
private JButton openReportSelection = new JButton("Open new Window");
private JButton closeButton = new JButton("Close Program");
private JButton getCloseButton() {
return closeButton;
}
private JButton getOpenReportSelection() {
return openReportSelection;
}
public UserInterface() {
mainInterface();
}
private void mainInterface() {
setTitle("Program Information Application");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel centerPanel = new JPanel(new GridLayout(0, 3));
centerPanel.add(openReportSelection);
centerPanel.add(closeButton);
getCloseButton().addActionListener(new Listener());
add(centerPanel, BorderLayout.CENTER);
setSize(1000, 200);
setVisible(true);
}
private void addReportPanel() {
JPanel reportPanel = createNewPanel();
getContentPane().add(reportPanel, BorderLayout.CENTER);
}
private JPanel createNewPanel() {
JPanel localJPanel = new JPanel();
localJPanel.setLayout(new FlowLayout());
return localJPanel;
}
}
ActionListener Class code:
package practice;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class Listener implements ActionListener {
public void actionPerformed(ActionEvent ae) {
System.exit(0);
}
}
EDIT: I think opening a new JPanel would be the way to go rather than a JFrame. What would be the best way to do this from a Jbutton click?
Start by using a different layout manager, FlowLayout or GridBagLayout might work better
JPanel centerPanel = new JPanel(new FlowLayout());
centerPanel.add(openReportSelection);
centerPanel.add(closeButton);
These layouts will honour the preferred sizes of your buttons
As for opening another window, well, you've already create one, so the process is pretty much the same. Having said that, you might consider having a look at The Use of Multiple JFrames: Good or Bad Practice? before you commit yourself to far.
A better approach might be to use a JMenuBar and JMenuItems to act as the "open" and "exit" actions. Take a look at How to Use Menus then you could use a CardLayout to switch between views instead, for example
From a pure design perspective (I know it's only practice, but perfect practice makes perfect), I wouldn't extend anything from JFrame and instead would rely on building your main GUIs around something like JPanel instead.
This affords you the flexibility to decide how to use these components, as you could add them to frames, applets or other components...
If you want your buttons to have the native Look and Feel (L&F), add the following to your program:
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
Instead of opening another JFrame, you'll want to instead use a JDialog, typically with modality set.
In Java, you can only extend one class and therefore you should consider carefully whether it is appropriate or not to extend another class. You could ask yourself, "Am I actually extending the functionality of JFrame?" If the answer is no, then you actually want to use an instance variable.
Below is an example program from the above recommendations:
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.EventQueue;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
public class MyApplication {
private JFrame myframe; // instance variable of a JFrame
private JDialog mydialog;
public MyApplication() {
super();
myframe = new JFrame(); // instantiation
myframe.setSize(new Dimension(400, 75));
myframe.getContentPane().setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));
JButton btnNewWindow = new JButton("Open New Window");
btnNewWindow.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
mydialog = new JDialog();
mydialog.setSize(new Dimension(400,100));
mydialog.setTitle("I got you! You can't click on your JFrame now!");
mydialog.setModalityType(Dialog.ModalityType.APPLICATION_MODAL); // prevent user from doing something else
mydialog.setVisible(true);
}
});
myframe.getContentPane().add(btnNewWindow);
JButton btnCloseProgram = new JButton("Close Program :(");
btnCloseProgram.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
myframe.dispose();
}
});
myframe.getContentPane().add(btnCloseProgram);
myframe.setVisible(true);
}
public static void main(String[] args) {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException
| UnsupportedLookAndFeelException e1) {
e1.printStackTrace();
}
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
new MyApplication();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}
I am not sure from your question what do wou want to do. Do you want to open a new JFrame or do you want to add a JPanel to the existing frame.
To open a new JFrame using a button, create an instance of the JFrame in the actionPerformed method of the button. In your case it would look similar to this:
openReportSelection.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
JFrame frame = new JFrame();
// Do something with the frame
}
}
});
You're probably looking up to create and open a new JFrame. For this purpose, first you need to instantiate an object from JFrame Class. As an example, Let's instantiate a new JFrame with specific boundries.
JFrame testFrame = new testFrame();
verificationFrame.setBounds(400, 100, 250, 250);
Then you need to create your components like JButtons, Jlabels and so on, and next you should add them to your new testFrame object.
for example, let's create a Jlabel and add it testFrame:
JLabel testLbl = new JLabel("Ok");
testLbl.setBounds(319, 49, 200, 30);
testFrame.getContentPane().add(testLbl);
Now let's suppose you have a Jbutton which is named "jbutton" and by clicking it, a new JFrame object will be created and the Jlabel component will be added to it:
jButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
JFrame testFrame = new testFrame();
verificationFrame.setBounds(400, 100, 250, 250);
Label testLbl = new JLabel("Ok");
testLbl.setBounds(319, 49, 200, 30);
testFrame.getContentPane().add(testLbl);
}}});

Java buttons repaint

look at this simple code:
Main.java :
package CarManager;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class Main extends JFrame {
private static final long serialVersionUID = 1L;
static int width = 400;
static int height = width / 16 * 9;
static String title = "Car Manager";
JButton viewTables = new JButton("View tables");
JButton clients = new JButton("Clients");
JButton search = new JButton("Search");
JButton viewCars = new JButton("View all");
JButton viewRent = new JButton("Rent a car");
JButton viewBuy = new JButton("Buy a car");
JButton viewAccessory = new JButton("Accessory");
public Main() {
setLayout(null);
setLocationRelativeTo(null);
setTitle(title);
setSize(width, height);
setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
JLabel background = new JLabel(new ImageIcon("res\\background2.jpg"));
add(background);
background.setSize(width, height);
add(viewTables);
add(clients);
add(search);
viewTables.setBounds(20, 20, 110, 30);
clients.setBounds(20, 70, 110, 30);
search.setBounds(20, 120, 110, 30);
viewTables.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
add(viewCars);
viewCars.setBounds(260, 20, 110, 20);
add(viewRent);
viewRent.setBounds(260, 50, 110, 20);
add(viewBuy);
viewBuy.setBounds(260, 80, 110, 20);
add(viewAccessory);
viewAccessory.setBounds(260, 110, 110, 20);
}
});
viewCars.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
View view = new View();
view.addWindowListener(new WindowPlug(Main.this));
setVisible(false);
}
});
}
public static void main(String args[]) {
new Main();
}
}
View.java:
package CarManager;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class View extends JFrame {
private static final long serialVersionUID = 1L;
int width = 400;
int height = width / 16 * 9;
String title = "View all Cars";
public View() {
setLayout(null);
setLocationRelativeTo(null);
setTitle(title);
setSize(width, height);
setResizable(false);
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
setVisible(true);
JLabel background = new JLabel(new ImageIcon("res\\background2.jpg"));
add(background);
background.setSize(width, height);
}
}
and WindowPlug.java:
package CarManager;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class WindowPlug extends WindowAdapter {
private Main mainFrame;
public WindowPlug(Main mainFrame) { // when creating an instance of this
// WindowAdapter, tell it with which
// Main Window you are working with
this.mainFrame = mainFrame;
}
public void windowClosing(WindowEvent e) {
mainFrame.setVisible(true);
mainFrame.revalidate();
}
}
when i click view tables and then view all (those are the buttons that work for now)
and the first window hides and a new window appears, now when i close the second window the first one appears visible but the buttons are not visible, i have to hover over with the mouse for them to be visible again. ive tried mainFrame.revalidate(); and
mainFrame.repaint();
but no result
im using windows 8.1 pro
One problem with your code, and I'm not sure if this is the main problem since your code works fine on my system, is that you're calling setVisible(true) on your main window before you've added all your components. It should only be called after all components have been added.
Other problems unrelated to your main question:
You should avoid using null layout. While using null layout may seem to a newbie the better way to create complex GUI's, it's a fallacy, and more you create Swing GUI's the more you learn to respect and use the layout managers and see that these creatures help immensely in creating flexible, beautiful and if need be, complex GUI's. Then you can let them size them selves appropriately by calling pack() prior to setting them visible.
It appears that you really want to use a CardLayout to swap views on one GUI rather than spitting multiple GUI's at the user.
If you absolutely must display a dialog window, then you should use a JDialog, not a JFrame. If you used a modal JDialog, you wouldn't be needing a WindowListener.
Edit
OK, a big problem I see is that you're using null layout and adding a JLabel that covers the whole contentPane, and then adding components to the same contentPane.
Instead, make the JLabel your contentPane, and then add your JButtons, etc to it.
But make sure that the JLabel's opaque property is set to true first.
Edit 2
If you need to use an image as a background image you can:
Put the Image in an ImageIcon, put the Icon in a JLabel, and again use the JLabel as your contentPane. Again, you will need to make the JLabel opaque by calling setOpaque(true) on it. This works well if you don't want to change the size of the image or the window.
If you do need to change the size of the image, better to have a JPanel draw the image in its paintComponent(Graphics g) method, and then use this JPanel as your contentPane.
Once you've created your contentPane, then set its layout and add your components to it.
Then call setContentPane(newContentPane) on your top level window and pass in the new contentPane.

Can't get my Jscrollpane working in my Jtextarea

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);

Categories

Resources