How to fix movement with Graphics2D using thread? - java

public class Billiard extends JPanel
{
// Constructor
public static Ball ball[] = new Ball[16];
private static int x = 0;
private static int y = 0;
public Billiard () {
super ();
// White Ball.
ball[15] = new Ball(x+50,y+165,15);
}
public void paintComponent (Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint (RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint (RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_SPEED);
g2d.setRenderingHint (RenderingHints.KEY_COLOR_RENDERING,
RenderingHints.VALUE_COLOR_RENDER_SPEED);
super.paintComponent (g);
for (int i = 0; i < 16; i++) {
ball[i].paint (g2d);
}
for(int n = 0; n<100; n++){
ball[15].move(4,0);
repaint();
try
{
Thread.sleep(7);
}
catch(Exception e)
{
System.out.println("Error");
}
}
}
}
When i use .move() on its own it moves the ball, however i cant seem to make the ball move smoothly using threads an repaint, any advice, i have declared the balls using a constructor from a different class, and these balls are being painted to a window in a another class and im adding them to it using setContentPane.

You shouldn't need to use multithreading to make this render smoother. You will need to tune your ball movement speed and your frame rate.
Right now, you are moving the ball in every single frame which is likely what is making it jump so much. Additionally, you are only sleeping for 7 ms between frames which is very rapid.
My advice:
1) Handle the ball movement outside of the frame rendering loop. I don't think you want to move it on every single frame.
2) Increase the sleep time between frames until the movement looks more natural. Try 50/100 for starters and increase it if your animations are too fast. Decrease it if they are too slow.

Related

repaint() doesn't work outside of keylistener

Over the past week or so I've been working on a game, where you're a white square that tries to dodge red squares which fall from the top of the screen. You can only move left and right, there are only 3 available positions to move to (left, middle, right), and the red square begins to fall faster as the game progresses. When I move the player (white square) everything repaints just fine, but when the red square's position updates it doesn't repaint at all. Say the red square moves once every second; if I wait one second, the repaint doesn't do anything. However, if I wait one second (or any amount of time) and then move the player, both squares jump to their new positions at once. After looking through the code for an hour, I still can't find any issues with it, and it doesn't help that I'm very new to coding, which probably means it's a really obvious mistake.
import java.util.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JComponent;
import javax.swing.JFrame;
public class boxface extends JComponent implements KeyListener {
private static int x=0, y=0;
static int counter = 0;
static Thread t = new Thread();
public void keyPressed(KeyEvent e) {
if(e.getKeyCode()== KeyEvent.VK_RIGHT)
moveRight();
else if(e.getKeyCode()== KeyEvent.VK_LEFT)
moveLeft(); }
public void keyReleased(KeyEvent e) {}
public void keyTyped(KeyEvent e) {}
static Rectangle player = new Rectangle(x, 400, 50, 50);
Rectangle bg = new Rectangle(0, 0, 700, 750);
static int x2 = ((int)((Math.random()*3)))*50;
static Rectangle enemy = new Rectangle(x2, y, 50, 50);
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.BLACK);
g2.fill(bg);
g2.setColor(Color.WHITE);
g2.fill(player);
g2.setColor(Color.RED);
g2.fill(enemy); }
public void moveLeft() {
if(x > 0) {
x -= 50;
player.setLocation(x, 400);
repaint();}}
public void moveRight() {
if(x < 100) {
x += 50;
player.setLocation(x, 400);
repaint();} }
public void enemyDown() {
if(enemy.getBounds().y == 400) {
x2=((int)((Math.random()*3)))*50;
y=0;
enemy.setLocation(x2, y);
counter++;
repaint(); }
else {
y = y + 50;
enemy.setLocation(x2, y);
repaint();}}
public boxface(){
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false); }
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setBounds(400, 200, 156, 479);
f.setMinimumSize(new Dimension(156, 0));
f.setResizable(false);
f.getContentPane().add(new boxface());
f.setVisible(true); }
});
boxface exec = new boxface();
int t = 20;
for(long i = 0; i < 21; i++) {
if(i == t) {
exec.enemyDown();
i = 0; }
if(counter == 10) t = 15;
if(counter == 25) t = 10;
if(counter == 50) t = 7;
if(counter == 100) t = 5;
if(counter == 150) t = 3;
if(counter == 225) t = 1;
if(enemy.intersects(player))
break;
System.out.println(i); }
}
}
Swing uses a "passive rendering" algorithm. This means that the UI will be updated at irregular intervals based on decisions been made by the RepaintManager
See Painting in AWT and Swing for more details
What you need is some way to schedule regular updates. Before I discuss that, some basic game theory...
Game/Main Loop...
Most games have a concept of a "main loop". The "main loop" does a number of jobs, it:
Updates the state of the game. This includes:
Updating the position of the player based on the current state of the input (keyboard/mouse/joystick)
Updating the position of other objects/obstacles within the world
Collision detection
Other states which need to be updated before they can be rendered
Rendering the current state
While you could use a Thread to accomplish this, Swing is NOT thread safe, meaning, you should never update the state of the UI (or any state that the UI relies on) outside the context of the Event Dispatching Thread. Swing is also single threaded, so you can't simply use Thread.sleep or some other loop within the context of the Event Dispatching Thread either.
The simplest solution would be to use a Swing Timer. This is pseudo loop, which is called repeatedly after a specified delay. Each time the timer is triggered, you'd perform the "main loop" operations and call repaint, thus, schedule a (mostly) regular update to the UI.
See How to use Swing Timers for more details
Other considerations...
Because the state of the game is actually updated within the "main loop", you can no longer respond to key events directly. Instead, you need to set a series of flags indicating the current state of your input triggers (ie isAPressed at its simplest form).
In most cases, this would invoke a Set and predefined series of inputs. I like to use a enum as it clearly defines the accepted inputs (up/down/left/right etc...). When pressed, you add the appropriate input to the Set and on release, you remove it. It deals with any repeated states and removes the oddity of the delay between the first press and the repeated key events.
Talking about key events. KeyListener has known issues, while there are "hacks" to "work around" it, they are just that, "hacks".
The recommend method for monitoring for (limited) key input is to use the key bindings API

