Please note that I am quite new to all this programming. Right now i have a frame which adds a panel to it. I have use the paintcomponent method on the panel I believe, but now when i am trying to use keylisteners i need to move the image that i have drawn on the panel. I currently do not know how to repaint it.
import java.awt.*;
import java.io.*;
import java.awt.event.*;
import javax.swing.*;
#SuppressWarnings
("serial")
public class Game extends JPanel implements KeyListener
{
Car fo = new Car();
draw a=new draw();
public Game()
{
JFrame frame2=new JFrame("JASA1 Racing");
frame2.add(new draw());
frame2.setSize(500,600);//set frame size
frame2.setVisible(true);//made frame visible
frame2.setResizable(false);
frame2.addKeyListener(this);
frame2.setFocusable(true);
}
public class draw extends JPanel
{
private static final long serialVersionUID = 1L;
public void redraw()
{
repaint();
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
ImageIcon ic2=new ImageIcon("C:\\Users\\Shawn\\track.jpg");
Image img=ic2.getImage();
g.drawImage(img, 0, 0,null);
g.drawImage(fo.getcar(),fo.getX(),fo.getY(),null);
System.out.println(fo.getX() + " " + fo.getY());
}
}
public void keyPressed(KeyEvent e)
{
int key = e.getKeyCode();
if(key == KeyEvent.VK_LEFT)
{
fo.move(-50, 0);
System.out.print(fo.getX());
a.repaint();
}
else if(key == KeyEvent.VK_RIGHT)
{
fo.move(50, 0);
System.out.print(fo.getX());
a.redraw();
}
}
public void keyReleased(KeyEvent e)
{
}
public void keyTyped(KeyEvent e)
{
}
}
draw a=new draw(); isn't what you've added to the frame, you've used frame2.add(new draw()); instead.
Try using frame2.add(a);
I'd also consider using Key Bindings as it will allow you to overcome the focus issues related to KeyListener
Related
So I am new to event handlers, and I wanted to create a program where I made a Purple panel inside a frame and if the user clicks the mouse button in the area of the panel and then types % with their keyboard, I want the panel to draw a line segment in the area of the panel. This is just testing the event handlers. Right now, I am trying it but it does not work. All help will be appreciated. After I get the hand of this, I want to try out the repaint() method, where if someone does the same actions as before, I wanted to check the background of the Panel. If you can help me with both, that'd be awesome but it is not a priority. Thank you.
import java.awt.Graphics; // for classes Graphics, Color, Font, Image
import java.awt.Color;
import java.awt.Font;
import java.awt.event.KeyEvent; // for classes KeyListener, MouseListener
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JFrame; // for classes JFrame, JPanel, JLabel
import javax.swing.JPanel;
public class GardenGrows
{
public GardenGrows()
{
}
public static void main(String[] args)
{
GardenGrows gg = new GardenGrows();
gg.runIt();
}
// makes the frame and handles all properties of the frame
// also instantiates the Garden.java object
public void runIt()
{
JFrame frame = new JFrame ("Garden");
frame.setDefaultCloseOperation( frame.EXIT_ON_CLOSE );
frame.setLayout(null);
frame.setBackground(Color.GRAY);
frame.setSize( 1200,700);
frame.setLocation( 50, 10);
frame.setResizable(true);
frame.setVisible(true);
Garden gar = new Garden();
frame.getContentPane().add(gar);
}
}
class Garden extends JPanel implements KeyListener, MouseListener
{
private boolean mouseClicked;
private boolean keyClicked;
private int xpos;
private int ypos;
public Garden()
{
mouseClicked = false;
keyClicked = false;
addKeyListener(this);
addMouseListener(this);
setBackground(Color.PINK);
setLocation(50,50);
setSize(1000,500);
}
public void mousePressed(MouseEvent evt)
{
int x = evt.getX();
int y = evt.getY();
if(x>=50 || x<=1050 && y<=50 || y>=550)
{
mouseClicked = true;
}
}
public void mouseClicked(MouseEvent evt){}
public void mouseReleased(MouseEvent evt){}
public void mouseEntered(MouseEvent evt){}
public void mouseExited(MouseEvent evt){}
public void keyReleased(KeyEvent evt){}
public void keyPressed(KeyEvent evt){}
public void keyTyped(KeyEvent evt)
{
int letter = evt.getKeyCode();
if (letter == 13)
{
keyClicked =true;
}
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
if(keyClicked && mouseClicked)
g.drawLine(50,0,110,120);
}
}
Making a key listener work in a JPanel, will not be so simple, because it is not focusable. (Think about a JTextField, when you write text on it, it is focused). So, in order to make this work you will have to use KeyBindings. In practice, remove the KeyListener implementation from your JPanel, and use KeyBindings.
public class GardenGrows {
public GardenGrows() {
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
// All swing applications must run on EDT Thread
GardenGrows gg = new GardenGrows();
gg.runIt();
});
}
// makes the frame and handles all properties of the frame
// also instantiates the Garden.java object
public void runIt() {
JFrame frame = new JFrame("Garden");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(null);
frame.setBackground(Color.GRAY);
frame.setSize(1200, 700);
frame.setLocation(50, 10);
frame.setResizable(true);
frame.setVisible(true);
Garden gar = new Garden();
frame.getContentPane().add(gar);
}
}
class Garden extends JPanel implements MouseListener {
private boolean mouseClicked;
private boolean keyClicked;
private int xpos;
private int ypos;
public Garden() {
mouseClicked = false;
keyClicked = false;
addMouseListener(this);
setBackground(Color.PINK);
setLocation(50, 50);
setSize(1000, 500);
getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_5, KeyEvent.SHIFT_MASK),
"percentageClicked");
getActionMap().put("percentageClicked", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
keyClicked = true;
repaint(); // Try to draw the line
}
});
}
public void mousePressed(MouseEvent evt) {
int x = evt.getX();
int y = evt.getY();
if (x >= 50 || x <= 1050 && y <= 50 || y >= 550) {
mouseClicked = true;
repaint(); // Try to draw the line
}
}
public void mouseClicked(MouseEvent evt) {
}
public void mouseReleased(MouseEvent evt) {
}
public void mouseEntered(MouseEvent evt) {
}
public void mouseExited(MouseEvent evt) {
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (keyClicked && mouseClicked)
g.drawLine(50, 0, 110, 120);
}
}
I'm trying to move a dot by pressing the right-left keys.
Here is my main:
import javax.swing.JFrame;
public class Main {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(null);
frame.setSize(500,500);
Graphic graphic=new Graphic();
frame.add(graphic);
}}
This is the graphic class where i created the dot and I implemented KeyListener and ActionListener:
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 Graphic extends JPanel implements ActionListener, KeyListener {
private int posX = 220;
private int posY = 300;
private Timer timer;
private int delay = 8;
private int width = 500;
private int height = 500;
public Graphic() {
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
timer = new Timer(delay, this);
timer.start();
this.setSize(width, height);
}
public void paint(Graphics g) {
g.setColor(Color.black);
g.fillRect(0, 0, width, height);
g.setColor(Color.GREEN);
g.fillOval(posX, posY, 20, 20);
}
#Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_LEFT) {
if (posX <= 20) {
posX = 20;
} else {
moveLeft();
}
}
if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
if (posX >= 460) {
posX = 460;
} else {
moveRight();
}
}
repaint();
}
private void moveRight() {
posX += 20;
}
private void moveLeft() {
posX -= 20;
}
#Override
public void actionPerformed(ActionEvent e) {
timer.start();
repaint();
}
#Override
public void keyReleased(KeyEvent e) {
}
#Override
public void keyTyped(KeyEvent e) {
}
}
In my opinion, this should work...but it doesn't. When I press the left-right keys nothing happens and it looks like it's not "listening" my commands. So, what is wrong with my code?
KeyListener works if the component which has the listener has the focus. JFrame has by default the focus when you display it but not a JPanel.
In the Graphic constructor add simply grabFocus() :
public Graphic() {
addKeyListener(this);
setFocusTraversalKeysEnabled(true);
setFocusable(true);
grabFocus();
timer = new Timer(delay, this);
timer.start();
this.setSize(width, height);
}
EDIT
I have tested on my machine. The problem is that it works randomly as the JFrame needs to be visible if we want that the JPanel grab the focus. Sometimes it is, other times it is not.
SwingUtilities.invokeLater() may solve the problem.
After adding the panel to the JFrame, invoke the code which grabs the focus in a invokeLater() method.
frame.add(graphic);
...
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
graphic.grabFocus();
}
});
You call repaint method of Component class instead of your paint method.
I'm making a game in Java where a ball moves forward constantly with no user control, but the user can control the vertical movement of the ball, using the up and down arrow keys, however I'm stuck on adding the keylistener class/whatever it is to my JFrame, through my main method. Basically, I do add(keylistener_class/method), and Java (quite rightly), complains that my class or method is not a component. My question, then, is how AM I supposed to add the keylistener into my Jframe?
Cheers,
Matt
Code:
package org.ultraluminous.vertiball;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Game extends JPanel{
static int x = 0;
static int y = 0;
static int ys = 0;
private static void shift(){
x+=1;
y+=ys;
}
public static void event(KeyEvent e){
if(e.getKeyCode() == KeyEvent.VK_UP){
ys = 1;
}
if (e.getKeyCode() == KeyEvent.VK_DOWN){
ys = -1;
}
}
public class key{
public void Listen() {
KeyListener listener = new KeyListener() {
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
}
};
addKeyListener(listener);
setFocusable(true);
}
}
#Override
public void paint(Graphics g){
super.paint(g);
Graphics2D Graph = (Graphics2D) g;
Graph.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
Graph.setColor(Color.BLUE);
Graph.drawOval(x, y, 50, 50);
Graph.fillOval(x, y, 50, 50);
}
public static void main (String[] args){
JFrame Win = new JFrame("Pong");
Game game = new Game();
Win.add(new Game());
//Win.add... add what? I need to add the key listener here
//but seem to be unable to.
Win.setResizable(false);
Win.setSize(900, 600);
Win.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Win.setVisible(true);
while (true) {
shift();
Win.repaint();
try {
Thread.sleep(10);
} catch (InterruptedException e){
e.printStackTrace();
}
}
}
I got it to work by adding the KeyListener to your JFrame. Alternatively you could create a separate class for the KeyListener and add it that way (instead of using an anonymous inner class). Here is what I added:
public static void main (String[] args){
JFrame Win = new JFrame("Pong");
Game game = new Game();
Win.add(new Game());
Win.addKeyListener(new KeyListener() {
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_UP){
ys = -1;
}
if (e.getKeyCode() == KeyEvent.VK_DOWN){
ys = 1;
}
}
#Override
public void keyReleased(KeyEvent e) {
}
});
Win.setResizable(false);
Win.setSize(900, 600);
Win.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Win.setVisible(true);
while (true) {
shift();
Win.repaint();
try {
Thread.sleep(10);
} catch (InterruptedException e){
e.printStackTrace();
}
}
}
}
You can add KeyListener to your JPanel by this way:
addKeyListener(new KeyListener(){
...//all the methods.
});
Alternatively, you can use KeyAdpater, if do not use all the methods.
addKeyListener(new KeyAdapter(){
...//Only the methods you want.
});
I am a bit new to threading, so bear with me. All relevant classes will be below the text in one place for easier reference.
Backstory:
I created a simple pong-like game following this tutorial: http://www.edu4java.com/en/game/game1.html
Everything worked perfectly, then I made modifications to better understand how it all works. In the tutorial, there is a main method from which the animations are played continuously. According to the tutorial author, Thread.sleep(10) "...tells the processor that the thread which is being run must sleep for 10 ms, which allows the processor to execute other threads and in particular the AWT-EventQueue thread which calls the paint method."
Now, my question is this:
(Just for fun and to practice Java,) I have created a "launcher" for all the various small programs and games I make. I have yet to get the pong game to work inside the launcher. Without a main method inside the pong frame, the animation never runs. I left the main method in in the code below, so that it works. How would I go about launching the animation from somewhere other than main?
Here's the code:
The Frame and main method:
package pongGame;
import javax.swing.*;
public class PongMainGUI extends JFrame
{
private static final int WINDOW_WIDTH = 500;
private static final int WINDOW_HEIGHT = 800;
private static AnimationPanel panel;
public PongMainGUI()
{
//This line sets the title, and, since it calls the super constructor, it calls setTitle().
super("Pong!");
panel = new AnimationPanel(this);
//This method simply makes the screen appear in the center of whatever size screen you are using.
setLocationRelativeTo(null);
setSize(WINDOW_WIDTH,WINDOW_HEIGHT);
add(panel);
setVisible(true);
}
public static void main(String args[]) throws InterruptedException
{
new PongMainGUI();
while(true)
{
System.out.println("PongMainGUI");
panel.repaint();
panel.move();
Thread.sleep(10);
}
}
}
The Animation Panel:
package pongGame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.event.MouseInputListener;
#SuppressWarnings("serial")
public class AnimationPanel extends JPanel
{
PongMainGUI frame;
Ball ballClass;
Racquet racquetClass;
boolean bool = false;
public AnimationPanel(PongMainGUI frame)
{
this.frame = frame;
addMouseListener(new MouseListener()
{
#Override
public void mouseClicked(MouseEvent arg0)
{
}
#Override
public void mouseEntered(MouseEvent arg0)
{
}
#Override
public void mouseExited(MouseEvent arg0)
{
}
#Override
public void mousePressed(MouseEvent arg0)
{
}
#Override
public void mouseReleased(MouseEvent arg0)
{
}
});
addMouseMotionListener(new MouseMotionListener()
{
#Override
public void mouseDragged(MouseEvent e)
{
}
#Override
public void mouseMoved(MouseEvent e)
{
}
});
addKeyListener(new KeyListener()
{
#Override
public void keyPressed(KeyEvent e)
{
racquetClass.keyPressed(e);
}
#Override
public void keyReleased(KeyEvent e)
{
racquetClass.keyReleased(e);
}
#Override
public void keyTyped(KeyEvent e)
{
}
});
//This is needed to ensure that the keyboard will register properly and receive focus.
setFocusable(true);
ballClass = new Ball(this);
racquetClass = new Racquet(this);
}
public void move()
{
//ballClass.moveBall();
racquetClass.moveRacquet();
}
#Override
public void paint(Graphics g)
{
System.out.println("AnimationPanel paint method");
//This method clears the panel so it appears as if the circle is moving.
super.paint(g);
//Better version of Graphics.
Graphics2D g2d = (Graphics2D) g;
//This method turns antialiasing on, which cleans up the corners.
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
ballClass.paint(g2d);
racquetClass.paint(g2d);
}
public void gameOver()
{
System.out.println("Game over method");
JOptionPane.showMessageDialog(null, "Game Over", "Game Over", JOptionPane.YES_NO_OPTION);
System.exit(ABORT);
}
}
The Ball "sprite":
package pongGame;
import java.awt.Graphics2D;
import java.awt.Rectangle;
public class Ball
{
int xCoordinate = 0;
int yCoordinate = 0;
//1 = right movement, -1 = left
int xDirection = 1;
int yDirection = 1;
private final static byte ballWidth = 30;
private final static byte ballHeight = 30;
private AnimationPanel panel;
public Ball(AnimationPanel panel)
{
this.panel = panel;
}
public void paint(Graphics2D g2d)
{
//This creates the actual circle with a specified width and height.
//Because super.paint(g) is called at the start, a new circle is created each time.
g2d.fillOval(xCoordinate, yCoordinate, ballWidth, ballHeight);
System.out.println("Ball paint method");
moveBall();
}
//What this method does is add 1 to the x and y coordinates each time it's called. However, getWidth() and getHeight() are used to determine the current panel size, not the frame size.
//Then, whatever the width and/or height is is subtracted so the circle does not completely disappear from view.
public void moveBall()
{
if (xCoordinate + xDirection < 0)
{
xDirection = 1;
}
else if (xCoordinate + xDirection > panel.getWidth() - ballWidth)
{
xDirection = -1;
}
if (yCoordinate + yDirection < 0)
{
yDirection = 1;
}
else if (yCoordinate + yDirection > panel.getHeight() - ballHeight)
{
System.out.println("Ball moveBall method");
panel.gameOver();
}
if (collision() == true)
{
yDirection = -1;
yCoordinate = panel.racquetClass.getPaddleHeight() - ballHeight;
}
xCoordinate = xCoordinate + xDirection;
yCoordinate = yCoordinate + yDirection;
}
public Rectangle getBounds()
{
return new Rectangle(xCoordinate, yCoordinate, ballWidth, ballHeight);
}
private boolean collision()
{
return panel.racquetClass.getBounds().intersects(getBounds());
}
}
And finally, the Racquet "sprite":
package pongGame;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
public class Racquet
{
private AnimationPanel panel;
private int xCoordinate = 0;
//0 = no movement, 1 is right, -1 is left.
private byte direction = 0;
//All of the following values are in pixels.
private final static byte PADDLE_OFFSET = 100;
private final static byte PADDLE_WIDTH = 120;
private final static byte PADDLE_HEIGHT = 10;
public Racquet(AnimationPanel panel)
{
this.panel = panel;
}
public void moveRacquet()
{
if (xCoordinate + direction > 0 && xCoordinate + direction < panel.getWidth()-60)
xCoordinate = xCoordinate + direction;
}
public void paint(Graphics2D g)
{
g.fillRect(xCoordinate, getPaddleHeight(), PADDLE_WIDTH, PADDLE_HEIGHT);
//move();
}
public void keyReleased(KeyEvent e)
{
direction = 0;
}
public void keyPressed(KeyEvent e)
{
if (e.getKeyCode() == KeyEvent.VK_LEFT)
direction = -1;
if (e.getKeyCode() == KeyEvent.VK_RIGHT)
direction = 1;
}
public Rectangle getBounds()
{
return new Rectangle(xCoordinate, getPaddleHeight(), PADDLE_WIDTH, PADDLE_HEIGHT);
}
public int getPaddleHeight()
{
return panel.getHeight() - PADDLE_OFFSET;
}
}
This may or may not help, but this is the code for the launcher I wanted to use to open the game:
This is the "main menu":
package GUI;
import javax.swing.*;
import painter.MainPainterGUI;
import java.awt.*;
import java.awt.event.*;
/**
* This class serves to create the launcher gui for the program.
* It extends JFrame.
* #author Jackson Murrell
*/
#SuppressWarnings("serial")
public class LauncherGUI extends JFrame implements ActionListener
{
//A couple constants that are used for sizing things.
private final short WINDOW_HEIGHT = 225;
private final short WINDOW_WIDTH = 550;
private final byte BLANK_SPACE = 25;
//Panels to use for adding in components.
JPanel textPanel, buttonPanel, mainPanel;
//Buttons for user input and selection.
JButton calculator, colorChooser, timer, exit, primeNumberTester, game, painter;
//A text label that will be used for giving the user
//instructions on the program.
JLabel textLabel;
//A constructor to create the GUI components when an object of this class is created.
public LauncherGUI()
{
//This call's the parent method's (JFrame) setTitle method.
super("Omni-program");
//These methods set various options for the JFrame.
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
setSize(WINDOW_WIDTH, WINDOW_HEIGHT);
setLocationRelativeTo(null);
textPanel = new JPanel();
buttonPanel = new JPanel();
mainPanel = new JPanel();
calculator = new JButton("Calculator");
colorChooser = new JButton("Color Chooser");
timer = new JButton("Timer");
primeNumberTester = new JButton("Prime Number Tester");
game = new JButton("Games");
exit = new JButton("Exit Launcher and Programs");
painter = new JButton("Painter");
calculator.addActionListener(this);
colorChooser.addActionListener(this);
timer.addActionListener(this);
exit.addActionListener(this);
primeNumberTester.addActionListener(this);
game.addActionListener(this);
painter.addActionListener(this);
textLabel = new JLabel("Welcome to the launcher! Click the button for the mini-program you would like to run.", 0);
textPanel.add(Box.createVerticalStrut(BLANK_SPACE));
textPanel.add(textLabel);
buttonPanel.add(calculator);
buttonPanel.add(colorChooser);
buttonPanel.add(timer);
buttonPanel.add(primeNumberTester);
buttonPanel.add(game);
buttonPanel.add(painter);
buttonPanel.add(exit);
mainPanel.setLayout(new GridLayout(2,1));
mainPanel.add(textPanel);
mainPanel.add(buttonPanel);
//mainPanel.add(Box.createVerticalStrut(BLANK_SPACE));
add(mainPanel);
//pack();
//Having this line at the end instead of the top ensures that once everything is added it is all set to be visible.
setVisible(true);
}
//This method is required since ActionListener is implemented.
//It will be used to process user input.
#Override
public void actionPerformed(ActionEvent e)
{
if (e.getSource() == calculator)
{
new CalculatorGUI();
dispose();
}
else if (e.getSource() == colorChooser)
{
new ColorChooserGUI();
dispose();
}
else if(e.getSource() == timer)
{
new TimerGUI();
dispose();
}
else if (e.getSource() == primeNumberTester)
{
new PrimeNumberTesterGUI();
dispose();
}
else if(e.getSource() == exit)
{
System.exit(0);
}
else if(e.getSource() == painter)
{
new MainPainterGUI();
dispose();
}
else if(e.getSource() == game)
{
new GameLauncherGUI();
dispose();
}
}
}
Here's the actual game launcher:
package GUI;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import pongGame.PongMainGUI;
public class GameLauncherGUI extends JFrame implements ActionListener
{
//A couple constants that are used for sizing things.
private final short WINDOW_HEIGHT = 225;
private final short WINDOW_WIDTH = 550;
private JButton adventureGame, pong, back;
private JLabel label;
private JPanel mainPanel, buttonPanel, textPanel;
public GameLauncherGUI()
{
//This call's the parent method's (JFrame) setTitle method.
super("Omni-program");
//These methods set various options for the JFrame.
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
setSize(WINDOW_WIDTH, WINDOW_HEIGHT);
setLocationRelativeTo(null);
adventureGame = new JButton("Adventure Game (Broken)");
adventureGame.addActionListener(this);
pong = new JButton("Pong");
pong.addActionListener(this);
back = new JButton("Back");
back.addActionListener(this);
label = new JLabel("Click the button below for the game you wish to play,\nor click back to go to the previous screen.");
mainPanel = new JPanel();
buttonPanel = new JPanel();
textPanel = new JPanel();
textPanel.add(label);
buttonPanel.add(adventureGame);
buttonPanel.add(pong);
buttonPanel.add(back);
mainPanel.add(textPanel);
mainPanel.add(buttonPanel);
add(mainPanel);
//Having this line at the end instead of the top ensures that once everything is added it is all set to be visible.
setVisible(true);
}
#Override
public void actionPerformed(ActionEvent e)
{
if(e.getSource() == back)
{
new LauncherGUI();
dispose();
}
else if(e.getSource() == pong)
{
new PongMainGUI();
dispose();
}
}
}
mainis a static method like others, so you can call it from your launcher:
PongMainGUI.main(null); // launch the pong game
However, note that, in order to avoid lots of trouble, Swing components must be created from the Event Dispatch Thread, as shown in this example. So you should wrap the content of your main method inside a Runnable and launch it with SwingUtilities.invokeLater().
However (again), by doing so, your Thread.sleep(10) will run on the EDT, blocking the GUI responsiveness again. Fortunately, Swing thought of that problem and created a utility called javax.swing.Timer that runs tasks periodically on the EDT (without blocking it):
public static void main(String args[])
{
SwingUtilities.invokeLater(new Runnable(){
public void run(){
new PongMainGUI();
Timer timer = new Timer(10, new ActionListener(){
public void actionPerformed(ActionEvent e){
System.out.println("PongMainGUI");
panel.repaint();
panel.move();
}
});
timer.start();
}
});
}
This main() method will run safely in standalone, or from your launcher.
I'm trying to make an applet which I can simply drag an image. And I want image object to listen events. So here is the applet code which simple run in a thread:
import java.awt.*;
import java.net.URL;
import javax.swing.JApplet;
public class Client extends JApplet implements Runnable {
private static final long serialVersionUID = 1L;
MediaTracker mediaTracker;
Image [] imgArray;
Tas t1;
public void init()
{
mediaTracker = new MediaTracker(this);
imgArray = new Image[1];
URL base = getCodeBase();
imgArray[0] = getImage(base,"okey.png");
mediaTracker.addImage(imgArray[0],1);
try {
mediaTracker.waitForAll();
} catch (InterruptedException e) {
e.printStackTrace();
}
t1 = new Tas(this, new Rectangle(0, 0, imgArray[0].getWidth(this), imgArray[0].getHeight(this)), imgArray[0]);
Thread t = new Thread(this);
t.start();
}
public void paint(Graphics g)
{
t1.paint(g);
}
#Override
public void run() {
while(true){
//System.out.println("run");
repaint();
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
And the class of object which holds image is:
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JPanel;
#SuppressWarnings("serial")
public class Movable extends JPanel implements MouseListener {
public Client mainObj;
public Rectangle rect;
public Image image;
public Movable(Client mainObj, Rectangle rect, Image image) {
this.mainObj = mainObj;
this.rect = rect;
this.image = image;
addMouseListener(this);
}
public void paint(Graphics g) {
g.drawImage(image, rect.x, rect.y, rect.width, rect.height, this);
}
#Override
public void mouseClicked(MouseEvent arg0) {
System.out.println("clicked");
}
#Override
public void mouseEntered(MouseEvent arg0) {
}
#Override
public void mouseExited(MouseEvent arg0) {
}
#Override
public void mousePressed(MouseEvent arg0) {
System.out.println("pressed");
}
#Override
public void mouseReleased(MouseEvent arg0) {
}
}
#SuppressWarnings("serial")
class Tas extends Movable{
public String name = "";
public Tas(Client mainObj, Rectangle rect, Image image) {
super(mainObj, rect, image);
}
}
I can see the image in my applet but nothing happens when I click in or out of the image. So what's wrong with this code.
Assuming that Tas in code #1 is Moveable in code #2...
You don't actually use the Moveable as a Component, but instead ask it to paint itself onto the Applet's graphics context, here:
public void paint(Graphics g)
{
t1.paint(g);
}
Instead you should add an instance of Moveable onto the Applet's container, wherein painting will become automatic, and it will start to receive mouse events. You can also remove that paint() method then too.
First of all you should never override the paint method of a top level container (JApplet, JFrame, JDialog).
Then to do custom painting on other Swing components you override the paintComponent() method of the component, NOT the paint() method. Read the Swing tutorial on Custom Painting. So first fix those problems.
I'm not sure what the point of the Thread is but remove it from your code until you solve your other problems. If you are trying to do animation, then you should be using a Swing Timer, not a Thread.
If you want to see some code for dragging components you can take a look at Moving Windows for some generic code.
This is a working solution. It is not an applet but you can easily convert that. Hope it helps :
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.geom.Point2D;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
#SuppressWarnings("serial")
public class ImagePanel extends JPanel {
Image image;
Point2D axis = new Point2D.Double();
boolean drag = false;
Point2D dragPoint = new Point2D.Double();
public ImagePanel(Image image) {
this.image = image;
setPreferredSize(new Dimension(300,300));
addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
drag = true;
dragPoint = e.getPoint();
}
#Override
public void mouseReleased(MouseEvent e) {
drag = false;
}
});
addMouseMotionListener(new MouseMotionAdapter() {
#Override
public void mouseDragged(MouseEvent e) {
if (drag) {
axis.setLocation(axis.getX()
+ (e.getPoint().x - dragPoint.getX()), axis.getY()
+ (e.getPoint().y - dragPoint.getY()));
dragPoint = e.getPoint();
repaint();
}
}
});
}
#Override
public void paintComponent(Graphics g) {
g.setColor(Color.white);
g.fillRect(0, 0, getWidth(), getHeight());
g.drawImage(image, (int) axis.getX(), (int) axis.getY(), null);
}
public static void main(String[] args) {
try {
JFrame f = new JFrame();
f.getContentPane().add(
new ImagePanel(ImageIO.read(new File("image.jpg"))));
f.pack();
f.setVisible(true);
} catch (IOException e) {
e.printStackTrace();
}
}
}
The simple answer is - you don't have code to do anything in mousePressed() or mouseReleased().
There are lots of other problems in the code though...
Simplest solution I could come up with -
public class Client extends JApplet {
private MouseInputAdapter myMouseListener = new MyMouseListener();
public void init() {
// usually a very bad idea, but needed here
// since you want to move things around manually
setLayout(null);
// assuming this will get used often, so making it a method.
addLabelForImage(getImage(getCodeBase(), "okay.png"));
}
private void addLabelForImage(Image image) {
ImageIcon icon = new ImageIcon(image);
JLabel l = new JLabel(icon);
add(l);
l.setSize(l.getPreferredSize());
// you'll probably want some way to calculate initial position
// of each label based on number of images, size of images,
// size of applet, etc. - just defaulting to 100,100 now.
l.setLocation(100, 100);
l.addMouseListener(myMouseListener);
l.addMouseMotionListener(myMouseListener);
}
// Made this a MouseInputAdapter because I assume you may want to handle
// other types of mouse events later...
private static class MyMouseListener extends MouseInputAdapter {
#Override
public void mouseDragged(MouseEvent e) {
// when the mouse is dragged over a the component this listener is
// attached to (ie - one of the labels) convert the point of the mouse
// event from the internal component coordinates (0,0 is upper right
// corner of each label), to it's parent's coordinates (0,0 is upper
// right corner of the applet), and set the components location to
// that point.
Component theLabel = e.getComponent();
Container theApplet = theLabel.getParent();
Point labelPoint = e.getPoint();
Point appletPoint = SwingUtilities.convertPoint(
theLabel, labelPoint, theApplet );
theLabel.setLocation(appletPoint);
}
}
}