KeyLisenter, repaint(), methods - java

Ok, I have been workinng of mending this for the past hour or more. I wanted to seperate the player class and the applet being drawn for convience when I add more to the player class it will be more organized. But, since I did this I have had error after error and I have another file similiar to this one where it draws the applet in the same file with no errors and runs. I have looked at it step by step and still can not find it. So I was hoping somebody could explain why I am getting these three errors.
player.java
package com.powder.game;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class player implements KeyListener{
private Rectangle rect;
public void init(){
rect = new Rectangle(10, 10, 50, 50); // make the rectangle
this.addKeyListener(this); // Listens to see if Rectangle is pressed
}
public void paint(Graphics e){
super.paint(e);
Graphics2D g2 = (Graphics2D) e;
g2.setColor(Color.RED); // Sets a color for the rectangle
g2.fill(rect);
}
public void keyTyped(KeyEvent e){
}
#Override
public void keyPressed(KeyEvent e){
if(e.getKeyCode() == KeyEvent.VK_E){
rect.setLocation(rect.x, rect.y-10);
}
if(e.getKeyCode() == KeyEvent.VK_S){
rect.setLocation(rect.x-10, rect.y);
}
if(e.getKeyCode() == KeyEvent.VK_D){
rect.setLocation(rect.x, rect.y+10);
}
if(e.getKeyCode() == KeyEvent.VK_F){
rect.setLocation(rect.x+10, rect.y);
}
repaint();
}
public void KeyReleased(KeyEvent e){
}
}
MyFrameInit.java
package com.powder.game;
import javax.swing.*;
import java.applet.*;
import java.awt.*;
import java.util.*;
import java.io.IOException;
import java.lang.Math;
import javax.swing.ImageIcon;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import com.powder.game.player;
public class MyFrameInit extends Applet {
player p = new player();
public void paint(Graphics g){
super.paint(g); // Super calls the parent
g.setColor(Color.BLUE); // Setting color for g (background)
g.fillRect(0, 0, 600, 400); // fill the background blue at x,y,width,height
this.setSize(600, 400); // Set the size of the applet
p.init();
}
}
Sorry if the formatting for the page isn't right. Still trying to understand this. I'm so used to tags lol.
EDIT: So, I extended Applet to player and it fixed almost everything I just added
public void keyReleased(KeyEvent arg0) {
// TODO Auto-generated method stub
}
that to the end and it started to work. Now my only problem is it's not keeping MyFrameInit.java when after I go to init() in player.java how could I fix this?

Problems
Player does not have methods...
addKeyListener
repaint
It does not inherit from anything, therefore it can't call...
super.paint, as it's parent classes do not have this method...
You can't call what you don't have...
Player does not meet to contractual requirements of the KeyListener interface, it does not implement
public void keyReleased(KeyEvent e)
Painting is for painting the current state of the component, you should never modify the state of the component or any child components from within any paint method, as this can produce an infinite loop of repaints
Don't do:
this.setSize(600, 400); // Set the size of the applet - You should never try and set the size of an applet, the size is determined by the HTML tag
p.init();. Your paint method will be called a lot of times over the life cycle of your program, it's pointless to initialise objects within that require there state to be maintained between calls
Recommendations
Start by using a JApplet instead of an Applet
Extending your Player from a JPanel; override it's paintComponent method instead of it's paint method (calling super.paintComponent instead); override it's getPreferredSize method and return a reasonable default size for the component
add Player to the JApplet...
Use the key bindings API instead of KeyListener, see How to Use Key Bindings. This will save you a few more days of head scratching and frustration.

Related

Drawing Graphics with other classes

