Please help me guys. I just can't run the KeyListener. But I have added everything you need (i think). I really have no idea what's wrong with this code. I added a Key Listener, implemented a key listener and included all classes so what did I forgot? :/
import java.awt.Button;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Rectangle;
/******Key classes are included*********/
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.IOException;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.Timer;
/********Key listener is Implemented********/
public class Game extends JPanel implements KeyListener,Runnable
{
JPanel m_mainPanel;
Thread moveBall = new Thread();
Timer t = new Timer(5, this);
int radius = 50;
int posx = 400;
int posy = 400;
int RectPosX = 10;
int RectPosY = 400;
int velocityX = 0;
int velocityY = 0;
//Konstruktor
public Game(JPanel mainPanel) {
m_mainPanel = mainPanel;
setLayout(new GridLayout(3, 1));
JPanel north_panel = new JPanel();
north_panel.setLayout(new FlowLayout(FlowLayout.LEFT));
/**********I didn't forget this********/
this.addKeyListener(this);
/*******Focus is set**********/
setFocusable(true);
setFocusTraversalKeysEnabled(false);
add(north_panel);
}
//Painting rectangle
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setColor(Color.BLACK);
g.fillRect(RectPosX, RectPosY, radius, radius);
}
//the key event wich isn't called
#Override
public void keyPressed(KeyEvent e)
{
System.out.println("Key pressed");
if(e.getKeyCode() == KeyEvent.VK_UP)
{
velocityY = 10;
}
if(e.getKeyCode() == KeyEvent.VK_DOWN)
{
velocityY = -10;
}
}
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
}
#Override
public void run()
{
while(true)
{
repaint();
}
}
}
Here's a little example MCVE:
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Main extends JPanel{
public Main(){
addKeyListener(new KeyListener(){
#Override
public void keyTyped(KeyEvent e) {
System.out.println("Typed: " + e.getKeyChar());
}
#Override
public void keyPressed(KeyEvent e) {
System.out.println("Pressed: " + e.getKeyChar());
}
#Override
public void keyReleased(KeyEvent e) {
System.out.println("Released: " + e.getKeyChar());
}
});
}
public static void main(String[] args){
JFrame frame = new JFrame("test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new Main());
frame.setSize(300, 300);
frame.setVisible(true);
}
}
This program exhibits the same problem you're having: the key listener is never called! This is because the focus is on the JFrame, not the JPanel.
To change this, you have to make the JPanel focusable. You do this by simply calling the setFocusable() method. Now your JPanel will have the focus:
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Main extends JPanel{
public Main(){
addKeyListener(new KeyListener(){
#Override
public void keyTyped(KeyEvent e) {
System.out.println("Typed: " + e.getKeyChar());
}
#Override
public void keyPressed(KeyEvent e) {
System.out.println("Pressed: " + e.getKeyChar());
}
#Override
public void keyReleased(KeyEvent e) {
System.out.println("Released: " + e.getKeyChar());
}
});
setFocusable(true);
}
public static void main(String[] args){
JFrame frame = new JFrame("test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new Main());
frame.setSize(300, 300);
frame.setVisible(true);
}
}
More complicated programs might require the requestFocusInWindow() function. Or you might want to look into using KeyBindings instead. But your main problem is caused by focus issues.
Related
I have a button. I want to change the background after I click on it. My problem here is the button auto call paintComponent(). How can prevent this? I expect after clicking the button the button will be blue, but it will still be red.
package test;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class ButtonDemo extends JButton implements ActionListener{
public ButtonDemo() {
this.setText("BUTTON TEXT");
this.addActionListener(this);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
setBackground(Color.RED);
}
public static void main(String[] args){
JFrame frame = new JFrame();
JPanel contentPane = new JPanel();
frame.setContentPane(contentPane);
contentPane.add(new ButtonDemo());
frame.setSize(500, 500);
frame.setVisible(true);
}
#Override
public void actionPerformed(ActionEvent e) {
this.setBackground(Color.BLUE);
}
}
My personal gut feeling is that JButton is probably not suited to your desired goal.
Essentially, you want to control when and how the "selected" state of the piece is changed.
Personally, I would have some kind of controller which monitored the mouse events in some way (probably having the piece component delegate the event back to the controller) and some kind of model which control when pieces become selected, this would then notify the controller of the state change and it would make appropriate updates to the UI.
But that's a long process to setup. Instead, I'm demonstrating a simple concept where a component can be selected with the mouse, but only the controller can de-select. In this example, this will allow only a single piece to be selected
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.LineBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new GridLayout(5, 5));
ChangeListener listener = new ChangeListener() {
private PiecePane selectedPiece;
#Override
public void stateChanged(ChangeEvent e) {
if (!(e.getSource() instanceof PiecePane)) { return; }
PiecePane piece = (PiecePane) e.getSource();
// Want to ignore events from the selected piece, as this
// might interfer with the changing of the pieces
if (selectedPiece == piece) { return; }
if (selectedPiece != null) {
selectedPiece.setSelecetd(false);
selectedPiece = null;
}
selectedPiece = piece;
}
};
for (int index = 0; index < 5 * 5; index++) {
PiecePane pane = new PiecePane();
pane.addChangeListener(listener);
add(pane);
}
}
}
public class PiecePane extends JPanel {
private boolean selecetd;
private Color selectedBackground;
private Color normalBackground;
private MouseListener mouseListener;
public PiecePane() {
setBorder(new LineBorder(Color.DARK_GRAY));
mouseListener = new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
setSelecetd(true);
}
};
setNormalBackground(Color.BLUE);
setSelectedBackground(Color.RED);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(50, 50);
}
#Override
public void addNotify() {
super.addNotify();
addMouseListener(mouseListener);
}
#Override
public void removeNotify() {
super.removeNotify();
removeMouseListener(mouseListener);
}
public void addChangeListener(ChangeListener listener) {
listenerList.add(ChangeListener.class, listener);
}
public void removeChangeListener(ChangeListener listener) {
listenerList.remove(ChangeListener.class, listener);
}
protected void fireSelectionChanged() {
ChangeListener[] listeners = listenerList.getListeners(ChangeListener.class);
if (listeners.length == 0) {
return;
}
ChangeEvent evt = new ChangeEvent(this);
for (int index = listeners.length - 1; index >= 0; index--) {
listeners[index].stateChanged(evt);
}
}
public boolean isSelected() {
return selecetd;
}
public void setSelecetd(boolean selecetd) {
if (selecetd == this.selecetd) { return; }
this.selecetd = selecetd;
updateSelectedState();
fireSelectionChanged();
}
public Color getSelectedBackground() {
return selectedBackground;
}
public void setSelectedBackground(Color selectedBackground) {
this.selectedBackground = selectedBackground;
updateSelectedState();
}
public Color getNormalBackground() {
return normalBackground;
}
public void setNormalBackground(Color normalBackground) {
this.normalBackground = normalBackground;
updateSelectedState();
}
protected void updateSelectedState() {
if (isSelected()) {
setBackground(getSelectedBackground());
} else {
setBackground(getNormalBackground());
}
}
}
}
I created a toggle button.
You set the primary color and the alternate color in the class constructor.
When you call the switchColors method, the JButton background changes from the primary color to the alternate color. When you call the switchColors method again, the JButton background changes from the alternate color to the primary color.
In the following example, I put the switchColors method in the actionListener so you can see the color change. Each time you left-click on the JButton, the background color changes.
You would call the switchColors method when you want the JButton background to change from blue to red, and again when you want the JButton background to change from red to blue. It's under your control.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class ButtonDemo extends JButton
implements ActionListener {
private static final long serialVersionUID = 1L;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame("Button Demo");
frame.setDefaultCloseOperation(
JFrame.EXIT_ON_CLOSE);
JPanel contentPane = new JPanel();
contentPane.setLayout(new BorderLayout());
frame.setContentPane(contentPane);
contentPane.add(new ButtonDemo(Color.BLUE,
Color.RED));
frame.setSize(300, 300);
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
});
}
private boolean primaryBackground;
private Color primaryColor;
private Color alternateColor;
public ButtonDemo(Color primaryColor,
Color alternateColor) {
this.primaryColor = primaryColor;
this.alternateColor = alternateColor;
this.primaryBackground = true;
this.setText("BUTTON TEXT");
this.setBackground(primaryColor);
this.addActionListener(this);
}
public void switchColors() {
primaryBackground = !primaryBackground;
Color color = primaryBackground ? primaryColor :
alternateColor;
this.setBackground(color);
}
#Override
public void actionPerformed(ActionEvent e) {
switchColors();
}
}
If you want to change the background for a short while you can do it with swing Timer:
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class ButtonDemo extends JButton implements ActionListener{
private static final int DELAY = 600; //milliseconds
private final Timer timer;
public ButtonDemo() {
this.setText("BUTTON TEXT");
this.addActionListener(this);
Color defaultCloor = getBackground();
timer = new Timer(DELAY, e-> setBackground(defaultCloor));
timer.setRepeats(false);
}
public static void main(String[] args){
JFrame frame = new JFrame();
JPanel contentPane = new JPanel();
frame.setContentPane(contentPane);
contentPane.add(new ButtonDemo());
frame.setSize(300, 200);
frame.setVisible(true);
}
#Override
public void actionPerformed(ActionEvent e) {
timer.stop();
this.setBackground(Color.RED);
timer.start();
}
}
I'm trying to make a barrel inside my game float downwards towards the sceen by itself, I've tried a few things and looked up some tutorials, but I can't seem to make it work. Maybe I am approaching this in the wrong way by trying to do this inside a paintcomponent()? Inside my JPanel I also have a car object that is an extension of a JPanel controlled by KeyListeners.
// this is inside a JPanel class that I made that's painting out the game
OilBarrel barrel = new OilBarrel();
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
road.paintComponent(g);
this.add(car);
this.add(barrel);
barrel.setBounds(barrelX, barrel.getBarrelY(), 150, 180);
int carX = car.getCarX();
car.setBounds(carX, carY, 800, 400);
barrel.setBounds(550, barrel.getBarrelY(), 800, 400);
while (true) {
barrel.move();
repaint();
try {
Thread.sleep(1);
} catch (Exception e) {
}
}
}
// this is the oilbarrel class
import java.awt.Dimension;
import java.awt.Image;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
public class OilBarrel extends JLabel{
int barrelX;
int barrelY = 0;
public OilBarrel() {
setVisible(true);
this.setFocusable(true);
Image img = new ImageIcon(this.getClass().getResource("/oil.png")).getImage();
this.setIcon(new ImageIcon(img));
}
public void move(){
if(barrelY<1000)
barrelY +=1;
}
public int getBarrelY() {
return barrelY;
}
}
Swing is single threaded, this means that you for-loop in your paintComponent method is blocking the Event Dispatching Thread, preventing it from updating the UI.
See Concurrency in Swing for more details
The simplest solution to solving the problem would be to use a Swing Timer, as it allows for a small delay to be scheduled off the EDT, but which triggers it's updates on the EDT, making it safe to update the UI from within.
Component animation isn't hard, but it does require a different work flow, for example:
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private JLabel label;
private int xDelta = 1;
public TestPane() {
setLayout(null);
label = new JLabel("*");
label.setSize(label.getPreferredSize());
label.setLocation(0, (200 - label.getHeight()) / 2);
add(label);
Timer timer = new Timer(10, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
int x = label.getX();
x += xDelta;
if (x + label.getWidth() > getWidth()) {
x = getWidth() - label.getWidth();
xDelta *= -1;
} else if (x < 0) {
x = 0;
xDelta *= -1;
}
label.setLocation(x, label.getY());
}
});
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
}
As a personal preference, I would avoid using components for this job and lean towards a complete custom painting route.
There are lots of reasons for this, components are complex objects which require a lot of attention to detail. It's also difficult to apply additional effects or transformations to them
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private Rectangle box;
private int xDelta = 1;
public TestPane() {
setLayout(null);
box = new Rectangle(0, 75, 50, 50);
Timer timer = new Timer(10, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
int x = box.x;
x += xDelta;
if (x + box.width > getWidth()) {
x = getWidth() - box.width;
xDelta *= -1;
} else if (x < 0) {
x = 0;
xDelta *= -1;
}
box.setLocation(x, box.y);
repaint();
}
});
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.draw(box);
g2d.dispose();
}
}
}
Use SwingUtilities.invokeLater when a thread needs to update the GUI.
https://docs.oracle.com/javase/7/docs/api/javax/swing/SwingUtilities.html#invokeLater(java.lang.Runnable)
Thread t = new Thread(){
public void run(){
while( true ){
// queue on Event Dispatch Thread
SwingUtilities.invokeLater( new Runnable(){
public void run(){
barrel.move();
repaint();
}
});
try{
Thread.sleep( 100 );
}catch( InterruptedException ie ){}
}
}
};
t.start();
Also, lookup Swing Timer. I think that may be better.
So I am trying to make my own version of the Pong game. My problems with this program is that my player doesn't move. I think I made a mistake but because I am really new to java I don't fully understand game mechanics in code. Could one of you please review my code carefully and tell me whats wrong and how to correct it. Also, would one of you tell me where did you learn or where can I learn game development with Java. Your answers will be really appreciated.
Window Class
import java.awt.Color;
import java.awt.Dimension;
import javax.swing.JFrame;
public class Window{
public Window(){
JFrame window = new JFrame();
GamePanel gamePanel = new GamePanel();
window.setSize(720, 480);
window.setResizable(true);
window.setTitle("2DGame");
window.add(gamePanel);
window.setUndecorated(false);
window.setLocationRelativeTo(null);
window.getContentPane().setBackground(Color.BLACK);
window.setVisible(true);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setMinimumSize(new Dimension(720, 480));
}
}
GamePanel Class
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
public class GamePanel extends JPanel{
Wall wall = new Wall();
Player player = new Player();
public GamePanel(){
setBackground(new Color(16, 16, 16));
}
public void paintComponent(Graphics g){
super.paintComponent(g);
wall.paintComponent(g);
player.paintComponent(g);
}
}
Player Class
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Player extends JPanel implements ActionListener, KeyListener{
Timer t = new Timer(5, this);
private int x = 28;
private int y = 190;
private int ydirection;
private int speed = 1;
public Player(){
t.start();
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
}
public void paintComponent(Graphics g){
g.setColor(Color.WHITE);
g.fillRect(x, y, 20, 100);
}
public void actionPerformed(ActionEvent e){
y += ydirection;
repaint();
}
public void keyPressed(KeyEvent e){
int KeyCode = e.getKeyCode();
if(KeyCode == KeyEvent.VK_W){
ydirection -= speed;
}
if(KeyCode == KeyEvent.VK_S){
ydirection += speed;
}
}
public void keyReleased(KeyEvent e){
int KeyCode = e.getKeyCode();
if(KeyCode == KeyEvent.VK_W){
ydirection = 0;;
}
if(KeyCode == KeyEvent.VK_S){
ydirection = 0;
}
}
public void keyTyped(KeyEvent e){}
}
Your logic is not entirely good, but you can easily fix it. Please study the OOP (principle).
For example:
The player is not JPanel.
The ActionListener and KeyListener interface management is not the Player class job, please create a separate class for her.
Please study the access modifiers.
Pay more attention to the transparency of your code.
For example:
Use the ovverride annotation.
Use the formatter(Ctrl + Shift + F in eclipse)
The problem was that you wrote Keylistener on another Jpanel. What I think you inadvertently put on the player class.
I quickly reworked the code a bit.
Window class:
import java.awt.Color;
import java.awt.Dimension;
import javax.swing.JFrame;
import java.awt.Color;
import java.awt.Dimension;
import javax.swing.JFrame;
public class Window {
public Window() {
JFrame window = new JFrame();
GamePanel gamePanel = new GamePanel();
window.setSize(720, 480);
window.setResizable(true);
window.setTitle("2DGame");
window.add(gamePanel);
window.setUndecorated(false);
window.setLocationRelativeTo(null);
window.getContentPane().setBackground(Color.BLACK);
window.setVisible(true);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setMinimumSize(new Dimension(720, 480));
}
public static void main(String args[]) {
Window window = new Window();
}
}
PlayerDirections enum:
public enum PlayerDirections {
UP, DOWN
}
Player class:
import java.awt.Color;
import java.awt.Graphics;
public class Player {
private int x = 28;
private int y = 190;
private int speed = 1;
public Player() {
}
public void draw(Graphics g) {
g.setColor(Color.WHITE);
g.fillRect(x, y, 20, 100);
}
public void Move(PlayerDirections direction) {
switch (direction) {
case UP:
y -= speed;
break;
case DOWN:
y += speed;
break;
}
}
}
GamePanel class:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.JPanel;
import javax.swing.Timer;
public class GamePanel extends JPanel implements ActionListener {
Player player = new Player();
public GamePanel() {
addKeyListener(new KeyAdapter() {
#Override
public void keyPressed(KeyEvent e) {
int KeyCode = e.getKeyCode();
if (KeyCode == KeyEvent.VK_W) {
player.Move(PlayerDirections.UP);
}
if (KeyCode == KeyEvent.VK_S) {
player.Move(PlayerDirections.DOWN);
}
}
});
setFocusable(true);
setFocusTraversalKeysEnabled(false);
setBackground(new Color(16, 16, 16));
Timer t = new Timer(5, this);
t.start();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
player.draw(g);
}
#Override
public void actionPerformed(ActionEvent e) {
repaint();
}
}
I am trying to display a timer count, but it is not being displayed, but everything else works fine. Thank you for helping btw.
import javax.swing.*;
import java.util.*;
import javax.swing.Timer;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Tester {
static Timer timer;
static JFrame frame;
static JPanel panel;
public static void init(){
frame = new JFrame();
panel = new JPanel();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.setSize(500, 500);
frame.add(panel);
}
The method above is just to make code cleaner.
public static void main(String[] args) {
init();
class Clicker extends JPanel{
int timesClicked;
public Clicker(){
timesClicked = 0;
}
void updateClicks(){
timesClicked++;
repaint();
}
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
System.out.println("Called!!!");
g2.drawString("Half Seconds: "+timesClicked, 100, 100);
}
} //end of Clicker
drawString method not working is above.
final Clicker c = new Clicker();
panel.add(c);
class TimeChecker implements ActionListener{
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("Clicked!");
c.updateClicks();
}
}// end of TimeChecker
ActionListener listener = new TimeChecker();
timer = new Timer(500,listener);
timer.start();
}
}
You have a combination of issues
Clicker was never actually added to anything
panel uses a FlowLayout by default, but Clicker provides no sizing hints, so it's sized to 0x0
You code generally is setup a little weird. I would learn to do without static very, very quickly.
Quick and fast solution...
Change the layout manager for panel to BorderLayout...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Test {
static Timer timer;
static JFrame frame;
static JPanel panel;
public static void init() {
frame = new JFrame();
panel = new JPanel(new BorderLayout());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.setSize(500, 500);
frame.add(panel);
}
public static void main(String[] args) {
init();
class Clicker extends JPanel {
int timesClicked;
public Clicker() {
timesClicked = 0;
}
void updateClicks() {
timesClicked++;
repaint();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
System.out.println("Called!!!");
g2.setColor(Color.BLACK);
g2.drawString("Half Seconds: " + timesClicked, 100, 100);
}
} //end of Clicker
final Clicker c = new Clicker();
panel.add(c);
panel.revalidate();
panel.repaint();
class TimeChecker implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("Clicked!");
c.updateClicks();
}
}// end of TimeChecker
ActionListener listener = new TimeChecker();
timer = new Timer(500, listener);
timer.start();
}
}
A slightly different approach (with out static)
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
Clicker clicker = new Clicker();
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(clicker);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
class TimeChecker implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("Clicked!");
clicker.updateClicks();
}
}// end of TimeChecker
ActionListener listener = new TimeChecker();
Timer timer = new Timer(500, listener);
timer.start();
}
});
}
public class Clicker extends JPanel {
private int timesClicked;
public Clicker() {
timesClicked = 0;
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 200);
}
void updateClicks() {
timesClicked++;
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
System.out.println("Called!!!");
g2.setColor(Color.BLACK);
g2.drawString("Half Seconds: " + timesClicked, 100, 100);
}
}
}
I am making a game. There are 3 different files in the project, there is a file called Dude, Frame and Board. So can anyone help me? The code:
The code for Board:
package Ourgame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Board extends JPanel implements ActionListener{
Dude p;
Image img;
Timer time;
public Board() {
p = new Dude();
addKeyListener(new AL());
setFocusable(true);
ImageIcon i = new ImageIcon("/Users/appleuser/Desktop");
img = i.getImage();
time = new Timer(5, this);
time.start();
}
public void actionPerformed(ActionEvent e) {
p.move();
repaint();
}
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
g2d.drawImage(img, 0, 0, null);
g2d.drawImage(p.getImage(), p.getX(), p.getY(), null);
}
private class AL extends KeyAdapter {
public void keyReleased(KeyEvent e) {
p.keyReleased(e);
}
public void keyPressed(KeyEvent e) {
p.keyPressed(e);
}
}
}
The code for Dude:
package Ourgame;
import java.awt.Image;
import java.awt.event.KeyEvent;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
public class Dude {
int x, dx, y;
Image still;
public Dude() {
ImageIcon i = new ImageIcon("/Users/appleuser/Desktop/the man.bmp");
still = i.getImage();
x = 10;
y = 172;
}
public void move() {
x = x + dx;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public Image getImage() {
return still;
}
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if(key == KeyEvent.VK_LEFT);
dx = -1;
if(key == KeyEvent.VK_RIGHT)
dx = 1;
}
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
if(key == KeyEvent.VK_LEFT);
dx = 0;
if(key == KeyEvent.VK_RIGHT)
dx = 0;
}
}
The code for Frame:
package Ourgame;
import javax.swing.JFrame;
public class Frame {
public static void main(String[] args){
JFrame frame = new JFrame("2D game");
frame.add(new Board());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(1200, 365);
frame.setVisible(true);
}
}
You might just need to call JFrame.pack(). It's possible the layout manager hasn't set the bounds of your Board. Try:
frame.getContentPane().add(new Board());
frame.pack();
frame.setVisible(true);
If this doesn't work then I suggest you follow the other advice on here: use a Debugger and/or check your image paths. "/Users/appleuser/Desktop" is definitely not an image.
Try invoking your Swing code on the EDT:
package Ourgame;
import javax.swing.JFrame;
public class Frame
{
public static void main(String[] args)
{
SwingUtilities.invokeLater( new Runnable()
{
#Override
public void run()
{
JFrame frame = new JFrame("2D game");
frame.add(new Board());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(1200, 365);
frame.setVisible(true);
}
});
}
}