I work java program language in netbeans. I want to move a jlabel box by means of use keybindings. Box can not move when ı keystroked. For example I keystroke w,a,s,d but box cannot move. When I press these keys, it should go up, down, right and left, but there is no movement in the program. The box stays where it is. What should do ı?
import java.awt.Color;
import java.awt.event.*;
import javax.swing.*;
public class BoxGame {
JFrame frame;
JLabel label;
Action upAction;
Action downAction;
Action leftAction;
Action rightAction;
BoxGame(){
frame = new JFrame("Keybinding");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(450,450);
frame.setLayout(null);
label = new JLabel();
label.setBackground(Color.red);
label.setBounds(100,100,100,100);
label.setOpaque(true);
upAction = new UpAction();
downAction = new DownAction();
leftAction = new LeftAction();
rightAction = new RightAction();
label.getInputMap().put(KeyStroke.getKeyStroke("w"), "upAction");
label.getActionMap().put("upAction",upAction);
label.getInputMap().put(KeyStroke.getKeyStroke("s"), "downAction");
label.getActionMap().put("downAction", downAction);
label.getInputMap().put(KeyStroke.getKeyStroke("a"), "leftAction");
label.getActionMap().put("leftAction", leftAction);
label.getInputMap().put(KeyStroke.getKeyStroke("d"), "rightAction");
label.getActionMap().put("rightAction", rightAction);
frame.add(label);
frame.setVisible(true);
}
public class UpAction extends AbstractAction{
#Override
public void actionPerformed(ActionEvent e) {
label.setLocation(label.getX(), label.getY()-10);
}
}
public class DownAction extends AbstractAction{
#Override
public void actionPerformed(ActionEvent e) {
label.setLocation(label.getX(), label.getY()+10);
}
}
public class LeftAction extends AbstractAction{
#Override
public void actionPerformed(ActionEvent e) {
label.setLocation(label.getX()-10, label.getY());
}
}
public class RightAction extends AbstractAction{
#Override
public void actionPerformed(ActionEvent e) {
label.setLocation(label.getX()+10, label.getY());
}
}
}
Start by making use of a more "gloabl" InputMap, the one you are using requires the component to be focusable AND have focus.
Avoid using KeyEvent.getKeyStroke(String), it does some weird things and isn't going to help you, instead, supply the actual KeyEvent, for example
InputMap inputMap = label.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_W, 0), "upAction");
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_S, 0), "downAction");
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_A, 0), "leftAction");
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_D, 0), "rightAction");
I'd also recommend making the time to learn about custom painting, as components don't tend to work well like this.
See Painting in AWT and Swing and Performing Custom Painting for more details
Related
I am still learning how to code in java and I could use a bit of help right now.
This is the current code I wrote. As you can see, it's a simple panel with a bunch of buttons and a slider. I want to make a different console output whenever I hit a different button. So if I hit Back, it's supposed to write Back in the console. If I scroll a bit on the slider, it's supposed to write the new value in the console. Stuff like that. I know it has to be done with actionListener and actionPerformed but after some experimenting I couldn't get it to work.
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Gui implements ActionListener {
// Adding all the goods
JFrame frame;
JPanel panel;
JButton endButton;
JButton backButton;
JButton calcButton;
JSlider maxIterations;
JLabel view;
Gui() {
// General
this.frame = new JFrame("Trying my best, I swear");
this.frame.setSize(500, 500);
this.frame.setVisible(true);
this.panel = new JPanel();
// Buttons
this.backButton = new JButton("Back");
this.calcButton = new JButton("Calc");
this.endButton = new JButton("End");
this.panel.add(this.endButton);
this.panel.add(this.calcButton);
this.panel.add(this.backButton);
this.frame.add(this.panel);
// Label
JLabel label1 = new JLabel();
label1.setText("Space Holer");
panel.add(label1);
// Slider
JSlider slider = new JSlider(JSlider.HORIZONTAL, 0, 30, 15);
panel.add(slider);
slider.setMinorTickSpacing(2);
slider.setMajorTickSpacing(5);
slider.setPaintTicks(true);
slider.setPaintLabels(true);
// Make the buttons do something
this.endButton.addActionListener(this);
}
public void actionPerformed(ActionEvent ae) {
System.out.println("End");
}
public static void main(String[] args) {
#SuppressWarnings("unused")
Gui m = new Gui();
}
}
You could...
Take advantage of the actionCommand property of the button, which is set to the ActionEvent when it's created. If you don't supply an actionCommand to the button yourself, it will default to the text value, so you could do something like
public class ButtonActionHandler implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
switch (e.getActionCommand()) {
case "Back":
System.out.println("Back");
break;
case "Calc":
System.out.println("Calc");
break;
case "End":
System.out.println("End");
break;
}
}
}
This is good if the ActionListener is external to the class where the buttons are defined, because you won't have access to the button references. It's also good, because you could have a number of buttons (including toolbar buttons and menu items) which do the same thing
You could...
Make use of the ActionListener's source property
public class ButtonActionHandler implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == backButton) {
System.out.println("Back");
} else if (e.getSource() == calcButton) {
System.out.println("Calc");
} else if (e.getSource() == endButton) {
System.out.println("End");
}
}
}
This is useful if the ActionListener in defined as a inner class to the parent class from where the buttons are defined
You could...
Use an anonymous class registered directly against the button...
endButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("End");
}
});
This is good where the button does a single, isolated task
You could...
Make use of the Action API which allows you to define a self contained unit of work, which can be used by buttons to configure themselves completely from it. This is useful where you have a repeated action which can be executed from different locations of the UI, like a "open file" action contained in the menu bar, tool bar and some wizard. You can even use it with the key bindings API for extended functionality
See How to use actions for more details
Need to add ActionListener to all buttons,
calcButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("calcButton");
// calculation for slider.
}
});
backButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("backButton");
}
});
then u get the different console output.
Call setVisible on jframe after you placed all components into it.
Add ActionListener to each button. Add ChangeListener to slider as it cannot have ActionListener.
See full code:
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.JSlider;
public class Gui implements ActionListener {
// Adding all the goods
JFrame frame;
JPanel panel;
JButton endButton;
JButton backButton;
JButton calcButton;
JSlider maxIterations;
JLabel view;
Gui() {
// General
this.frame = new JFrame("Trying my best, I swear");
this.frame.setSize(500, 500);
this.panel = new JPanel();
// Buttons
this.backButton = new JButton("Back");
this.calcButton = new JButton("Calc");
this.endButton = new JButton("End");
this.panel.add(this.endButton);
this.panel.add(this.calcButton);
this.panel.add(this.backButton);
this.frame.add(this.panel);
// Label
JLabel label1 = new JLabel();
label1.setText("Space Holer");
panel.add(label1);
// Slider
JSlider slider = new JSlider(JSlider.HORIZONTAL, 0, 30, 15);
panel.add(slider);
slider.setMinorTickSpacing(2);
slider.setMajorTickSpacing(5);
slider.setPaintTicks(true);
slider.setPaintLabels(true);
// Make the buttons do something
this.endButton.addActionListener(this);
this.backButton.addActionListener(this);
this.calcButton.addActionListener(this);
slider.addChangeListener(e -> {
Object source = e.getSource();
if (source instanceof JSlider) {
int value = ((JSlider) source).getValue();
System.out.println(value);
}
});
frame.pack();
this.frame.setVisible(true);
}
public void actionPerformed(ActionEvent ae) {
Object source = ae.getSource();
if (source instanceof JButton) {
String text = ((JButton) source).getText();
System.out.println(text);
}
}
public static void main(String[] args) {
#SuppressWarnings("unused")
Gui m = new Gui();
}
}
I was wondering how to add a focus gained event listener.
At the moment I have a Mouse Event which is being added to my
JTextareas
//=======================================================
// mouse drag event
//=======================================================
public static class genDrag extends MouseMotionAdapter {
JTextArea textarea;
// receive textarea as argument
public genDrag(JTextArea argTextarea) {
textarea = argTextarea;
}
// add drag functionality to argument
public void mouseDragged(MouseEvent E) {
Point p = SwingUtilities.convertPoint(textarea, E.getPoint(), gc_gui.cv_content);
textarea.setBounds((p.x - 40), (p.y - 15), 100, 30);
}
}
which I can then call using
//=======================================================
// apply mouse event
//=======================================================
JTextArea textarea = new JTextArea();
textarea.setBounds(50, 50, 100, 30);
textarea.addMouseMotionListener(new genDrag(textarea));
this works fine but I have been unable to reproduce the same
functionality for a focusGained event
//=======================================================
// mouse focus event
//=======================================================
public static class genFocus extends EventListener {
JTextArea textarea;
public genFocus() {
textarea = argTextarea;
}
public void focusGained(FocusEvent E) {
System.out.println("Focus Triggered");
}
}
The above doesn't seem happy at all
UPDATING CODE
static gui classGui;
public static void main(String[] args) {
classGui = new gui();
classGui.textarea.addMouseMotionListener(
new genDrag(classGui.textarea)
);
classGui.textarea.addFocusListener(
new genFocus(this)
);
classGui.frame.setVisible(true);
public static class gui {
JFrame frame;
JPanel panel;
JTextArea textarea;
public gui() {
frame = new JFrame();
// configure JFrame here
panel = new JPanel();
// configure JPanel here
textarea = new JTextArea();
textarea.setBounds(50, 50, 100, 30);
frame.add(textarea);
}
}
public static class genDrag extends MouseMotionAdapter {
JTextArea textarea;
public genDrag(JTextArea argTextarea) {
textarea = argTextarea;
}
public void mouseDragged(MouseEvent E) {
Point p = SwingUtilities.convertPoint(textarea, E.getPoint(), gc_gui.cv_content);
textarea.setBounds((p.x - 40), (p.y - 15), 100, 30);
}
}
public static class genFocus implements FocusListener {
JTextArea textarea;
public genFocus(JTextArea argTextarea) {
textarea = argTextarea;
}
public void focusGained(FocusEvent E) {
System.out.println("Focus gained");
}
public void focusLost(FocusEvent E) {
System.out.println("Focus lost");
}
}
}
To handle focus events, your handler needs to implement the FocusListener interface instead of EventListener.
Note that you need to add this handler via the addFocusListener. I don't think you did this, because if you had done this, you would have gotten a compiler error indicating what was wrong.
Use of the #Override annotation helps finding such errors. Put it above every method you think should override a parent method. If such a method does not actually override another method, the compiler will throw an error. This way you get informed of the mistake instead of your program failing silently.
you should add a event-listener to the control JTextArea then only it will be able to handle any event request.
JTextField textarea= new JTextField("Value");
textarea.addFocusListener(new genFocus(textarea)); //this peice of code will add an listener to you textarea Object of JTextField.
Your Mouse Listener will work because you have added a mouse event listener to your JTextArea.
textarea.addMouseMotionListener(new genDrag(textarea));//code to add MouseMotionListener.
but there is no FocusEvent is registerd with your JTextArea.
Thanks.
I think this is exactly what you need...
Just a hint: your class genFocus (prefer to follow code conventions: GenFocus) should implement FocusListener.
For school I have to make a small game which is based on Breakout.
I got my JFrame which does this:
game.setFocusable(true);
setContentpane(game);
in my game I am adding a inputhandler which extends Keylistener and implements JPanel.
setFocusable(true);
Inputhandler input = new Inputhandler();
addKeylistener(input);
It just doesn't seem to work, I've been writing a lot of tests but I can't see to get the input handle capture any keyPressed.
When I change my JFrame to:
add(game);
it works like it is meant to work but the problem I encounter when doing this way is painting my panels the correct way. I'm kinda stuck on this issue so please someone help me out.
Point I've reached now:
public Game(){
setFocusable(true);
requestFocus();
requestFocusInWindow();
getInputMap().put(KeyStroke.getKeyStroke("SPACE"), "pressed");
getActionMap().put("pressed", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("Space is pressed");
}
});
this.inputHandler = new InputHandler();
addKeyListener(this.inputHandler);
setPreferredSize(new Dimension(500,500));
}
If I had a dollar for every time this question were asked, I'd retire rich. As per previous similar questions...
Yes you would need to make the JPanel focusable for its KeyListener to work
And you'd also have to give it the focus, since being focusable is not enough. Usually this is achieved by calling requestFocusInWindow() on the listened to JPanel.
And nothing else can have the focus or steal the focus if the KeyListener is to continue functioning.
Which is one of several reasons why most of us recommend against use of KeyListeners for Swing applications
And usually in favor of using Key Bindings.
Edit
I've used your code and it works, both the key bindings and the KeyListener:
import java.awt.Dimension;
import java.awt.event.*;
import javax.swing.*;
public class Game extends JPanel {
private InputHandler inputHandler;
public Game() {
setFocusable(true);
requestFocus();
requestFocusInWindow();
getInputMap().put(KeyStroke.getKeyStroke("SPACE"), "pressed");
getActionMap().put("pressed", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("Space is pressed");
}
});
this.inputHandler = new InputHandler();
addKeyListener(this.inputHandler);
setPreferredSize(new Dimension(500, 500));
}
class InputHandler extends KeyAdapter {
#Override
public void keyPressed(KeyEvent e) {
System.out.println("key pressed");
}
#Override
public void keyReleased(KeyEvent e) {
System.out.println("key released");
}
}
private static void createAndShowGui() {
Game mainPanel = new Game();
JFrame frame = new JFrame("Game");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
I want to close my JDialog by hitting the "enter" key on my keyboard. how can I do that? thank you!
NOTE:
I want to do this, without any button involved.
THank you!
One way:
You could give it a close JButton
whose ActionListener has code that closes the dialog,
And make that button the default button for the dialog's rootpane.
e.g.,
myDialog.getRootPane().setDefaultButton(exitButton);
Option two:
Use Key Bindings to bind the enter key to exit code in an AbstractAction.
e.g.,
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.*;
public class DemoDialog {
public static void main(String[] args) {
JFrame frame = new JFrame("Frame");
frame.add(Box.createRigidArea(new Dimension(400, 300)));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
final JDialog dialog = new JDialog(frame, "Dialog", true);
// set binding
int condition = JPanel.WHEN_IN_FOCUSED_WINDOW;
InputMap inputMap = ((JPanel) dialog.getContentPane()).getInputMap(condition);
ActionMap actionMap = ((JPanel) dialog.getContentPane()).getActionMap();
String enter = "enter";
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), enter);
actionMap.put(enter, new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
dialog.dispose();
}
});
dialog.add(Box.createRigidArea(new Dimension(200, 200)));
dialog.pack();
dialog.setLocationRelativeTo(frame);
dialog.setVisible(true);
}
}
I would like to say first that 'Hovercraft Full Of Eels' solution is more elegant than this one and more closely in the spirit of the JDialog and Swing API. However, to offer an alternative here is a basic example of using a KeyListener on your JDialog that will do as you need without adding a button;
public class Test {
public static void main(String[] args) {
JDialog jd = new JDialog();
// Add and define the KeyListener here!
jd.addKeyListener(new KeyListener(){
#Override
public void keyTyped(KeyEvent e) {
// Nothing
}
#Override
public void keyPressed(KeyEvent e) {
// Nothing
}
#Override
public void keyReleased(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_ENTER){
JDialog d = (JDialog)e.getSource();
d.dispose();
}
}
});
// End key listener code
jd.setVisible(true);
}
}
The important/relevant code is between the two main comments. This is a compilable example, so you can copy paste this into a new file and run it to view the effects.
Me and a friend are trying to make an mp3 player with buttons in java, however once the first button is clicked it resizes all butttons on the second menu.
Any information on how to keep the buttons from rezising would be greatly appreciated.
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
public class Player extends JFrame {
class CustomPanel extends JPanel{ //create image
public void paintComponent (Graphics painter){
Image pic = Toolkit.getDefaultToolkit().getImage("playerBase.jpg");
if(pic != null) painter.drawImage(pic, 0, 0, this);
}
}
public static void main(String[] args) {
Player gui = new Player();
gui.go();
}
public void go() {
JFrame frame = new JFrame("MP3 Player."); //Creates window.
CustomPanel base = new CustomPanel(); //Makes the image into a panel.
JButton button1 = new JButton("Artists");
JButton button2 = new JButton("Genres");
JButton button3 = new JButton("Songs");
JButton button4 = new JButton("TEST");
JButton button5 = new JButton("TEST");
button1.setHorizontalAlignment(SwingConstants.LEFT);
button2.setHorizontalAlignment(SwingConstants.LEFT);
button3.setHorizontalAlignment(SwingConstants.LEFT);
button4.setHorizontalAlignment(SwingConstants.LEFT);
button5.setHorizontalAlignment(SwingConstants.LEFT);
button1.addActionListener(new Button1Listener());
button2.addActionListener(new Button2Listener());
button3.addActionListener(new Button3Listener());
button4.addActionListener(new Button4Listener());
button5.addActionListener(new Button5Listener());
base.add(button1);
base.add(button2);
base.add(button3);
base.add(button4);
base.add(button5);
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.setSize(304, 360);
frame.setResizable(false);
frame.add(base);
frame.setVisible(true);
button1.setSize(280, 30);
button1.setLocation(10,10);
button1.setBackground(Color.BLACK);
button1.setForeground(Color.white);
button2.setSize(280, 30);
button2.setLocation(10,40);
button2.setBackground(Color.BLACK);
button2.setForeground(Color.white);
button3.setSize(280, 30);
button3.setLocation(10,70);
button3.setBackground(Color.BLACK);
button3.setForeground(Color.white);
button4.setSize(280, 30);
button4.setLocation(10,100);
button4.setBackground(Color.BLACK);
button4.setForeground(Color.white);
button5.setSize(280, 30);
button5.setLocation(10,130);
button5.setBackground(Color.BLACK);
button5.setForeground(Color.white);
}
//These are the actions for the 5 buttons.
//Need to get buttons straight once first button is clicked
class Button1Listener implements ActionListener {
public void actionPerformed(ActionEvent event) {
if (event.getSource() instanceof JButton) {
JButton clickedButton = (JButton) event.getSource();
clickedButton.setSize(280, 30);
clickedButton.setLocation(10,10);
clickedButton.setBackground(Color.BLACK);
clickedButton.setForeground(Color.white);
String buttonText = clickedButton.getText();
if (buttonText.equals("Artists")) {
System.out.println("Artists");
clickedButton.setText("Back");
}
else if (buttonText.equals("Back")) {
System.out.println("Back");
}
}
}
}
//these are just place holders for the other buttons.
class Button2Listener implements ActionListener {
public void actionPerformed(ActionEvent event) {
System.out.println("Genres");
}
}
class Button3Listener implements ActionListener {
public void actionPerformed(ActionEvent event) {
System.out.println("Songs");
}
}
class Button4Listener implements ActionListener {
public void actionPerformed(ActionEvent event) {
System.out.println("TEST");
}
}
class Button5Listener implements ActionListener {
public void actionPerformed(ActionEvent event) {
System.out.println("TEST");
}
}
}
Set the layout Manager to null on your CustomPanel base.
base.setLayout(null);
If you want to force the size and location of your components (using setBounds()), then you need to remove the layout manager.
However, LayoutManagers provide better UI experience across different platforms as they will adapt to differences. LayoutManager's perform the sizing and positionning of the components based on preferredSize and constraints. If you have never used them or heard from them, you should really consider looking into them: http://docs.oracle.com/javase/tutorial/uiswing/layout/using.html
well, I didn't see a menu code. However, by default, the Layout manager for Panel is Flow Layout. Since you did not specify any layout, Flow Layout is assumed, and any sizing you specify will largely be ignored.
So, as Guillaume suggests, set it to null, so you can position things absolutely. Or use more complex layouts depending on your needs. Have a look at how to use layout managers in the swing tutorial. GridBagLayout is the most complex (difficult to use), unless you use some sort of gui builder. Other candidates are BorderLayout, GridLayout among others. Read through the examples to see which one fits your case.