I have two classes below: And I'm trying to make it so that calling FilledFrame would make certain shapes. I've tested it with a Line below, but it doesn't show up on the GUI. Is there something I'm doing wrong here? I also need to make a Card class that is able to modify some rectangle's positions, so would I need to make a graphics object in the main and enter it into FilledFrame and my Card class?
import java.awt.Canvas;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Line2D;
import javax.swing.*;
public class FilledFrame extends JFrame implements ActionListener {
static int FRAME_WIDTH = 500;
static int FRAME_HEIGHT = 100;
Graphics g = getGraphics();
public FilledFrame () {
g.drawLine(1, 1, 100, 100);
setSize(FRAME_WIDTH, FRAME_HEIGHT);
setVisible(true);
}
private void createComponents() {
...
}
private void createCards() {
...
}
#Override
public void actionPerformed(ActionEvent e) {
}
public static void draw (Graphics g) {
g.fillRect(0, 50, 100, 150);
}
}
Main class:
import java.awt.Graphics;
import java.awt.Shape;
import java.awt.geom.Line2D;
import java.awt.geom.Line2D.Float;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;
import java.awt.Canvas;
import javax.swing.JComponent;
import javax.swing.JPanel;
public class Main {
public static void main (String args[]) {
FilledFrame frame = new FilledFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.show();
}
}
Is there something I'm doing wrong here?
Sorry to say, but you're guessing at how to do Swing drawing, and while this might work with simple Java concepts, it won't for something as complex as Swing graphics.
Problems include:
Trying to draw directly within the JFrame -- never do this, but instead draw in a JPanel.
Calling getGraphics() on a component to get a Graphics resource. This will lead to your getting an unstable and short-lived Graphics object that can lead to either failed painting or NullPointerExceptions
Not drawing in an appropriate painting method.
You're using int literals in your drawing method parameters rather than int variables, making any drawing that you do do, fixed -- you can never move or change it.
Instead I suggest that you:
Create a class that extends JPanel and paint in that class.
Draw within this class's protected void paintComponent(Graphics g) method.
Don't forget to call the super's paintComponent method within your override so that your GUI cleans up any dirty pixels.
Then place that JPanel into the JFrame that needs to display it.
Use int fields (variables) not int literals (so-called "magic" numbers) for most of your drawing method parameters so that your drawings can change if you so desire while the program runs.
And most important, read and study the standard Swing graphics tutorials.
Resources:
The Really Big Index: the main tutorial where you should start.
Using Swing Components: how to create Swing GUI's
Lesson: Performing Custom Painting: introductory tutorial to Swing graphics
Painting in AWT and Swing: advanced tutorial on Swing graphics

JApplet Animation Not Running

So I am trying to get into simple animations and virtual physics and whatnot. I am trying to animate a ball so that it slowly grows as time passes by. The code I have here is pretty much exactly as it is in a Java For Dummies book I have with the exception of a few things such as: getting rid of constants for the size of the applet (this.setSize(500, 500) vs this.setSize(WIDTH, HEIGHT) and declaring WIDTH and HEIGHT earlier). The changes were simple and would not effect the program. (I would know as I've taken a Java course in school). Anyway, I'm starting here with Applets and I can't get the program to run past two iterations. Down in the paint function I have a System.out.println(d) to check how many times the diameter of the ellipse grows. However the only output I see is "21" then "22". The applet continues to run via the applet viewer however nothing else is printed even though it should continue to grow. Anyone know what's wrong?
As a side note I should mention I am using NetBeans 7.2 and selecting "Run File" to run it.
package GraphicsTesting;
import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;
import java.awt.event.*;
import java.applet.*;
import java.util.concurrent.*;
public class Main extends JApplet
{
private PaintSurface canvas;
#Override
public void init()
{
this.setSize(500,500);
canvas = new PaintSurface();
this.add(canvas, BorderLayout.CENTER);
ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(3);
executor.scheduleAtFixedRate(new AnimationThread(this), 0L, 20L, TimeUnit.MILLISECONDS);
}
}
class AnimationThread implements Runnable
{
JApplet c;
public AnimationThread(JApplet C)
{
this.c = c;
}
public void run()
{
c.repaint();
}
}
class PaintSurface extends JComponent
{
int d = 20;
#Override
public void paint(Graphics g)
{
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint
(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
d+=1;
System.out.println(d);//This is to test
Shape ball = new Ellipse2D.Float(200, 200, d, d);
g2.setColor(Color.RED);
g2.fill(ball);
}
}
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package javaapplication3;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import javax.swing.Timer;
import javax.swing.JApplet;
import javax.swing.JComponent;
public class Main extends JApplet {
private PaintSurface canvas;
private Timer timer;
#Override
public void init() {
this.setSize(500, 500);
canvas = new PaintSurface();
this.add(canvas, BorderLayout.CENTER);
// ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(3);
// executor.scheduleAtFixedRate(new AnimationThread(this), 0L, 20L, TimeUnit.MILLISECONDS);
timer = new Timer(20, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
canvas.repaint();
}
});
timer.start();
}
}
class PaintSurface extends JComponent {
int d = 20;
#Override
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
d += 1;
System.out.println(d);//This is to test
Shape ball = new Ellipse2D.Float(0, 0, d, d);
g2.setColor(Color.RED);
g2.fill(ball);
}
}
You are calling repaint() on a thread that is not the Event Dispatch Thread
so the UI is not updated. There are other ways to do this, but internally javax.swing.Timer calls the actionPerformed method inside the Event Dispatch Thread so the UI is updated.
UPDATE: You could see the applet in action using java webstart: https://tetris-battle-bot.googlecode.com/files/launch.jnlp
The above answer does work. However, looking at your original code there is one little itty bitty misconception that, it appears, neither of you caught. In the constructor of the animation thread you have JApplet C as a parameter rather than JApplet c. To clarify, you accidently capitalized the c. The capitlization of the C caused you to set this.c = c which basically assigned it to itself. It wasn't needed to rewrite the entire code at all.