HOw to move my bullet slowly in java?

Hi I am developing a game that a fighter moves right and left and shoots. For the shooting part, I tried to use a for loop to slow the speed down and user can see the bullet. But it wasn't enough. I used sleep too but not a good answer. Now I have no idea what to do.
Here is my paintComponent calss:
package game;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import javax.imageio.ImageIO;
import javax.swing.JPanel;
public class PaintComponent extends JPanel implements KeyListener {
int dx = 200-15;
int dy = 450;
int my = 450;
ArrayList<Bullet> bullets = new ArrayList<>();
public Rectangle2D rec =new Rectangle2D.Double(dx , dy, 30, 10);
Rectangle2D recB = new Rectangle2D.Double(dx+13 , my, 6, 6);
// public Polygon pol = new Polygon
private BufferedImage imageBg, imageFi, imageBu;
public PaintComponent() {
this.addKeyListener(this);
this.setFocusable(true);
this.setBackground(Color.white);
try {
imageBg = ImageIO.read(new File("C:\\Java\\NetbeansProjects\\Game\\bg.jpg"));
imageBu = ImageIO.read(new File("C:\\Java\\NetbeansProjects\\Game\\bul.png"));
imageFi = ImageIO.read(new File("C:\\Java\\NetbeansProjects\\Game\\fi.png"));
} catch (IOException ex) {
System.out.println("No background image is available!");
}
}
public void shoot(){
if(bullets != null){
for(int i=0; i<bullets.size(); i++){
for(int j=0; j<200; j++){
bullets.get(i).setdy(my-j);
}
System.out.println(bullets.get(i).getdy());
}
}
}
public void moveRec(KeyEvent evt){
switch(evt.getKeyCode()){
case KeyEvent.VK_LEFT:
dx -= 5;
rec.setRect(dx, dy, 30, 10);
recB.setRect(dx+13, dy, 6, 6);
repaint();
break;
case KeyEvent.VK_RIGHT:
dx += 5;
rec.setRect(dx, dy, 30, 10);
recB.setRect(dx+13, dy, 6, 6);
repaint();
break;
case KeyEvent.VK_SPACE:
Bullet b = new Bullet(dx, dy);
bullets.add(b);
shoot();
break;
}
}
#Override
public void paintComponent(Graphics grphcs)
{super.paintComponent(grphcs);
Graphics2D gr = (Graphics2D) grphcs;
int X = (int) rec.getCenterX();
int Y = (int) rec.getCenterY();
gr.drawImage(imageBg, 0, 0, null);
gr.drawImage(imageFi, X-50, Y-75, null);
gr.setColor(Color.GRAY);
if(bullets != null){
for(int i=0;i<bullets.size();i++){
gr.drawImage(imageBu, null, bullets.get(i).getdx(), bullets.get(i).getdy());
repaint();
}
}
gr.draw(recB);
}
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent e)
{moveRec(e);}
#Override
public void keyReleased(KeyEvent e)
{}
}
and this is my bullet calss:
package game;
public class Bullet {
private int x, y, newy;
public Bullet(int x, int y){
this.x = x;
this.y = y;
}
public int getdy(){
return y;
}
public void setdy(int newy){
y = newy;
}
public int getdx(){
return x;
}
}
I think you are going wrong with slowing down the loop. The last thing you want to do is slow down the game loop or sleep the game loop. This will affect all you objects with in the game.
There are multiple way to go about this:
Smaller increments per tick
One of the most obvious things you could do is make the increment of the bullet smaller. Lets take a look at your shoot(); method:
public void shoot(){
if(bullets != null){
for(int i=0; i<bullets.size(); i++){
for(int j=0; j<200; j++){
bullets.get(i).setdy(my-j);
}
System.out.println(bullets.get(i).getdy());
}
}
}
As far as i understand you are iterating 200x over all the bullets, each tick the bullet's y axis gets changed, using the formula "my - j" or "450 - the tick index"
In order to slow down the bullet you would need to divide the j with a certain number to get the desired speed of the bullet. For instance: "my - (j / 2)" would impact the speed of the bullet. Try to play around with these variables to get the desired speed.
Adding a speed modifier
What a lot of games to is a speed modifier or a base speed for each projectile. This could be of use to you, the only thing i noticed that you are kinda trying to simulate loss of velocity. To achieve this result you would need another variable. Let call that "time to live" for right now.
So if we modify the bullet class it would look like this. Noticed we also have a new function called Move();. This will calculate the next move based upon the variables.
public class Bullet {
private int x, y, newy;
private speed, ttl; //ttl = time to live
public Bullet(int x, int y, int speed){
this.x = x;
this.y = y;
this.speed= speed;
this.ttl = 250;
}
public int Move()
{
//Do some calculation to perform loss of velocity within a reasonable range. Because these number might be overkill
this.speed -= (ttl / 100);
y += this.speed;
ttl--;
}
public int getdy(){
return y;
}
public void setdy(int newy){
y = newy;
}
public int getdx(){
return x;
}
}
What the code now does is it calculates the speed based upon the time to live variable the longer the bullet live the less velocity it will have. Adjusting the speed variable makes you able to control the bullet better. And to say so myself it looks a lot more neater in the shoot method:
public void shoot(){
if(bullets != null){
for(int i=0; i<bullets.size(); i++){
bullets.get(i).Move();
}
}
}
Of course there is more to it, like checking if the speed and time to live dont go out of bounds and stuff, but i think your smart enough to figure that out ;)
Running it off a timer
As ControlAltDel said you can implement a timer, im not an expert on java so im not going in depth on this. But it surely it is a possibility. Its nothing more then implement the current shoot method inside the tick function of the timer. Of course removing the for i<200 loop. Since its not very effecient.
Anyways
If i did get something wrong or misunderstood (or even grammer mistaked :) ) the problem, im sorry. If there are any question i loved to hear from you ;).
And please not that this is untested code and im only here to explain things you could try to get it working a intended!
Sincerly,
Syntasu.
UPDATE:
Some explaining on how to update the bullet's.
In order to update the bullets we need to make it run off a loop. Since in this case the main loop is were also where the drawing is happening, the "paintComponent" method. There is already a loop withing the paint component to draw the bullet, only thing we have to do is to add our logic regarding the .Move(); method.
The paint component will look as following ( + i also fixed the tabbing ):
#Override
public void paintComponent(Graphics grphcs)
{
super.paintComponent(grphcs);
Graphics2D gr = (Graphics2D) grphcs;
int X = (int) rec.getCenterX();
int Y = (int) rec.getCenterY();
gr.drawImage(imageBg, 0, 0, null);
gr.drawImage(imageFi, X-50, Y-75, null);
gr.setColor(Color.GRAY);
if(bullets != null)
{
for(int i=0;i<bullets.size();i++)
{
//Here is were we loop over the bullet list, lets add the move method
bullets.get(i).Move();
gr.drawImage(imageBu, null, bullets.get(i).getdx(), bullets.get(i).getdy());
repaint();
}
}
gr.draw(recB);
}
The thing is added is "bullets.get(i).Move();". This will now run every frame. This will work in theory (inb4 im not testing these codes). Going by the assumption you use multiple instance's of the bullet class, each class should encapsulate their own speed and time to live variable.
Implementing this will make the shoot method obsolete. What you can do is move the code inside the paintComponent that is related to shooting and move that to the shoot function.
Regarding the time to live variable, i would like to add one more piece to the code. This will take care of garbage collection of bullets. Since now they live indefinitly:
for(int i=0;i<bullets.size();i++)
{
Bullet b = bullets.get(i);
if(b.ttl >= 1)
{
bullets.get(i).Move();
gr.drawImage(imageBu, null, b.getdx(), b.getdy());
}
else
{
//Remove the bullet from the list
//In C# its bullets.Remove(b);
}
repaint();
}
Hopefully this resolves the issue of the bullet not moving. And potential performance issue due the bullets not being destroyed. In before, it there are any questions i love to hear them! ;)
Finally I did it with adding a timer in my bullet class and repaint() in my paintcomponent method!
package game;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Timer;
public class Bullet {
private int x, y;
private int speed, ttl;
public final Timer timer1;
public Bullet(int x, int y, int speed){
this.x = x;
this.y = y;
this.speed= speed;
this.ttl = 250;
ActionListener actListener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Move();
}
};
this.timer1 = new Timer(50, actListener);
timer1.start();
}
public int getdy(){
return y;
}
public void setdy(int newy){
y = newy;
}
public int getdx(){
return x;
}
public int Move(){
//Do some calculation to perform loss of velocity within a reasonable range. Because these number might be overkill
this.speed -= (ttl / 100);
y += this.speed;
ttl--;
return y;
}
}
In your game loop make it update the bullet every so many ticks. You most likely never want to use sleep to slow down something in a game as it will need a new thread or it will sleep the whole game.
If you do not know what a game loop is, a game loop is basically a loop which continually takes input, updates the game (such as a bullet), renders everything, then pauses the entire program (you can use sleep) for the amount of time which the loop has left over from what is expected. You also want to update the game according to how many ticks or milliseconds have passed since the last update. This will prevent the game from running faster or slower on different computers.
I haven't read this all the way but THIS might help.
Also, not sure if this is correct, I think using Canvas instead of a JPanel will be better for making a game. It is what I used for my first java game.
Edit:
If you want to use JPanel and no game loop you can make the shoot method create a new thread and use the sleep to slow it down. Also the way you have the shoot method setup can cause problems if multiple bullets are shot because it will loop through each bullet in two separate loops and if you have a separate thread the bullets array can be modified while it is looping in one thread therefor causing an error.
Try this:
public void shoot(Bullet bullet){
new Thread(new Runnable(){
for(int j=0; j<200; j++){
bullet.setdy(my-j);
try{
Thread.sleep(time);//set the time
catch(Exception e){
e.printStackTrace();
}
}
System.out.println(bullet.getdy());
getBullets().remove(bullet);
}).start();
}
Create a method called getBullets(). Make sure it has the synchronized modifier.
protected synchronized ArrayList<Bullet> getBullets(){
return bullets;
}
This will make sure it can only be modified by one thread at a time.
Finally where the player presses space, change bullets.add(b); to getBullets().add(b);

JPanel only showing one object

I've made 20 objects from my Ball class, as I need 20 balls bouncing around on the screen, but right now it only shows 1 ball bouncing around.
I think it has something to do with 20 JPanels being added and they are overlapping each other, but I'm not entirely sure.
package com.company;
import javax.swing.*;
import java.awt.*;
import java.util.Random;
/**
* Created by John on 25/02/2015.
*/
public class Ball extends JComponent{
int _speedX;
int _speedY;
int _size;
int _x;
int _y;
Color _color;
int _windowX;
int _windowY;
Ball(int x, int y, int sz, int sX, int sY, Color c, int windowX, int windowY){
_x = x;
_y = y;
_speedX = sX;
_speedY = sY;
_size = sz;
_color = c;
_windowX = windowX;
_windowY = windowY;
setForeground(_color);
}
public void update(){
_x = _x + _speedX;
_y = _y + _speedY;
if (_x<0 || _x>_windowX-_size){
_speedX*=-1;
}
if (_y<=0 || _y>_windowY-_size){
_speedY*=-1;
}
this.repaint();
}
public static int randInt(int min, int max) {
// NOTE: Usually this should be a field rather than a method
// variable so that it is not re-seeded every call.
Random rand = new Random();
// nextInt is normally exclusive of the top value,
// so add 1 to make it inclusive
int randomNum = rand.nextInt((max - min) + 1) + min;
return randomNum;
}
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
g2d.fillOval(_x, _y, _size, _size);
}
public static void main(String[] args) {
// write your code here
JFrame frame = new JFrame("Title"); //create a new window and set title on window
frame.setSize(600, 600); //set size of window
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //set the window to close when the cross in the corner is pressed
frame.setVisible(true); //make the window visible
JPanel panel = new JPanel();
frame.add(panel);
Ball[] balls = new Ball[20];
for(int i = 0; i<20;i++){
balls[i] = new Ball(randInt(0,600),randInt(0,600),randInt(10,20),randInt(1,8), randInt(1,8),Color.yellow,600,600);
panel.add(balls[i]);
}
while(true){
for(int i = 0; i < balls.length; i++) {
balls[i].update();
}
panel.repaint();
try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); }
}
}
}
Suggestions:
Don't make Ball extend JComponent or JPanel, but instead make it a logical non-component class.
Create a Drawing class that extends JPanel and draw in its paintComponent method, not its paint(...) method. This will lead to smoother animation.
Create an ArrayList<Ball> of your Ball objects and draw them inside of the paintComponent(...) method override by iterating through the list.
Same for moving the Balls held by the List.
Use a Swing Timer to drive your animation, not a while (true) loop. If you make one mistake with that loop, you'll freeze your GUI rendering it non-functioning, and so the Swing Timer is a much safer way to do this.
it only shows 1 ball bouncing around.
I'm surprised you even see one. You shouldn't see any.
I think it has something to do with 20 JPanels being added and they are overlapping each other,
The problem is that by default a JPanel uses a FlowLayout. When you add a component to the panel the panel will respect the preferred size of the component. You are using a custom component and the default size is (0, 0) since you didn't provide one.
If you want to continue this approach by using a custom component then you need to:
use the properties of the component to control the size and location of the component on the panel. That is you can use the setSize(...) method and setLocation(...) method. You don't need your _x, _y and _size variables. You also don't need the color variable because you can use setForeground(...) to set the color of your component.
Override the getPreferredSize() method to return the size of the ball.
Override the 'paintComponent(...)` method to fill the oval with an x/y value of 0, since the painting needs to be done relative to the ball, not the panel.
In the update() method you use the setLocation(...) method to set the location of the component on the panel.
Now you also need to use a null layout on your panel so the balls can move randomly.
I don't recommend this approach for your final solution, but it is a good exercise to implement this logic to understand how you might go about creating a custom component and how painting is done on this component. Understanding this concept will help you better understand how Swing works in general.

