There are two java files Animate and Anim1.The Anim1 file has the JFrame and I want to attach the Animate file which has the logic of text scrolling by the screen(supposed to be the JFrame screen).But I cannot find a way.And also the code is throwing the following compile time error-
Exception in thread "Thread-0" java.lang.Error: Unresolved compilation problem:
The method repaint() is undefined for the type Animation
import java.awt.Graphics;
public class Animation implements Runnable {
int x=500;
String s="hello world";
public void run(){
while(true){
repaint();
try{
Thread.sleep(50);
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
public void paint(Graphics g){
g.drawString("hello world", x,-10 );
x--;
if(x< -100){
x=500;
}
}
}
import java.awt.Component;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Anim1 {
public static void main(String[] args){
Animation a= new Animation();
Thread t= new Thread(a);
t.start();
JFrame frame= new JFrame("animate");
frame.setVisible(true);
frame.setSize(400,400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
The repaint method is found in Swing components -- same for the paint and paintComponent. Calling it inside of a class that does not extend a Swing comopnent does not make sense unless you're making the repaint call on another object that is a component. Likewise giving a non-component class a paint method makes no sense since you're not overriding any painting method.
Likely your Animation class should extend JPanel so that it can override paintComponent (not paint) and so that the repaint() call makes sense. Also always pre-pend your painting method (or any other method that you think overrides a parent method) with the #Override annotation. This way the compiler will complain to you when you're not overriding the method correctly (or at all). You'll also want to call the super's painting method inside of your override.
Most important: read the Swing painting tutorials as it's all explained there. Check out: Performing custom painting
Your painting method would look something like so:
#Override
protected void paintComponent(Graphics g) {
// always call the super's method to clean "dirty" pixels
super.paintComponent(g);
// then draw the String. Make y a field too, so it can be controlled
// more easily
g.drawString(s, x, y);
}
Note that I don't change the x value or call any state-changing code within my painting method, and that's by design. The paintComponent method is for painting only. You don't have full control over whether or even if it will be called, and it can be called multiple times.
Instead the x value should be changed within the "game loop", here your Runnable's run() method. Also, as per my comments, while this code can be created using Thread/Runnable, it's safer to instead use a Swing Timer to drive the animation instead, since this saves you from having to worry so much about Swing threading issues.
Perhaps .repaint() needs to be passed something to work. Often animations will take place on a canvas then you would update that. The update method would have to be made separate with all of the things you wish to update.
canvas.update()
public void update(){
what it is you wish to update
canvas.draw()
}
I hope this helps. EDIT so your canvas is your JFrame
Related
So I'm trying to display an image(ball) which I'll eventually control with user input. For know, the image just gets displayed over intervals using thread's sleep method.
I've made 2 classes, one that extends JPanel and the other extends JFrame.
The JPanel subclass looks like this:
public class BallPanel extends JPanel {
private Image ball;
private int x,y;
public BallPanel(){
try {
ball=ImageIO.read(new File("C:\\Users\\Owner\\Desktop\\ball.png"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
x=10;
y=10;
Thread thread = new Thread() {
#Override
public void run(){
loop();
}
};
thread.start();
}
public void paintComponent(Graphics g){
super.paintComponent(g);
g.drawImage(ball,x,y,null);
}
public void loop(){
while(true){
repaint();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
In the loop method I call the sleep method to allow repaint to be called over intervals. Then, loop() is called in the constructor.
The JFrame subclass looks like this:
public class BallFrame extends JFrame {
public BallFrame(){
setVisible(true);
setSize(800,800);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setContentPane(new BallPanel());
}
public static void main(String args[]){
//SwingUtilities.invokeLater(new Runnable() {
// #Override
// public void run() {
new BallFrame();
// }
//});
}
}
Now the interesting, or perhaps confusing thing, is that when I run the code as it is shown here, with the anonymous inner class commented out, the ball doesn't always appear. Sometimes I need to re-size the frame (i.e call repaint) before the ball is shown. However, when I call it through the even dispatch thread using the anonymous inner class the ball appears every time I run the code. What is the reason for this?
It has little to do with starting the UI from within the EDT or not (although you should cause that can cause lots of other weird and interesting issues) and more to do with the fact that you've called setVisible before you've established the contents of the UI.
This is possibly an example of a race condition between the system trying to get the EDT up and running and the OS calls responding before it's established.
In either case you SHOULD start the UI from within the EDT and call setVisible last.
Swing can be lazy about updating the UI, this is actually a deliberate design choice as well as a good idea. You don't always want the UI updated after each and every change you make (like adding/removing components), so it hands over some of the control to the developer to decided when it's best to revalidate container hierarchy and request repaints
I would also avoid using a Thread to update the state of the UI as this could cause dirty paints as Swing uses a passive rendering approach (painting when it feels it's required) and consider using a Swing Timer which updated from within the EDT OR use a BufferStrategy and employ a active rendering approach, which you can then control
I have an application that is using a BufferStrategy created by a JFrame object to paint shapes. The code is pretty standard, what you would find elsewhere:
// JFrame class
frame.setVisible( true );
frame.createBufferStrategy( 2 );
new Logic( frame.getBufferStrategy() ).loop();
// Logic class
public Logic( BufferStrategy bs ){
this.bs = bs;
}
public void loop(){
// looping should be in another thread
Thread loop = new Thread(new Runnable() {
public void run(){
looooooooop();
}
});
loop.start();
}
Now the looooooooop function is where the drawing is actually happening:
g = (Graphics2D)bs.getDrawGraphics();
// draw stuff here, leaving out for simplicity
g.dispose();
bs.show();
Toolkit.getDefaultToolkit().sync();
Now the issue is about 75% of the time the application boots up and runs great, the other 25% of the time the frame appears but only the background colour of the frame can be seen, it is like the graphics objects isn't drawing anything on the screen. I have tried debugging and figuring out were this issue is stemming but it is really hard to do so. I am thinking it has something to do with the logic loop running in another thread (maybe this explains the inconsistent nature of the application) but haven't had any luck. Does this issue sound familiar to anyone? Thanks!
Edit - After removing the separate thread this is still happening so it can't be because of that.
Edit 2 - It seems like this is only happening when full screen mode is enabled (with or without the call to setVisible()):
this.setVisible( true );
if(isFullScreen){
GraphicsEnvironment
.getLocalGraphicsEnvironment()
.getDefaultScreenDevice()
.setFullScreenWindow(this);
}
Is this a known issue or am I missing something? Thanks!
Edit 3 - This is only happening on Ubuntu - verified through brute force. Can't find anything online regarding a bug so I am not sure what to think.
If you think creating a thread is necessary (I don't think so), I would do this instead:
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
looooooooop();
}
});
My recommendation is to try it without creating the new thread.
UPDATE:
Try these events in this order:
// Create a canvas object (where you are actually doing the drawing)
frame.add(canvas);
frame.setVisible(true);
canvas.createBufferStrategy(2);
canvas.requestFocus();
// Do your drawing now.
You can't create the buffer before it's displayed. Also, if you are calling pack() on the frame anywhere on your code, just remove it.
I am writing a 2D strategy game and require to be able to display hundreds of images at one time.
So far I have many classes, but I have one dilemma as I fear I do not understand the JFrame components well enough. I have written a smaller 3 class program to show my problem:
First I have a main class which constructs the frame:
import javax.swing.JFrame;
public class MainClass {
static JFrame Frame = new JFrame("MainFrame");
public static void main(String[] args){
Frame.add(new Board());
Frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Frame.setSize(1024, 500);
Frame.setVisible(true);
Frame.setResizable(false);
}
}
Currently the board class is the class which sits at the center of the program and pulls all of the strings to make the program run. Previously all of the tutorials I have seen on the internet have pointed towards having the paint(Graphics g) method inside the board class, but this gives me the main dilemma. Currently I have to type out manually every time I want something painted to the screen:
public board{
//......code....
public void paint(Graphics g){
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
g2d.drawImage(b.getImage(0), 0, 0, null);//Black
g2d.drawImage(b.getImage(1), GameMachanic.getCurrentPosX(), GameMachanic.getCurrentPosY(), null);//background
g2d.drawImage(b.getImage(3), GameMachanic.getCurrentPosX(), GameMachanic.getCurrentPosY(), null);//background
//...more paint to screen code
}
//......code......
}
This method is repainted every few milliseconds and everything is great! except... now I have gotten to the point where I need hundreds of different elements painted to the screen at one time, from different classes and with this current method U have to type out manually each and every paint command, making the code ineffective and frankly pointless.
Therefore I tried making a class that replaces the need of this manual labour, making the method reusable, but I am finding it extremely hard to make it work:
public class GraphicsPaint extends JFrame{
public void paint(Graphics g, ){
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
g2d.drawImage(b.getImage(0), 0, 0, null);//image
}
}
But how do I implement this class into my code, do I add it as a component? (And if so, how?) Because I have tried this and it just throws an error at me, and I have tried using a few layouts but they just glitch up for some reason.
Do I add them to Panels? I have no idea how that would pan out..
Other than that I am clueless as I have spent the whole day looking at this problem.
What is an effective way of painting hundreds of images to a JFrame at a time?
Put them in a collection such as an ArrayList.
Iterate the collection in a loop.
Within the loop body, paint each member of the collection in turn.
I'm new to Java. I need help figuring out some of the code I'll be displaying below. The point of the code is to simply create an applet which displays a ball moving from left to right using a change in X position. I have began following a tutorial for applets from a website which made this code available to me (http://www.javacooperation.gmxhome.de/BallBewegungEng.html). Basically, I need someone to explain to the following methods and their contents: the start method (what is a thread? I'm aware it's an object, but what purpose does it serve here?). The run method (what exactly am I doing when I set the thread priority to MIN/MAX? Why does this method call the repaint() method even when no such method has been created?). Lastly, the paint method (what exactly is the g.fillOval line doing and how?). I've tried googling these things, but I'm having a hard time understanding understand the jargon that I see with most answers. I need things explained in a more simplistic way so that I may understand the jargon later on.
Thanks for any help in advance. The code:
import java.applet.*;
import java.awt.*;
public class MovingBall extends Applet implements Runnable
{
int x_pos = 10;
int y_pos = 150;
int radius = 20;
public void init()
{
setBackground (Color.blue);
}
public void start()
{
Thread th = new Thread(this);
th.start();
}
public void stop()
{
}
public void destroy()
{
}
public void run()
{
Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
while(true)
{
x_pos++;
repaint();
try
{
Thread.sleep (20);
}
catch(InterruptedException ex)
{
}
Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
}
}
public void paint (Graphics g)
{
g.setColor (Color.red);
g.fillOval (x_pos - radius, y_pos - radius, 2 * radius, 2 * radius);
}
}
A thread is something you use when you want to run multiple pieces of code at the same time, without interrupting the other threads. In this case you use the thread to repaint the screen and pause the loop without affecting the rest of the program.
The run method is overriding from the Runnable object that you pass to the thread to run. When you create a thread, you pass it a runnable object with a run method defined, which will run when the thread starts.
The repaint method is not defined in this class, however it is defined in the parent class(Applet), so you can call it in this class just fine.
The paint method is overriding from Applet as well, so you are defining what the applet will do when it runs the paint method.
Recently I've started coding some Java 2D.
I made this:
public void paintComponent(Graphics comp) {
Graphics2D comp2D = (Graphics2D) comp;
Font fontx = new Font("Verdana", Font.BOLD, 5);
comp2D.setFont(fontx);
comp2D.drawString("Hello World!", 5, 50);
}
I did import JFrame and java.awt.*, but there's still a problem.
When I run it, I get this:
Exception in thread "main" java.lang.NullPointerException
at game.Game.paintComponent(Game.java:41) - comp2D.setFont(fontx); - Sets Font
at game.Game.next(Game.java:36) - paintComponent(null); - calls the paintComponent public void from the next() public void
at game.Game.main(Game.java:26) - next.next(); - calls a public void called "next" using an object called "next" (this public void throws InterruptedException)
Java Result: 1
How can I solve it?
You state:
Exception in thread "main" java.lang.NullPointerException
at game.Game.paintComponent(Game.java:41) -
comp2D.setFont(fontx); - Sets Font
This means that comp2D is null and you're trying to call a method on a null variable.
at game.Game.next(Game.java:36) - paintComponent(null);
- calls the paintComponent public void from the next() public void
This means that you're calling paintComponent directly and passing in null!
So you're calling paintComponent directly and passing in null! It should come as no surprise that the Graphics object is null and will throw a NPE if you try to call methods on it.
Solution:
You almost never call paintComponent directly.
Instead have the JVM call it when you call repaint(). The JVM will pass in a valid Graphics object.
Most important -- read the painting with Swing tutorial. You can't guess at this stuff and expect it to work.
Be sure that your paintComponent method is held within a JPanel or other JComponent derived component.
Be sure that your override is valid by using the #Override annotation for paintComponent.
Don't neglect to call the super.paintComponent(...) method within your override.
For example, have your other method change a class field, say have it change a String field called text, then call repaint(), and then have your paintComponent(...) method use the text field for the text to print in the JPanel. This is just an example. You can change any of the drawing component's fields, and then use them inside of paintComponent(...).