JApplet not showing paint or draw methods

I have a animation class which simply draws two circles and a line (no main method), in another class i have a main method which is passed the animation class as a object and should show the two circles that I have drawn but it doesn't show, it only shows the window none of the circles or the line that I have done, if i was to put the main method in my animation class it will work perfectly, this is a user error somehow but I'm not sure what or why.
The animation method in separate class.
import javax.swing.*;
import java.awt.geom.*;
import java.awt.*;
import java.awt.Graphics.*;
import javax.swing.JApplet;
public class Animation extends JApplet{
public void init(){
}
public static void createAndShowGUI(JApplet j)
{
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
frame.setSize(500,500);
frame.getContentPane().add("Center", j);
}
public void paint(Graphics g){
Graphics2D g2 = (Graphics2D) g;
int x=50;
int y=10;
g2.setPaint(Color.black);
g2.draw(new Line2D.Double(x,y,50,400));
drawT(g2);
drawH(g2);
//create a method that translates
}
public void drawH(Graphics2D g2)
{
int y=25;
g2.setColor(Color.blue);
drawCircle(y,g2);
}
public void drawT(Graphics2D g2){
int y=100;
g2.setColor(Color.green);
drawCircle(y,g2);
}/*
public void raceLoop(){
long startingTime = System.currentTimeMillis();
long cumTime=startingTime;
while(mve.hposition<70){
long timePassed = System.currentTimeMillis()-cumTime;
cumTime += timePassed;
//mve.update(timePassed);
}
}*/
public void drawCircle(int y, Graphics2D g2)
{
g2.fillOval(50,y,50,50);
}
}
The Main Method
import javax.swing.*;
import java.awt.geom.*;
import java.awt.*;
import java.awt.Graphics.*;
import javax.swing.JApplet;
public class Race {
public static void main(String[] args) {
JApplet applet = new JApplet();
Animation animie = new Animation();
animie.createAndShowGUI(applet);
}
}
You don't need to (or want) extend from JApplet if all you're going to is use a JFrame. You're better of (in any case), extending from JPanel (as this can then be added to a JApplet or JFrame)
You've not added anything to the JFrame, so, in fact, you program is doing exactly what you told it to.
You should very rarely need to override the paint method of a top level container (like JApplet or JFrame), instead, use JPanel and override it's paintComponent method.
You should always call super.paintXxx, the paint methods chain together to paint the various aspects of the application and it will end in tears if you break this chain.
You might like to have a read through
Creating a GUI With JFC/Swing
Performing Custom Painting
Painting in AWT and Swing
For some more background
Looks like you're passing the wrong reference to the createAndShowGui(..) method.
Try this on your Race class:
import javax.swing.*;
import java.awt.geom.*;
import java.awt.*;
import java.awt.Graphics.*;
import javax.swing.JApplet;
public class Race {
public static void main(String[] args) {
Animation animie = new Animation();
animie.createAndShowGUI(animie);
}
}

Java screenshot (using Robot and BufferedImage.getRGB)

