import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JPanel;
public class Panel extends JPanel {
/**
*
*/
private static final long serialVersionUID = 1L;
final static int WIDTH = 800;
final static int HEIGHT = 600;
private int x = 40, y = 49, r = 20;
Dimension SIZE = new Dimension(WIDTH, HEIGHT);
public Panel() {
setLayout(new BorderLayout());
setPreferredSize(SIZE);
setMaximumSize(SIZE);
setMinimumSize(SIZE);
setBackground(Color.cyan);
setFocusable(true);
requestFocus();
new input(this);
}
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2 = (Graphics2D) g;
g2.fillOval(x, y, r, r);
repaint();
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
}
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
public class input extends KeyAdapter {
private Panel panel;
public input(Panel panel) {
panel = new Panel();
panel.addKeyListener(this);
}
#Override
public void keyPressed(KeyEvent e) {
int keycode = e.getKeyCode();
int x = panel.getX();
int y = panel.getY();
if (keycode == KeyEvent.VK_LEFT) {
panel.setX(x - 1);
}
if (keycode == KeyEvent.VK_RIGHT) {
panel.setX(x + 1);
}
}
}
I'm a Java newbie. I was trying to make a class specially for KeyListener
but it just doesn't work. I can't figure out what I did wrong.
It might be meaningless to make a inputhandler class, and it controls only the only one class (jpanel), but i used to put all of my code in one single class.. it looks so bad. i'm learning to make them into more separate classes or make them more object-oriented~
I just confuse when to make a new class, and when not.
please help me, could you tell me what i did wrong with my code above. Was my thought wrong or just the code?
This looks like the first reason your KeyListener doesn't work:
public input(Panel panel) {
panel = new Panel();
panel.addKeyListener(this);
}
When you do this:
new input(this);
Because you are also doing this:
panel = new Panel();
You are adding the KeyListener to new Panel(), not the panel you are passing in to the constructor with this.
Personally I don't see a problem with creating a listener object just to listen, although I do not think that is necessary here.
Although presumably this will not have an effect on your listener, one other problem I see is that you are overriding paint which you should not be doing in Swing. You should be overriding paintComponent. See Painting in AWT and Swing: http://www.oracle.com/technetwork/java/painting-140037.html#callbacks
Also as far as style goes, class names start with a capital letter in Java. Your input class should be named Input.
Related
I can draw static things to the screen, but I want to make them move with user key input. I don't know what to do, I've been searching and searching and haven't come up with an answer yet. Please help!
package com.Game.game;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Game extends JFrame
{
final static int width = 500;
final static int height = 500;
public int x = 250;
public int y = 250;
public int changeX = 10;
public int changeY = 10;
public static void main(String[] args)
{
new Game();
}
public Game()
{
KeyListener listener = new KeyListening();
addKeyListener(listener);
setFocusable(true);
DrawingStuff drawingstuff = new DrawingStuff();
add(drawingstuff);
setSize(width, height);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
public class DrawingStuff extends JPanel
{
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.drawString("Hey there!", 300, 300);
g.setColor(Color.RED);
g.fillRect(x, y, 50, 50);
}
}
public class KeyListening implements KeyListener
{
DrawingStuff drawingstuff = new DrawingStuff();
#Override
public void keyPressed(KeyEvent e)
{
if(e.getKeyCode() == KeyEvent.VK_UP)
{
y = y + changeY;
System.out.println("Hey");
drawingstuff.repaint();
}
}
#Override
public void keyReleased(KeyEvent e)
{
}
#Override
public void keyTyped(KeyEvent e)
{
}
}
public void update()
{
}
}
EDIT: Fixed it. I took away the key listener stuff in the constructor method, added a command to focus on "drawingstuff" in the constructor method, and, most importantly, added this bit of code to the end of the constructor method:
while(true)
{
drawingstuff.repaint();
}
The problem is that your KeyListening object has a reference to a different DrawingStuff object than the one you added to your UI inside the Game constructor.
public class KeyListening implements KeyListener
{
DrawingStuff drawingstuff = new DrawingStuff();
...
You should pass a DrawingStuff reference to the KeyListening instance so that it can tell the right object to repaint itself.
I am trying to draw circle objects with each click and then store every circle object into an Arraylist, I don't know why my program is not working! If I removed the arraylist and the line that create a new circle object, the program will work. How would I make my program store all circuit objects into an Arraylist ?
import javax.swing.JPanel;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Random;
public class CircleObj extends JPanel {
private int rColor;
private int gColor;
private int bColor;
private int radius;
private Random rand = new Random();
private int xStart;
private int yStart;
ArrayList <Circle> xxx ;
public CircleObj () {
xxx = new ArrayList<Circle>();
addMouseListener(new MouseAdapter() {
public void mouseClicked (MouseEvent e) {
xStart = e.getX();
yStart = e.getY();
rColor = rand.nextInt(256);
gColor = rand.nextInt(256);
bColor = rand.nextInt(256);
radius = rand.nextInt(20);
repaint();
}
}); // end addMouseListener
}
public void paintComponent (Graphics g) {
super.paintComponent(g);
g.setColor(new Color(rColor, gColor, bColor));
g.fillOval(xStart, yStart, radius, radius);
xxx.add(new Circle());
}
private class Circle {
private int x;
private int y;
private int r;
private int rcol;
private int gcol;
private int bcol;
public Circle()
{
x=xStart;
y=yStart;
r=radius;
rcol= rColor;
gcol= gColor;
bcol= bColor;
}
}
}
======
import javax.swing.JFrame;
import java.awt.BorderLayout;
public class HW3 {
public static void main (String[] arg) {
JFrame frame = new JFrame("Circles");
CircleObj canvas = new CircleObj();
frame.add(canvas, BorderLayout.CENTER);
frame.setBounds(250, 98, 600, 480);
//frame.setLayout(new BorderLayout());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
} // end main
} //end HW3
Don't add the new shape inside the paintComponent method, paintComponent can be called for any number of reasons, many of which you don't control, instead, create it when the mouseClicked event is triggered...
public void mouseClicked (MouseEvent e) {
xStart = e.getX();
yStart = e.getY();
rColor = rand.nextInt(256);
gColor = rand.nextInt(256);
bColor = rand.nextInt(256);
radius = rand.nextInt(20);
xxx.add(new Circle(xStart, yStart, new Color(rColor, gColor, bColor), radius));
repaint();
}
And then in your paintComponent, loop through the ArrayList and paint the circles...
public void paintComponent (Graphics g) {
super.paintComponent(g);
for (Circle c : xxx) {
g.setColor(c.getColor());
g.fillOval(c.getX(), c.getY(), c.getRadius(), c.getRadius());
}
}
Now, you're going to have to modify you Circle class to provide getters which the CircleObj can use in order to actually paint the circles...
Alternatively, you could make use of the Shapes API provided within Java...Have a look at Working with Geometry for more details...
I want my button to change color on the mod == 0 of i % 3. The paintComponent(...) is called when the form is re-sized and index is passed in so I would think that this should change the color of my button ever time I start moving the form around the screen.
I have two components on the screen but both will not show up this might be a factor.
Code:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class testform {
public static void main (String[] p) {
testBall3 j1 = new testBall3();
myButton b1 = new myButton("test");
JPanel testPane = new JPanel();
testPane.setBackground(Color.green);
testPane.setLayout(new BorderLayout());
j1.setPreferredSize(new Dimension(10,10));
//testPane.add(b1);
testPane.add(j1);
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(testPane);
frame.pack();
frame.setSize(300, 200);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
//j1.setColorBall(Color.BLACK);
//j1.repaint();
}
}
class myButton extends JButton {
private static final long serialVersionUID = 1L;
public myButton(String s) {
super(s);
}
public void setPrefferedSize(Dimension d) {
//this.setBounds(x, y, width, height)
setPreferredSize(d);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
index += i;
System.out.println(i);
if (index % 3 == 0) {
setBackground(Color.RED);
}
else {
setBackground(Color.BLACK);
}
}
}
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JComponent;
class testBall3 extends JComponent
{
private static final long serialVersionUID = 1L;
private Color colorBall = Color.red;
private int x1, y1;
int index = 0;
public void setColorBall(Color c)
{
this.colorBall = c;
}
public testBall3()
{
super();
System.out.println("MyBall (0)");
}
public testBall3(int x, int y, int diameter)
{
super();
this.setLocation(x, y);
this.setSize(diameter, diameter);
System.out.println("MyBall (1)");
x1 = x;
y1 = y;
}
public void paintBorder(Graphics g)
{
super.paintBorder(g);
g.setColor(Color.YELLOW);
g.fillOval(100, 100, 50, 50);
System.out.println("PaintBorder");
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setColor(colorBall);
g.fillOval(x1, y1, 10, 10);
System.out.println("paintComponent");
}
public void paint(Graphics g)
{
super.paint(g);
paintComponent(g);
paintBorder(g);
paintChildren(g);
System.out.println("Paint");
}
}
But paintComponent doesn't take a second parameter, how are you passing it? I would think that instead of trying to pass i, you would want make i an attribute of class myButton instead and initialize it to 0 upon instantiation. That is, if you want each button to have its own counter. That sounds like the better plan.
You've got a lot of strange stuff going on...
You've got a component where you override all four major painting methods for no good reason.
In this component, your paint method override calls the super method, and calls the other 3 methods, which in essence will make those 3 methods be called twice.
You've got program logic (advancement of i) inside of your myButton's paintComponent method -- something that should never be done. You do not have full control over when or even if this method is called.
You are calling setBackground(...) from within paintComponent, something which shouldn't be done.
Your class names do not begin with an upper case letter, going against coding conventions, and potentially confusing anyone who tries to read your code.
If you want to change the state of a component on resize, use a ComponentListener.
e.g.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import javax.swing.*;
#SuppressWarnings("serial")
public class Foo2 extends JPanel {
protected static final Color MAGIC_BACKGROUND = Color.red;
protected static final int MAGIC_NUMBER = 3;
private static final int TIMER_DELAY = 20;
private int index = 0;
private JButton myButton = new JButton("My Button");
protected int DELTA_SIZE = 2;
public Foo2() {
add(myButton);
addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent e) {
index++;
if (index % MAGIC_NUMBER == 0) {
myButton.setBackground(MAGIC_BACKGROUND);
} else {
myButton.setBackground(null);
}
}
});
new Timer(TIMER_DELAY, new ActionListener() {
private Toolkit toolkit = Toolkit.getDefaultToolkit();
private int screenWidth = toolkit.getScreenSize().width;
private int screenHeight = toolkit.getScreenSize().height;
#Override
public void actionPerformed(ActionEvent e) {
if (getWidth() >= screenWidth || getHeight() >= screenHeight) {
((Timer)e.getSource()).stop();
} else {
int width = getWidth() + DELTA_SIZE;
int height = getHeight() + DELTA_SIZE;
setPreferredSize(new Dimension(width, height));
Window win = SwingUtilities.getWindowAncestor(Foo2.this);
win.pack();
win.setLocationRelativeTo(null);
}
}
}).start();
}
private static void createAndShowGui() {
JFrame frame = new JFrame("Foo2");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new Foo2());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
I have an assignment that I am doing where I am supposed to implement and design an application that plays a game called catch the creature. Have the creature appear at a random location then disappear and reappear somewhere else. The goal is to "catch" the creature by clicking the creature with a mouse button. Record the number of times the creature is caught.
I need help just displaying the creature which is an JPEG of a pikachu, I have tried a few things but none of them work. Any help is appreciated thank you!
Main Code:
import javax.swing.*;
public class Catch_The_Creature
{
public static void main(String[] args)
{
JFrame frame = new JFrame("Catch the Creature");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Creature panel = new Creature();
JOptionPane.showMessageDialog(frame, "Catch Pikachu!");
frame.getContentPane().add(panel);
frame.pack();
frame.setVisible(true);
}
}
Creature Code:
import java.awt.*;
import java.util.Random;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
public class Creature extends JPanel
{
private final int WIDTH = 400, HEIGHT = 300;
private final int DELAY=20, IMAGE_SIZE = 60;
private ImageIcon image;
private int pikachuX, pikachuY;
private int x, y;
private int catchCount=0;
private static Random generator = new Random();
private Timer time;
private ActionListener updater;
private JLabel countLabel;
public Creature()
{
image = new ImageIcon("image/pikachu.jpg");
time = new Timer(DELAY, updater);
addMouseListener ((MouseListener) new MouseClickedListener());
setBackground (Color.green);
setPreferredSize(new Dimension(1900,1000));
time.start();
}
public boolean point(int x, int y)
{
if (x == pikachuX && y == pikachuY)
{
catchCount++;
return true;
}
return false;
}
public int getCatchCount()
{
return catchCount;
}
private class MouseClickedListener extends MouseAdapter
{
public void mouseClicked(MouseEvent event)
{
point(event.getX(), event.getY());
}
}
public void paintComponent(Graphics page)
{
super.paintComponent(page);
page.drawImage(image.getImage(),WIDTH, HEIGHT, null);
page.drawString("Pikachus Captured: " + catchCount, 10, 35);
setFont(new Font("Arial", Font.BOLD,35));
}
public void actionPerformed(ActionEvent event)
{
time.setDelay(1000);
x += pikachuX;
y += pikachuY;
if (x <= 0 || x >= WIDTH-IMAGE_SIZE)
pikachuX = pikachuX * -1;
if (y <= 0 || y >= HEIGHT-IMAGE_SIZE)
pikachuY = pikachuY * -1;
repaint();
}
public void mouseEntered(MouseEvent arg0) {}
public void mouseExited(MouseEvent arg0) {}
public void mousePressed(MouseEvent arg0) {}
public void mouseReleased(MouseEvent arg0){}
}
It doesn't look like you ever add the ImageIcon to the panel or tell it to paint in the paintComponent() method.
First solution [Preferred]: Add ImageIcon to the panel. In the constructor
super.add(image);
Make sure you use the correct layout (probably a null or absolute layout) and that you update the coordinates of the ImageIcon itself, not just some member variables.
Second solution: Paint the ImageIcon in the paintComponent() method. This is probably discouraged because it goes against the general Swing principles.
Make sure your Image file is in the right directory. If you're running from netbeans or eclipse your file structure should look like this
ProjectRoot
src
bin
image
pikachu.jpeg
Since you are using "image/pikachu.png", you image filder should be a child of the project root folder as that's where the IDE will first search fore your file path
Edit: To draw image. Instead of using ImageIcon, use BufferedImage
try {
BufferedImage image = ImageIO.read("image/pikachu.jpeg");
} catch (Exception ex){
ex.printStackTrace();
}
public void paintComponent(Graphics page)
{
super.paintComponent(page);
page.drawImage(image, x, y, heightYouWant, widthYouWant, this);
page.drawString("Pikachus Captured: " + catchCount, 10, 35);
setFont(new Font("Arial", Font.BOLD,35));
}
All i needed to do was put values on where I wanted the picture to start at in the constructor.
public Creature()
{
image = new ImageIcon ("pikachu.png");
time = new Timer(DELAY, updater);
x = 0;
y = 50;
addMouseListener ((MouseListener) new MouseClickedListener());
setBackground (Color.green);
setPreferredSize(new Dimension(1900,1000));
time.start();
}
While still using an Image Icon and still paint the image in the paint component.
public void paintComponent(Graphics page)
{
super.paintComponent(page);
image.paintIcon (this, page, x, y);
page.drawString("Pikachus Captured: " + catchCount, 10, 35);
setFont(new Font("Arial", Font.BOLD,35));
}
Hello people,
I am trying to write an animated character for a multitouch screen. I want my object to have 5 eyes and each of whose pupil to be dragged and dropped differently, within the eye of course.
I have tried to do it all in a single class and the problem seems to be assigning mouse handlers to each of the five pupils! In other words, if I move one pupil, all the pupils are moving.
Then, I resorted to using a bespoke class just to the pupil. When I use it by itself, the pupil is draggable. However, when I use it as an object in the eyes class, the pupil is static! No clicks registered, no mouse activity tracked.
I have looked at tutorials, other related issues with mouse handlers and could not make any progress. I changed the code a dozen times from various tutorials and suggestions before finally posting here. Any ideas where I am missing the cue? Any pointers would be greatly appreciated.
Thanks in advance.
PS: I know I am yet to put the constraints on the pupil movement within the eye.
Code for main eyes class:
package rollEyes;
import java.awt.*;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class FiveEyes extends JPanel
{
private static final long serialVersionUID = 1L;
private static final int SIZE = 512;
private int a = SIZE / 2;
private int b = a;
private int r = 4 * SIZE / 5;
private int n;
int circleSize=30;
Pupil dc = new Pupil(1);
public FiveEyes(int n)
{
super(true);
this.setPreferredSize(new Dimension(SIZE, SIZE));
this.n = n;
}
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(Color.black);
a = getWidth() / 2;
b = getHeight() / 2;
int m = Math.min(a, b);
r = 4 * m / 5;
int r2 = Math.abs(m - r) / 2;
int numOfEyes = 5;
for (int i = 0; i < numOfEyes ; i++)
{
Graphics2D g2d2 = (Graphics2D) g;
double t = 2 * Math.PI * i / n;
int x = (int) Math.round(a + r * Math.cos(t));
int y = (int) Math.round(b + r * Math.sin(t));
drawEyeSockets(g2d2, x,y, 2*r2,2*r2);
}
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
#Override
public void run()
{
create();
}
});
}
public void drawEyeSockets(final Graphics2D g2, int x, int y, int w, int h)
{
g2.drawOval(x,y,w,h);
dc.drawCircle(g2, x+12, y+12);
}
private static void create()
{
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
FiveEyes fivey = new FiveEyes(5);
f.add(fivey);
f.pack();
f.setVisible(true);
}
}
Code for the Pupil class:
package rollEyes;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Pupil extends JPanel
{
private static final long serialVersionUID = 1L;
int radius=50;
int x_after = 50;
int y_after = 50;
MouseHandler mh ;
private static int n =1;
public Pupil(int n)
{
super(true);
}
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
drawCircle(g2d,x_after,y_after);
}
public void drawCircle(final Graphics2D g2d, int x, int y)
{
g2d.setColor(Color.BLUE);
g2d.fillOval(x, y, radius/2, radius/2);
mh = new MouseHandler();
this.addMouseListener(mh);
this.addMouseMotionListener(mh);
}
private static void create()
{
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Pupil dc = new Pupil(n);
f.add(dc);
f.pack();
f.setVisible(true);
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
#Override
public void run()
{
create();
}
});
}
private class MouseHandler extends MouseAdapter
{
boolean circleClicked=false;
public void mouseReleased(MouseEvent e)
{
circleClicked = false;
}
public void mousePressed(MouseEvent me)
{
circleClicked = true;
}
public void mouseDragged(MouseEvent me)
{
if (circleClicked)
{
x_after = me.getX();
y_after = me.getY();
repaint();
}
}
}
}
You have Pupil extend JPanel, but really shouldn't be doing that. Instead, use the concepts that you've learned in your current Pupil class -- how to draw a movable circle, and extend it in the larger FiveEyes class, only this time create a List<Pupil> and draw them. My suggestions:
Make Pupil not extend JPanel. Instead give it the machinery to draw circles in certain locations and to have that location changed.
Also you will need to give it a way to recognize if its circle has been clicked by giving it a contains(Point p) method. One way to do this is to use a Shape object, or you can roll your own method.
Give FiveEyes a List<Pupil> that in reality is an ArrayList<Pupil> and fill it with Pupil objects.
In FiveEyes paintComponent(...) method, iterate through this List telling each Pupil to draw itself.
In your FiveEyes MouseAdapter's mousePressed(...) method, iterate through your Pupil List to see if a Pupil has been clicked on. If so, move it.
Alternatively, you could create a Pupil BufferedImage, put it into an ImageIcon, and put that into a JLabel, and then allow your FiveEyes class's MouseAdapter to drag the labels around.
First of all, this code
mh = new MouseHandler();
this.addMouseListener(mh);
this.addMouseMotionListener(mh);
must only be called once. You're adding millions of mouse handlers to the component!
And you need five instances of Pupil, one for each eye. Right now, you have only one, so of course the rendering will only yield one result.
Lastly, you must make sure that only one eye is "active" at a time (i.e. not all of them should receive mouse events or not all of them should process them).