Paint Method within an ActionListener

I am trying to use the Java paint method within an ActionListener. However, when paint is placed within the ActionListener, my compiler throws errors, and eclipse does not recognize paint as a method at all, despite importing java.awt.geom.*;
private class NumHandler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
//Draw Ovals
public void paint (Graphics g)
{
int number;
int x = 10;
int y = 30;
int width = 20;
int height = 10;
number = Integer.parseInt(numberTF.getText());
for (int i = 0; i < number; i++)
{
g.drawOval(x, y, width, height);
x += 5;
y += 5;
width += 5;
height += 5;
}
}
}
}
Your paint method cannot be inside your actionPerformed method. It needs to exist as a class member method of your component rather than NumHandler. You could place a single repaint() call in your ActionListener method to request that a repaint be carried out.
Don't place any logic that is likely to lead to an exception in your paint method, namely:
number = Integer.parseInt(numberTF.getText());
This is better done in the actionPerformed method.
Also if using Swing, paintComponent is preferred for optimized paint performance. Remember to call super.paintComponent(g); to repaint any child components.
See: Painting in AWT and Swing

setBackgrounds throws exception in Windows (but not in MacOSX)

I was trying to have a image background, so I created the following code in a JFrame:
#Override
public void paint(Graphics g) {
super.paint(g);
try {
final Image image = ImageIO.read(getClass().getResource("/images/login/gentlenoise100.png"));
int iw = 256;
int ih = 256;
for (int x = 0; x < getWidth(); x += iw) {
for (int y = 0; y < getHeight(); y += ih) {
g.drawImage(image, x, y, iw, ih, this);
}
}
} catch (IOException ex) {
Logger.getLogger(Login.class.getName()).log(Level.SEVERE, null, ex);
}
for(Component componente:getComponents()){
componente.repaint();
}
}
I saw that the background color had some kind of preference and I decided so set it to invisible:
setBackground(new java.awt.Color(0,0,0,0));
It was working fine in Mac OS X (java 1.6), and I had to probe it in Windows and if I remove the setBackground call it doesn't show my background, if I keep the background color invisible it throws an exception and says the Frame is decorated!
I tried to use setUndecorate(true) but in macosx it looses the title bar (of course) and in Windows it gives me a transparent window.
How can I solve that?
there are three ways, to use
JComponent#setOpaque() in the case that you don't want to panting background
How to Create Translucent and Shaped Windows on Win, OSX a few ***unix
for Transparency have to change value of AlphaComposite
don't paint() whatever to JFrame, put there JPanel and override paintComponent()
If you can avoid it, don't override the paint methods of top level containers (like JFrame), they do to many important things.
In the case, you'd be better of using a JPanel and setting the frames content pane to it...
Something like...
public class BackgroundPane extends JPanel {
private Image background;
public BackgroundPane() {
try {
background = ImageIO.read(getClass().getResource("/images/login/gentlenoise100.png"));
} catch (IOException ex) {
Logger.getLogger(Login.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
int iw = 256;
int ih = 256;
for (int x = 0; x < getWidth(); x += iw) {
for (int y = 0; y < getHeight(); y += ih) {
g.drawImage(background, x, y, iw, ih, this);
}
}
}
}
//...
JFrame frame = new JFrame();
frame.setContentPane(new BackgroundPane());
//...
Don't do anything in your paint method's that are either time consuming or that may cause the repaint manager to schedule your component for repainting again
Things like...
final Image image = ImageIO.read(getClass().getResource("/images/login/gentlenoise100.png"));
and
for(Component componente:getComponents()){
componente.repaint();
}
Inside you're paint method is an really bad idea.
The second one could cause the repaint manager to decide that the parent container (your frame) needs to repainted, over and over and over and over again...eventually consuming your CPU...
Beware, as of Java 7, calling setBackground with a color that that contains a alpha value of less then 255 on Window will cause the window to become transparent.
Window.setBackground(Color) Passing new Color(0,0,0,alpha) to this
method, where alpha is less than 255, installs per-pixel translucency
This will also throw an exception if the window is decorated...

Categories