I discovered the Robot class yesterday, and thought it was pretty cool. Today I wanted to experiment with it and see what was possible; so I decided I wanted to make a program that took a screenshot of the entire screen, and rendered out an image pixel by pixel on a JPanel. I have the program finished (two classes), but it isn't working and I can't find out why (I HAVE looked over the code a few times). Here's the code:
(FIRST CLASS)
import java.awt.AWTException;
import java.awt.FlowLayout;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
public class One {
public static void main(String[] args) {
BufferedImage screenCap = null;
Rectangle screenRect = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
try {
screenCap = new Robot().createScreenCapture(screenRect);
Two imageRenderer = new Two(screenCap, screenRect);
imageRenderer.doRender();
JFrame frame = new JFrame();
frame.setVisible(true);
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new FlowLayout());
frame.add(imageRenderer);
frame.pack();
} catch (AWTException e) {
e.printStackTrace();
}
}
}
(SECOND CLASS)
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import javax.swing.JPanel;
public class Two extends JPanel {
private BufferedImage screenCap;
private Rectangle screenRect;
private Color pixelRGB;
//c1 and c2 are the x and y co-ordinates of the selected pixel.
private int c1, c2;
public Two(BufferedImage sC, Rectangle rect) {
screenCap = sC;
screenRect = rect;
setPreferredSize(new Dimension(rect.width, rect.height));
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
setBackground(Color.WHITE);
g.setColor(pixelRGB);
g.drawRect(c1, c2, 1, 1);
}
public void doRender() {
for(int i=0; i<screenRect.width; i++) {
for(int j=0; j<screenRect.height; j++) {
pixelRGB = new Color(screenCap.getRGB(i, j));
c1 = i;
c2 = j;
repaint();
}
}
}
}
I have googled around this problem to no avail.
Can anyone tell me what I'm doing wrong?
In order to make it work, just replace your paintComponent() method in your class Two with the following:
public void paintComponent(Graphics g) {
super.paintComponent(g);
setBackground(Color.WHITE);
g.drawImage(screenCap, 0, 0, getWidth(), getHeight(), null);
}
You can also get rid of the doRender() method.
Two should probably be an instance of a JLabel that is displaying screenCap. E.G.
import java.awt.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
public class Screenshot {
public static void main(String[] args) throws Exception {
Rectangle screenRect = new Rectangle(
Toolkit.getDefaultToolkit().getScreenSize());
final BufferedImage screenCap =
new Robot().createScreenCapture(screenRect);
Runnable r = new Runnable() {
#Override
public void run() {
JOptionPane.showMessageDialog(null, new ImageIcon(screenCap));
}
};
SwingUtilities.invokeLater(r);
}
}
Drop it in a scroll pane if you wish to be really neat about it. Batteries not included.
In case it is not obvious: A JOptionPane uses a JLabel to render an ImageIcon.
Each time you repaint, you paint white over the whole panel, then do only a single pixel. So after each one, you'll only get one pixel. It also shouldn't be necessary to call repaint many times. In fact, when you call repaint, it does not immediately actually call paintComponent. It simply submits a request to repaint, which swing will eventually do. And it might not be one-to-one. E.g., many calls to repaint might result in only one call to paintComponent. You should try to write code so that a single call to paintComponent will completely display the component.
To do this, you can use g.drawImage to display a BufferedImage. See this post for more information on displaying an image in a JPanel.

Help with creating a complex Swing GUI with animation

This is my first non-school related program. I have a few questions that you guys can hopefully answer with ease. I have 3 questions. How can I add my button to my JFrame even though it's in a different class than the button?
Also, how would I go about making my shape and ten others like it about a quarter second after each other so I had a line of them.
Then, how would I force them to follow a predetermined path that scales to somebody dragging the box around?
Thanks a lot for reading and helping me out guys. Here are my three classes:
gameRunner.java
import javax.swing.JFrame;
public class gameRunner {
public static void main(String args []){
Enemy e = new Enemy();
Buttons b = new Buttons();
JFrame f = new JFrame();
f.add(b);
f.add(e);
f.setVisible(true);
f.setSize(1300, 700);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setTitle("Tower Defense");
}
}
Enemy.java
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Rectangle2D;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Enemy extends JPanel implements ActionListener {
Timer t = new Timer(5, this);
double x = 0;
double y = 0;
double velX = 3;
double velY = .5;
int health = 10;
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
Rectangle2D square = new Rectangle2D.Double(x, y, 10, 10);
g2.fill(square);
t.start();
}
public double adjustHorizontalSpeed() {
y += velY;
return y;
}
public double adjustVerticalSpeed() {
x += velX;
return x;
}
public void actionPerformed(ActionEvent e) {
adjustHorizontalSpeed();
adjustVerticalSpeed();
repaint();
}
}
Buttons.java
import java.awt.*;
import java.awt.event.*;
import javax.swing.JButton;
import javax.swing.JFrame;
public class Buttons extends JFrame implements ActionListener{
private JButton shoot;
public Buttons(){
shoot = new JButton("Shoot!");
shoot.setBounds(50,60,50,100);
shoot.addActionListener(this);
}
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
}
}
Buttons shouldn't extend JFrame if all you want to do is use it to create a JButton that you wish to add to another GUI. Instead perhaps give it a public method called getShoot() that returns the button created:
public JButton getShoot() {
return shoot;
}
Next, to do things in a timed fashion, you should use a Swing Timer. The tutorials will tell you how to do this: How to use Swing Timers
Next, you'll want to read the Swing tutorial section on how to use layout managers so you can add a complex mix of components to the GUI and have them all fit well together: Laying out Components in a Container
Finally, as for this:
Then, how would I force them to follow a predetermined path that scales to somebody dragging the box around?
You'll have to describe this better for me to understand what you're trying to do.
For the predetermined path, you should probably have them move/size themselves proportional to the containing pane. With a layout manager, assuming they are inside their own JPanel, the pane should scale automatically, so when the window is resized, the shapes will resize and move properly.

Categories

Resources