Use Timer class to call move() - java

ok so I created a method that randomly moves an enemy icon, and I used a Swing timer to make it constantly repeat and update every second or so, but the problem is the icon isn't moving it's just staying at the position, I added a print method to display my random numbers, and they are being created and displayed properly, but my enemy is not moving, any help is greatly appreciated :) and the ImageIcon for the bluespell class is a method that jus returns a regular ImageIcon there's nothing wrong with that method ha
public class BlueSpell extends WizardBattleGrid{
private int BlueSpellx;
private static int BlueSpelly;
private ImageIcon Blue;
WizardBattleRunner wbr = new WizardBattleRunner();
Timer timer;
public BlueSpell(int x, int y, ImageIcon BlueSpell){
BlueSpellx = x;
BlueSpelly = y;
Blue = BlueSpell;
}
public int getx(){
return BlueSpellx;
}
public int gety(){
return BlueSpelly;
}
public ImageIcon getIcon(){
return Blue;
}
public int changex(int x){
BlueSpellx = x;
return x;
}
public int changey(int y){
BlueSpelly = y;
return y;
}
public void shootSpell(){
final BlueSpell b = new BlueSpell(GoodGuy.getx(), GoodGuy.gety() +1, BlueSpellWizard());
int delay = 60;
timer = new Timer(delay,new ActionListener(){
public void actionPerformed(ActionEvent e){
if(b.gety() != 19){
WizardCells[b.getx()][b.gety()].setIcon(null);
WizardCells[b.getx()][b.changey(b.gety()+1)].setIcon(b.getIcon());
}
else{
WizardCells[b.getx()][b.gety()].setIcon(null);
b.changex(GoodGuy.getx());
b.changey(GoodGuy.gety() +1);
timer.stop();
}
}
});
timer.start();
}
}
WizardCells are in my Grid class here they are:
public class WizardBattleGrid extends GameWindowWizard {
public static JLabel[][] WizardCells = new JLabel [20][20];
public static JPanel WizardPanel = new JPanel(new GridLayout(20, 20, 0, 0));
static BufferedImage cursorimage = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB);
static Cursor blankcursor = Toolkit.getDefaultToolkit().createCustomCursor(cursorimage, new Point(0, 0), "blank cursor");
public static void CreateGrid(){
for(int i=0; i<WizardCells.length; i++ ){
for(int j=0; j<WizardCells[i].length; j++){
JLabel label = new JLabel();
WizardCells[i][j] = label;
}
}
for(int i=0; i<WizardCells.length; i++){
for(int j=0; j<WizardCells[i].length;j++){
WizardPanel.add(WizardCells[i][j]);
}
}
WizardCells[10][0].setIcon(GoodGuyWizardIcon());
WizardPanel.setOpaque(true);
WizardPanel.setBackground(Color.DARK_GRAY);
WizardPanel.setCursor(blankcursor);
gameWindow.add(WizardPanel);
}
}

Related

Painting with paintComponent in Java

I have a problem with my code.
We have to code a Game called "Mühle" as our project for this semester.
My problem is, that I want to draw my game token on the field and it does not work although the tokens are added to the board and you can click them but they are not visible and I don't know what I can do.
This is the important part frow my GUI Class:
public class GUIMühle extends JFrame {
static JLabel spieler1, spieler2;
static JFrame frame;
static JButton[] button;
static JButton btnReset;
static int x, y;
static int gewinner = 0;
static int player = 2;
static Buttons[] buttons;
static Steine[] steine1;
static Steine[] steine2;
public GUIMühle(){
InitUI();
}
private void InitUI(){
MouseEvents ME = new MouseEvents();
frame = new JFrame("Mühle");
frame.setSize(960, 540);
frame.setLocationRelativeTo(null);
frame.setLayout(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setBackground(Color.CYAN);
frame.setResizable(false);
DrawSpielbrett spielbrett = new DrawSpielbrett();
spielbrett.setBounds(0,0,960,540);
spielbrett.setVisible(true);
frame.add(spielbrett);
spieler1 = new JLabel("Spieler 1");
spieler1.setBounds(590, 50, 150, 35);
spieler1.setFont(new Font("Arial", Font.BOLD, 30));
frame.add(spieler1);
spieler2 = new JLabel("Spieler 2");
spieler2.setBounds(785, 50, 150, 35);
spieler2.setFont(new Font("Arial", Font.BOLD, 30));
frame.add(spieler2);
// Spielsteine
steine1 = Steine.Erstellen(Color.white, 9, 665, 85);
steine2 = Steine.Erstellen(Color.black, 9, 860, 85);
DrawSteine[] drawSteine1 = new DrawSteine[9];
DrawSteine[] drawSteine2 = new DrawSteine[9];
for(int i = 0; i < steine1.length; i++){
steine1[i].setBounds(steine1[i].getX(),steine1[i].getY(),30,30);
steine1[i].addMouseListener(ME);
steine1[i].setVisible(true);
frame.add(steine1[i]);
}
for(int i = 0; i < steine2.length; i++){
steine2[i].setBounds(860,85+(i*32),30,30);
steine2[i].addMouseListener(ME);
frame.add(steine2[i]);
}
And this is the part from my game token class:
public class Steine extends JLabel{
private Color farbe;
private int x;
private int y;
public Steine(Color farbe, int x, int y){
this.farbe = farbe;
this.x = x;
this.y = y;
}
public static Steine[] Erstellen(Color farbe, int anzahl, int x, int y){
Steine[] steine = new Steine[anzahl];
for(int i = 0; i < steine.length; i++){
steine[i] = new Steine(farbe,x,y);
y = y + 32;
}
return steine;
}
protected void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setColor(this.farbe);
g.fillOval(this.x, this.y, 30, 30);
repaint();
}
/*public static void DrawSteine(Steine stein){
GUIMühle.frame.add(stein);
}*/
public Color getFarbe() {
return this.farbe;
}
#Override
public int getX() {
return this.x;
}
public void setX(int x) {
this.x = x;
}
#Override
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
}
I hope somebody can help me with this problem.
Thank you in advance.

How do I paint multiple objetcs that move at different speeds in Java?

I am working on homework for class, and its late because I can't seem to understand the material despite all the research that I am doing. I am a beginner and do not know much in the way of java. Also, this is my first post so please be forgiving when you are reading this.
I am building on source code from my textbook, which I updated recently for past homework, but now I am trying to generate a class that draws multiple squares and moves those objects independently and at different speeds. They will all need to rebound off the walls as well. I followed the instructions and created two arrays that will hold the random x and y values between 1 and 10. However, I struggle with arrays and I am sure that I am not doing it correctly. So, I would love some feedback to see if I have it set up correctly.
I have a the jpanel pulling up and drawing, and as long as there is 1 square it is working fine bouncing off the walls, but things change when I draw more than one. The do not move independently and they also share the same speed. Some even disappear from time to time. This has really thrown me off. I appreciate any help!
In short, I am trying to paint new squares that all travel in different directions and at different speeds. Per the instructions we are suppose create and use a two arrays that handle the x and y values.
Here is what I have so far:
public class DotsPanel extends JPanel
{
private int delay = 15;
private final int SIZE = 7, IMAGE_SIZE = 3; // radius of each dot
private Timer timer;
private int x, y, i;
private ArrayList<Point> pointList;
static int [] xarray = new int [1000];
static int [] yarray = new int [1000];
Random rand = new Random();
//-----------------------------------------------------------------
// Constructor: Sets up this panel to listen for mouse events.
//-----------------------------------------------------------------
public DotsPanel()
{
pointList = new ArrayList<Point>();
int [] xarray = new int [1000];
int [] yarray = new int [1000];
timer = new Timer(delay, new ReboundListener());
addMouseListener (new DotsListener());
addMouseMotionListener (new DotsListener());
setBackground(Color.gray);
setPreferredSize(new Dimension(700, 500));
for(int i = 0; i < xarray.length; i++)
{
xarray[i] = rand.nextInt(7);
yarray[i] = rand.nextInt(7);
}
timer.start();
}
//-----------------------------------------------------------------
// Draws all of the dots stored in the list.
//-----------------------------------------------------------------
public void paintComponent(Graphics page)
{
super.paintComponent(page);
page.setColor(Color.BLUE);
for (Point spot : pointList)
{
page.fillRect(spot.x-SIZE, spot.y-SIZE, 25, 25);
page.drawString("Count: " + pointList.size(), 5, 15);
}
}
//*****************************************************************
// Represents the listener for mouse events.
//*****************************************************************
private class DotsListener implements MouseListener, MouseMotionListener
{
//--------------------------------------------------------------
// Adds the current point to the list of points and redraws
// the panel whenever the mouse button is pressed.
//--------------------------------------------------------------
public void mousePressed(MouseEvent event)
{
pointList.add(event.getPoint());
repaint();
}
public void mouseDragged(MouseEvent event)
{
// initially I had two xarray and yarray in here just like in
// mouseClicked
// but it did not change anything when removed
}
//--------------------------------------------------------------
// Provide empty definitions for unused event methods.
//--------------------------------------------------------------
public void mouseClicked(MouseEvent event)
{
xarray[i] = rand.nextInt(7);
yarray[i] = rand.nextInt(7);
}
public void mouseReleased(MouseEvent event) {}
public void mouseEntered(MouseEvent event) {}
public void mouseExited(MouseEvent event) {}
public void mouseMoved(MouseEvent e) {}
}
private class ReboundListener implements ActionListener
{
//--------------------------------------------------------------
// Updates the position of the image and possibly the direction
// of movement whenever the timer fires an action event.
//--------------------------------------------------------------
public void actionPerformed(ActionEvent event)
{
for (Point spot : pointList)
{
spot.x += xarray[i];
spot.y += yarray[i];
if (spot.x <= 0 || spot.x >= 700)
xarray[i] = xarray[i] * -1;
if (spot.y <= 0 || spot.y >= 500)
yarray[i] = yarray[i] * -1;
repaint();
}
}
}
}
However, I struggle with arrays and I am sure that I am not doing it correctly.
I wouldn't use Arrays.
Instead, have a Ball object manage its own state. Then you can have different color, speed, size etc for each Ball. Then when the Timer fires you just calculate the new position and repaint the Ball.
Here is an example to get you started:
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.util.*;
import javax.swing.*;
import javax.swing.Timer;
public class BallAnimation4
{
private static void createAndShowUI()
{
BallPanel panel = new BallPanel();
JFrame frame = new JFrame("BallAnimation4");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add( panel );
frame.setSize(800, 600);
frame.setLocationRelativeTo( null );
//frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.setVisible( true );
panel.addBalls(5);
panel.startAnimation();
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowUI();
}
});
}
}
class BallPanel extends JPanel implements ActionListener
{
private ArrayList<Ball> balls = new ArrayList<Ball>();
public BallPanel()
{
setLayout( null );
setBackground( Color.BLACK );
}
public void addBalls(int ballCount)
{
Random random = new Random();
for (int i = 0; i < ballCount; i++)
{
Ball ball = new Ball();
ball.setRandomColor(true);
ball.setLocation(random.nextInt(getWidth()), random.nextInt(getHeight()));
ball.setMoveRate(32, 32, 1, 1, true);
// ball.setMoveRate(16, 16, 1, 1, true);
ball.setSize(32, 32);
balls.add( ball );
}
}
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
for (Ball ball: balls)
{
ball.draw(g);
}
}
public void startAnimation()
{
Timer timer = new Timer(75, this);
timer.start();
}
public void actionPerformed(ActionEvent e)
{
move();
repaint();
}
private void move()
{
for (Ball ball : balls)
{
ball.move(this);
}
}
class Ball
{
public Color color = Color.BLACK;
public int x = 0;
public int y = 0;
public int width = 1;
public int height = 1;
private int moveX = 1;
private int moveY = 1;
private int directionX = 1;
private int directionY = 1;
private int xScale = moveX;
private int yScale = moveY;
private boolean randomMove = false;
private boolean randomColor = false;
private Random myRand = null;
public Ball()
{
myRand = new Random();
setRandomColor(randomColor);
}
public void move(JPanel parent)
{
int iRight = parent.getSize().width;
int iBottom = parent.getSize().height;
x += 5 + (xScale * directionX);
y += 5 + (yScale * directionY);
if (x <= 0)
{
x = 0;
directionX *= (-1);
xScale = randomMove ? myRand.nextInt(moveX) : moveX;
if (randomColor) setRandomColor(randomColor);
}
if (x >= iRight - width)
{
x = iRight - width;
directionX *= (-1);
xScale = randomMove ? myRand.nextInt(moveX) : moveX;
if (randomColor) setRandomColor(randomColor);
}
if (y <= 0)
{
y = 0;
directionY *= (-1);
yScale = randomMove ? myRand.nextInt(moveY) : moveY;
if (randomColor) setRandomColor(randomColor);
}
if (y >= iBottom - height)
{
y = iBottom - height;
directionY *= (-1);
yScale = randomMove ? myRand.nextInt(moveY) : moveY;
if (randomColor) setRandomColor(randomColor);
}
}
public void draw(Graphics g)
{
g.setColor(color);
g.fillOval(x, y, width, height);
}
public void setColor(Color c)
{
color = c;
}
public void setLocation(int x, int y)
{
this.x = x;
this.y = y;
}
public void setMoveRate(int xMove, int yMove, int xDir, int yDir, boolean randMove)
{
this.moveX = xMove;
this.moveY = yMove;
directionX = xDir;
directionY = yDir;
randomMove = randMove;
}
public void setRandomColor(boolean randomColor)
{
this.randomColor = randomColor;
switch (myRand.nextInt(3))
{
case 0: color = Color.BLUE;
break;
case 1: color = Color.GREEN;
break;
case 2: color = Color.RED;
break;
default: color = Color.BLACK;
break;
}
}
public void setSize(int width, int height)
{
this.width = width;
this.height = height;
}
}
}
Since your Arrays only contain the Point you want to paint you don't have any information about the speed each point should be moved at. The best you could do is create a random amount each point should be moved each time its location is changed. This would give erratic movement as each time you move a point the distance would be random.
If you want more constant speed then you would need to create a second Array to contain the distance each point should move every time.
This starts to get messy creating a new Array every time you want a new property to be unique for the object you want to paint. That is why the approach to create a custom Object with multiple properties is easier to manage.

How to return Instance Variables for objects in an array

I am new to graphics in java and I am currently working on a game. Essentially, there are rising bubbles, and the user has to pop them by moving the mouse over them.
I have already made the bubbles but now for the collision detection, I need to be able to find the x and coordinates as well as the diameter of the circle. How can I return the instance variables for each bubble (from the Bubbles object array). You can see my code below. If you find coding errors, please let me know.
Game Class:
public class Game extends JPanel{
public static final int WINDOW_WIDTH = 600;
public static final int WINDOW_HEIGHT = 400;
private boolean insideCircle = false;
private static boolean ifPaused = false;
private static JPanel mainPanel;
private static JLabel statusbar;
private static int clicks = 0;
//Creates a Bubbles object Array
Bubbles[] BubblesArray = new Bubbles[5];
public Game() {
//initializes bubble objects
for (int i = 0; i < BubblesArray.length; i++)
BubblesArray[i] = new Bubbles();
}
public void paint(Graphics graphics) {
//makes background white
graphics.setColor(Color.WHITE);
graphics.fillRect(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
//paints square objects to the screen
for (Bubbles aBubblesArray : BubblesArray) {
aBubblesArray.paint(graphics);
}
}
public void update() {
//calls the Square class update method on the square objects
for (Bubbles aBubblesArray : BubblesArray) aBubblesArray.update();
}
public static void main(String[] args) throws InterruptedException {
statusbar = new JLabel("Default");
Game game = new Game();
game.addMouseMotionListener(new MouseAdapter() {
#Override
public void mouseMoved(MouseEvent e) {
statusbar.setText(String.format("Your mouse is at %d, %d", e.getX(), e.getY()));
}
public void mouseExited(MouseEvent e){
ifPaused = true;
}
public void mouseEntered(MouseEvent e){
ifPaused = false;
}
});
JFrame frame = new JFrame();
frame.add(game);
frame.add(statusbar, BorderLayout.SOUTH);
frame.setVisible(true);
frame.setSize(WINDOW_WIDTH, WINDOW_HEIGHT);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("Bubble Burst");
frame.setResizable(false);
frame.setLocationRelativeTo(null);
while (true) {
if (!ifPaused){
game.update();
game.repaint();
Thread.sleep(5);
}
}
}
}
Bubbles Class:
public class Bubbles{
private int circleXLocation;
private int circleSize;
private int circleYLocation = Game.WINDOW_WIDTH + circleSize;
private int fallSpeed = 1;
private int color = (int) (4 * Math.random() + 1);
Random rand = new Random();
private int whereMouseX;
private int whereMouseY;
public int generateRandomXLocation(){
return circleXLocation = (int) (Game.WINDOW_WIDTH * Math.random() - circleSize);
}
public int generateRandomCircleSize(){
return circleSize = (int) (50 * Math.random() + 30);
}
public int generateRandomFallSpeed(){
return fallSpeed = (int) (5 * Math.random() + 1);
}
public void paint(Graphics g){
if (color == 1) g.setColor(new Color(0x87CEEB));
if (color == 2) g.setColor(new Color(0x87CEFF));
if (color == 3) g.setColor(new Color(0x7EC0EE));
if (color == 4) g.setColor(new Color(0x6CA6CD));
g.fillOval (circleXLocation, circleYLocation, circleSize, circleSize);
}
public Bubbles(){
generateRandomXLocation();
generateRandomCircleSize();
generateRandomFallSpeed();
}
public void update(){
if (circleYLocation <= - circleSize){
generateRandomXLocation();
generateRandomFallSpeed();
generateRandomCircleSize();
circleYLocation = Game.WINDOW_HEIGHT + circleSize;
}
if (circleYLocation > - circleSize){
circleYLocation -= fallSpeed;
}
}
public int getX(){
return circleXLocation;
}
public int getY(){
return circleYLocation;
}
public int getCircleSize(){
return circleSize;
}
}
Set your bubbles to include x and y values in it's constructor.
Public Bubble(float x, float y, int circleSize){
// initialize variables here
}
Then check to see if they are colliding with your current mouse location, something like...
if(e.getX() == this.getX() && e.getY() == this.getY()){
// do something
}
Loop through each Bubble in the array and access the public get methods you have created in the Bubble class:
Example:
for (Bubble b : BubblesArray)
{
int x = b.getX();
int y = b.getY();
}

How to refer ChangeListener of one class to another class?

I DISCARD ALL THESE CODE AND WORK ON TOTALLY DIFFERENT ONE>>>
NO NEED TO ANSWER ANYMORE
I got a homework from my professor. He told us to make applet paint program using 4 classes.
Main; LightSourcePanel;DrawingPanel;PalettePanel;
(The basic code are not giving; only the class)
The program will take Mouse input and draw circle when I make a circular line. And the circle will have a 'glowing effect' depend on the lightSource (Use JSlider as light). When the JSlider is slided, the circle glowing effect change real time.
I am having problem referring the LightSource event Listener to the Drawing so It change the 'int light' inside the DrawingPanel. I don't know why the refering in the JColorChooser work while this one don't.
(It gave me java "non-static method cannot be referenced from a static" and I can't change it to static since I need to call repaint() method )
This is my Third class assignment and professor just taught us basic action listener in a single class. So I have no idea what Am I doing. If possible please explain my mistake in detail.
Main code:
public class HW3_to_4 extends Applet {
public void init (){
Dimension d = this.getSize();
setLayout(new BorderLayout());
JPanel Pale = new PalettePanel();
Pale.setBorder(BorderFactory.createLineBorder(Color.black, 5));
JPanel Light = new LightSourcePanel();
Light.setBorder(BorderFactory.createLineBorder(Color.black, 5));
JPanel Draw = new DrawingPanel();
Cursor c = Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR);
Draw.setCursor(c);
Draw.setBorder(BorderFactory.createLineBorder(Color.green, 3));
add(Pale, BorderLayout.SOUTH );
add(Light,BorderLayout.NORTH);
add(Draw,BorderLayout.CENTER);
}
}
PalettePanel Code:
class PalettePanel extends JPanel implements ChangeListener {
JColorChooser j;
public PalettePanel () {
j = new JColorChooser ();
j.setPreviewPanel(new JPanel());
j.getSelectionModel().addChangeListener(this);
this.add(j);
}
public void stateChanged (ChangeEvent e){
Color a = j.getColor();
DrawingPanel.changecolor (a);
}
}
DrawingPanel Code & sub class inside (DrawingCanvas and Polyline)
I rip this off from a example page in YAIP.
:
public class DrawingPanel extends JPanel {
private List<PolyLine> lines = new ArrayList<PolyLine>();
private static PolyLine currentline;
private int maxX,maxY,difX, difY,minX,minY;
private static int lightSource = 0;
public static final int CANVAS_WIDTH = 2000;
public static final int CANVAS_HEIGHT = 800;
public static int[][] circle = new int[1000][4];
public static int check = 0;
public static Color c = Color.RED;
public DrawingPanel(){
DrawingCanvas canvas = new DrawingCanvas();
Dimension d = new Dimension(CANVAS_WIDTH, CANVAS_HEIGHT);
canvas.setPreferredSize(d);
canvas.addMouseListener(new MouseAdapter(){
public void mousePressed(MouseEvent e){
currentline = new PolyLine();
currentline.line_color = c;
lines.add(currentline);
currentline.add(e.getX(), e.getY());
}
});
canvas.addMouseMotionListener(new MouseMotionAdapter(){
public void mouseDragged(MouseEvent e){
currentline.add(e.getX(), e.getY());
repaint();
}
});
canvas.addMouseListener(new MouseAdapter(){
public void mouseReleased(MouseEvent e){
for(int i = 0; i<currentline.xList.size()-1; i++){
if(maxX<currentline.xList.get(i)){
maxX = currentline.xList.get(i);
}
}
for(int i = 0; i<currentline.yList.size()-1; i++){
if(maxY<currentline.yList.get(i)){
maxY = currentline.yList.get(i);
}
}
minX = maxX;
for(int i = 0; i<currentline.xList.size()-1; i++){
if(minX>currentline.xList.get(i)){
minX = currentline.xList.get(i);
}
}
minY = maxY;
for(int i = 0; i<currentline.yList.size()-1; i++){
if(minY>currentline.yList.get(i)){
minY = currentline.yList.get(i);
}
}
difX = maxX - minX;
difY = maxY - minY;
currentline.addcircle(minX,minY, difX, difY);
circle[check][0] = minX;
circle[check][1] = minY;
circle[check][2] = difX;
circle[check][3] = difY;
check++;
repaint();
maxX = 0; difX = 0;
maxY = 0; difY = 0;
}
});
this.add(canvas);
}
public static void changecolor(Color b){
c = b;
}
public void lightChange (int light){
lightSource = light;
RE();
}
public void RE (){
for (int x = 0; x< check ; x++) currentline.addcircle(circle[x][0],circle[x][1], circle[x][2],circle[x][3],lightSource);
repaint();
}
private class DrawingCanvas extends JPanel{
public void paint(Graphics g){
for(PolyLine line : lines){
g.setColor(line.line_color);
line.draw(g);
}
}
}
static class PolyLine{
public Color line_color = Color.RED;
private List <Integer> xList;
private List <Integer> yList;
boolean drawcircle = false;
int minx, miny, difx, dify, light;
public PolyLine() {
xList = new ArrayList<Integer>();
yList = new ArrayList<Integer>();
}
public void add(int x, int y){
xList.add(x);
yList.add(y);
}
public void addcircle(int x, int y, int difx, int dify){
this.minx = x; this.miny = y; this.difx = difx; this.dify = dify;
drawcircle = true;
}
public void addcircle(int x, int y, int difx, int dify, int light){
this.minx = x; this.miny = y; this.difx = difx; this.dify = dify; this.light = light;
drawcircle = true;
}
public void draw(Graphics g){
if(drawcircle){
g.fillOval(minx, miny, difx, dify);
g.setColor(Color.WHITE);
g.fillOval((minx+difx/4)+light, miny+dify/4, difx/4, dify/4);
g.setColor(line_color);
}else{
for(int i = 0; i<xList.size()-1; i++){
g.drawLine((int)xList.get(i), (int)yList.get(i), (int)xList.get(i + 1),
(int)yList.get(i + 1));
}
}
}}}
>
Here is the problem.
LightSourcePanel Code:
class LightSourcePanel extends JPanel implements ChangeListener {
static JSlider j;
public LightSourcePanel (){
j = new JSlider(0,180,90);
j.setMajorTickSpacing(45);
j.setMinorTickSpacing(5);
j.setPaintLabels(true);
j.setPaintTicks (true);
j.setPreferredSize(new Dimension (1500,50));
j.addChangeListener(this);
this.add(j);
}
#Override
public void stateChanged(ChangeEvent e) {
// TODO Auto-generated method stub
lightChange(j.getValue()); // problem <<<<<< FAIL
}}
First off, change the changecolor(Color) method in DrawingPanel to remove the static keyword. Then you need an instance of DrawingColor to use the class. I would store the instance of it in a field just like JColorChooser is stored.

Something seems wrong with the layout, JButton showing unexpected behaviour at resize of the window

JRE Version 1.7 Update 3
EXPECTED BEHAVIOUR
As I run the program, it works as expected, everything works smoothly. As when I click on STOP JButton the animation stops and the text on the same JButton changes to START. Now when i click on BALL COLOUR JButton, the colour of the BALL changes, as well as the colour of the BALL COLOUR JBUTTON, also changes, to that of the BALL. This whole behaviour works if I run my application as is without resizing.
UNEXPECTED BEHAVIOUR
But when i RESIZE my JFrame, by pulling the Right Side, that's when unexpected behaviour of my Application is shown, in the sense that if I press STOP JButton and then click on BALL COLOUR button, the text on the JButton clicked earlier whose text changed to START will change to STOP again when it should not be, as well as the colour of the BALL COLOUR JButton will remain unchanged or will turn to BLUE, when it should be changed to the colour of the ball. I am attaching the pics for more info. But if you will try to resize it back to it's original size or closer to that, then things will come back to normal. Why is this happening ? Any idea or clue will be much appreciated.
As My Application Runs with EXPECTED BEHAVIOUR as described above :
And here the UNEXPECTED BEHAVIOUR
BOTTOM-LINE :
Why the Application runs as usual as it should be, at the BEGINNING , but not when RESIZED by dragging it's RIGHT SIDE, but again if you bring it to it's original size or closer to it, things come back to normal, it works as expected ?
So considering the scenario, am I doing something wrong, in the program. Or is this exactly the situation, where I should be using the SwingWorker, Or Is this an issue with the Layout, or something hidden related to Content Pane. Please do put some light :-)
here is the code I am using, I had brought it down to the minimum, as I think to demonstrate my problem :
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class BallAnimation
{
private int x;
private int y;
private boolean positiveX;
private boolean positiveY;
private boolean isTimerRunning;
private int speedValue;
private int diameter;
private DrawingArea drawingArea;
private Timer timer;
private int colourCounter;
Color[] colours = {
Color.BLUE.darker(),
Color.MAGENTA.darker(),
Color.BLACK.darker(),
Color.RED.darker(),
Color.PINK.darker(),
Color.CYAN.darker(),
Color.DARK_GRAY.darker(),
Color.YELLOW.darker(),
Color.GREEN.darker()
};
private Color backgroundColour;
private Color foregroundColour;
private ActionListener timerAction = new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
x = getX();
y = getY();
drawingArea.setXYColourValues(x, y, backgroundColour
, foregroundColour);
}
};
private JPanel buttonPanel;
private JButton startStopButton;
private JButton speedIncButton;
private JButton speedDecButton;
private JButton resetButton;
private JButton colourButton;
private JButton exitButton;
private ComponentAdapter componentAdapter = new ComponentAdapter()
{
public void componentResized(ComponentEvent ce)
{
timer.restart();
startStopButton.setText("STOP");
isTimerRunning = true;
}
};
public BallAnimation()
{
x = y = 0;
positiveX = positiveY = true;
speedValue = 1;
colourCounter = 0;
isTimerRunning = false;
diameter = 50;
backgroundColour = Color.WHITE.brighter();
foregroundColour = colours[colourCounter];
timer = new Timer(10, timerAction);
}
private void createAndDisplayGUI()
{
JFrame frame = new JFrame("Ball Animation");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationByPlatform(true);
drawingArea = new DrawingArea(x, y
, backgroundColour, foregroundColour, diameter);
drawingArea.addComponentListener(componentAdapter);
frame.add(makeButtonPanel(), BorderLayout.LINE_END);
frame.add(drawingArea, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
private JPanel makeButtonPanel()
{
buttonPanel = new JPanel();
buttonPanel.setLayout(new GridLayout(0, 1));
buttonPanel.setBorder(BorderFactory.createLineBorder(
Color.DARK_GRAY, 5, true));
startStopButton = new JButton("START");
startStopButton.setBackground(Color.GREEN.darker());
startStopButton.setForeground(Color.WHITE.brighter());
startStopButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
System.out.println("START/STOP JButton Clicked!");
if (!isTimerRunning)
{
startStopButton.setText("STOP");
timer.start();
isTimerRunning = true;
buttonPanel.revalidate();
buttonPanel.repaint();
}
else if (isTimerRunning)
{
startStopButton.setText("START");
timer.stop();
isTimerRunning = false;
buttonPanel.revalidate();
buttonPanel.repaint();
}
}
});
startStopButton.setBorder(BorderFactory.createLineBorder(
Color.WHITE, 4, true));
buttonPanel.add(startStopButton);
colourButton = new JButton("BALL COLOUR");
colourButton.setBackground(colours[colourCounter]);
colourButton.setForeground(Color.WHITE);
colourButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
System.out.println("COLOUR JButton Clicked!");
//timer.restart();
colourCounter++;
if (colourCounter == 9)
colourCounter = 0;
foregroundColour = colours[colourCounter];
drawingArea.setXYColourValues(x, y, backgroundColour
, foregroundColour);
//drawingArea.setForegroundForBall(foregroundColour);
colourButton.setBackground(foregroundColour);
colourButton.revalidate();
colourButton.repaint();
//timer.start();
}
});
colourButton.setBorder(BorderFactory.createLineBorder(
Color.WHITE, 2, true));
buttonPanel.add(colourButton);
exitButton = new JButton("EXIT");
exitButton.setBackground(Color.RED.darker());
exitButton.setForeground(Color.WHITE.brighter());
exitButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
System.out.println("EXIT JButton Clicked!");
timer.stop();
System.exit(0);
}
});
exitButton.setBorder(BorderFactory.createLineBorder(
Color.RED.darker().darker(), 4, true));
buttonPanel.add(exitButton);
return buttonPanel;
}
private int getX()
{
if (x < 0)
positiveX = true;
else if (x >= drawingArea.getWidth() - diameter)
positiveX = false;
return (calculateX());
}
private int calculateX()
{
if (positiveX)
return (x += speedValue);
else
return (x -= speedValue);
}
private int getY()
{
if (y < 0)
positiveY = true;
else if (y >= drawingArea.getHeight() - diameter)
positiveY = false;
return (calculateY());
}
private int calculateY()
{
if (positiveY)
return (y += speedValue);
else
return (y -= speedValue);
}
public static void main(String... args)
{
Runnable runnable = new Runnable()
{
public void run()
{
new BallAnimation().createAndDisplayGUI();
}
};
SwingUtilities.invokeLater(runnable);
}
}
class DrawingArea extends JComponent
{
private int x;
private int y;
private int ballDiameter;
private Color backgroundColor;
private Color foregroundColor;
public DrawingArea(int x, int y
, Color bColor, Color fColor, int dia)
{
this.x = x;
this.y = y;
ballDiameter = dia;
backgroundColor = bColor;
foregroundColor = fColor;
setBorder(BorderFactory.createLineBorder(
Color.DARK_GRAY.darker(), 5, true));
}
public void setXYColourValues(int x, int y
, Color bColor, Color fColor)
{
this.x = x;
this.y = y;
backgroundColor = bColor;
foregroundColor = fColor;
repaint();
}
public Dimension getPreferredSize()
{
return (new Dimension(500, 400));
}
public void paintComponent(Graphics g)
{
g.setColor(backgroundColor);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(foregroundColor);
g.fillOval(x, y, ballDiameter, ballDiameter);
}
}
**LATEST EDIT : **
The problem with your very nice example may be platform dependent, but I can offer a few observations:
You're not adding or removing components, so you don't need revalidate().
Because the background color is a bound property of the buttons, you don't need the subsequent calls to repaint().
You do need repaint() in your custom DrawingArea, but you may want to experiment with adding property change support, as suggested here.
Color.white can't be brighter() and Color.black can't be darker(); Color.darkGray.darker() is Color.black().
The variation below uses a Queue<Color> to simplify changing colors.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
/** #see https://stackoverflow.com/q/9849950/230513 */
public class BallAnimation {
private int x;
private int y;
private boolean positiveX;
private boolean positiveY;
private boolean isTimerRunning;
private int speedValue;
private int diameter;
private DrawingArea drawingArea;
private Timer timer;
private Queue<Color> clut = new LinkedList<Color>(Arrays.asList(
Color.BLUE.darker(),
Color.MAGENTA.darker(),
Color.BLACK,
Color.RED.darker(),
Color.PINK,
Color.CYAN.darker(),
Color.DARK_GRAY,
Color.YELLOW.darker(),
Color.GREEN.darker()));
private Color backgroundColour;
private Color foregroundColour;
private ActionListener timerAction = new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
x = getX();
y = getY();
drawingArea.setXYColourValues(x, y, backgroundColour, foregroundColour);
}
};
private JPanel buttonPanel;
private JButton startStopButton;
private JButton speedIncButton;
private JButton speedDecButton;
private JButton resetButton;
private JButton colourButton;
private JButton exitButton;
private ComponentAdapter componentAdapter = new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent ce) {
timer.restart();
startStopButton.setText("Stop");
isTimerRunning = true;
}
};
public BallAnimation() {
x = y = 0;
positiveX = positiveY = true;
speedValue = 1;
isTimerRunning = false;
diameter = 50;
backgroundColour = Color.white;
foregroundColour = clut.peek();
timer = new Timer(10, timerAction);
}
private void createAndDisplayGUI() {
JFrame frame = new JFrame("Ball Animation");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationByPlatform(true);
drawingArea = new DrawingArea(x, y, backgroundColour, foregroundColour, diameter);
drawingArea.addComponentListener(componentAdapter);
frame.add(makeButtonPanel(), BorderLayout.LINE_END);
frame.add(drawingArea, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
private JPanel makeButtonPanel() {
buttonPanel = new JPanel(new GridLayout(0, 1));
buttonPanel.setBorder(BorderFactory.createLineBorder(Color.darkGray, 5));
startStopButton = new JButton("Start");
startStopButton.setOpaque(true);
startStopButton.setForeground(Color.white);
startStopButton.setBackground(Color.green.darker());
startStopButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
if (!isTimerRunning) {
startStopButton.setText("Stop");
timer.start();
isTimerRunning = true;
} else if (isTimerRunning) {
startStopButton.setText("Start");
timer.stop();
isTimerRunning = false;
}
}
});
startStopButton.setBorder(BorderFactory.createLineBorder(Color.gray, 4));
buttonPanel.add(startStopButton);
colourButton = new JButton("Change Color");
colourButton.setOpaque(true);
colourButton.setForeground(Color.white);
colourButton.setBackground(clut.peek());
colourButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
//timer.restart();
clut.add(clut.remove());
foregroundColour = clut.peek();
drawingArea.setXYColourValues(x, y, backgroundColour, foregroundColour);
colourButton.setBackground(foregroundColour);
}
});
colourButton.setBorder(BorderFactory.createLineBorder(Color.gray, 4));
buttonPanel.add(colourButton);
exitButton = new JButton("Exit");
exitButton.setBackground(Color.red);
exitButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
timer.stop();
System.exit(0);
}
});
exitButton.setBorder(BorderFactory.createLineBorder(Color.red.darker(), 4));
buttonPanel.add(exitButton);
return buttonPanel;
}
private int getX() {
if (x < 0) {
positiveX = true;
} else if (x >= drawingArea.getWidth() - diameter) {
positiveX = false;
}
return (calculateX());
}
private int calculateX() {
if (positiveX) {
return (x += speedValue);
} else {
return (x -= speedValue);
}
}
private int getY() {
if (y < 0) {
positiveY = true;
} else if (y >= drawingArea.getHeight() - diameter) {
positiveY = false;
}
return (calculateY());
}
private int calculateY() {
if (positiveY) {
return (y += speedValue);
} else {
return (y -= speedValue);
}
}
public static void main(String... args) {
Runnable runnable = new Runnable() {
#Override
public void run() {
new BallAnimation().createAndDisplayGUI();
}
};
SwingUtilities.invokeLater(runnable);
}
}
class DrawingArea extends JComponent {
private int x;
private int y;
private int ballDiameter;
private Color backgroundColor;
private Color foregroundColor;
public DrawingArea(int x, int y, Color bColor, Color fColor, int dia) {
this.x = x;
this.y = y;
ballDiameter = dia;
backgroundColor = bColor;
foregroundColor = fColor;
setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY, 5));
}
public void setXYColourValues(int x, int y, Color bColor, Color fColor) {
this.x = x;
this.y = y;
backgroundColor = bColor;
foregroundColor = fColor;
repaint();
}
#Override
public Dimension getPreferredSize() {
return (new Dimension(500, 400));
}
#Override
public void paintComponent(Graphics g) {
g.setColor(backgroundColor);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(foregroundColor);
g.fillOval(x, y, ballDiameter, ballDiameter);
}
}
Seems like there is something wrong with BorderLayout.LINE_END thingy, only when I place the buttonPanel on LINE_END, I am getting undesirable results. I had tried to use only one JButton, instead of three as the latest measure, to sort out thingies. Now the problem that use to come as shown in this pic :
has been sorted out by changing the position of the JButton Panel to LINE_START or using JRE version 1.6 update 31, in the pic as below :
Here is the code used for this example :
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class BallAnimation
{
private int x;
private int y;
private boolean positiveX;
private boolean positiveY;
private boolean isTimerRunning;
private int speedValue;
private int diameter;
private DrawingArea drawingArea;
private Timer timer;
private int colourCounter;
Color[] colours = {
Color.BLUE.darker(),
Color.MAGENTA.darker(),
Color.BLACK.darker(),
Color.RED.darker(),
Color.PINK.darker(),
Color.CYAN.darker(),
Color.DARK_GRAY.darker(),
Color.YELLOW.darker(),
Color.GREEN.darker()
};
private Color backgroundColour;
private Color foregroundColour;
private ActionListener timerAction = new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
x = getX();
y = getY();
drawingArea.setXYColourValues(x, y, backgroundColour
, foregroundColour);
}
};
private JPanel buttonPanel;
private JButton startStopButton;
private JButton speedIncButton;
private JButton speedDecButton;
private JButton resetButton;
private JButton colourButton;
private JButton exitButton;
private ComponentAdapter componentAdapter = new ComponentAdapter()
{
public void componentResized(ComponentEvent ce)
{
timer.restart();
}
};
public BallAnimation()
{
x = y = 0;
positiveX = positiveY = true;
speedValue = 1;
colourCounter = 0;
isTimerRunning = false;
diameter = 50;
backgroundColour = Color.WHITE.brighter();
foregroundColour = colours[colourCounter];
timer = new Timer(10, timerAction);
}
private void createAndDisplayGUI()
{
JFrame frame = new JFrame("Ball Animation");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationByPlatform(true);
drawingArea = new DrawingArea(x, y
, backgroundColour, foregroundColour, diameter);
drawingArea.addComponentListener(componentAdapter);
frame.add(makeButtonPanel(), BorderLayout.LINE_START);
frame.add(drawingArea, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
private JPanel makeButtonPanel()
{
buttonPanel = new JPanel();
buttonPanel.setLayout(new GridLayout(0, 1));
buttonPanel.setBorder(BorderFactory.createLineBorder(
Color.DARK_GRAY, 5, true));
colourButton = new JButton("BALL COLOUR");
colourButton.setOpaque(true);
colourButton.setBackground(colours[colourCounter]);
colourButton.setForeground(Color.WHITE);
colourButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
System.out.println("COLOUR JButton Clicked!");
if (timer.isRunning())
timer.stop();
colourCounter++;
if (colourCounter == 9)
colourCounter = 0;
foregroundColour = colours[colourCounter];
drawingArea.setXYColourValues(x, y, backgroundColour
, foregroundColour);
colourButton.setBackground(foregroundColour);
if (!timer.isRunning())
timer.start();
}
});
colourButton.setBorder(BorderFactory.createLineBorder(
Color.WHITE, 2, true));
buttonPanel.add(colourButton);
return buttonPanel;
}
private int getX()
{
if (x < 0)
positiveX = true;
else if (x >= drawingArea.getWidth() - diameter)
positiveX = false;
return (calculateX());
}
private int calculateX()
{
if (positiveX)
return (x += speedValue);
else
return (x -= speedValue);
}
private int getY()
{
if (y < 0)
positiveY = true;
else if (y >= drawingArea.getHeight() - diameter)
positiveY = false;
return (calculateY());
}
private int calculateY()
{
if (positiveY)
return (y += speedValue);
else
return (y -= speedValue);
}
public static void main(String... args)
{
Runnable runnable = new Runnable()
{
public void run()
{
new BallAnimation().createAndDisplayGUI();
}
};
SwingUtilities.invokeLater(runnable);
}
}
class DrawingArea extends JComponent
{
private int x;
private int y;
private int ballDiameter;
private Color backgroundColor;
private Color foregroundColor;
public DrawingArea(int x, int y
, Color bColor, Color fColor, int dia)
{
this.x = x;
this.y = y;
ballDiameter = dia;
backgroundColor = bColor;
foregroundColor = fColor;
setBorder(BorderFactory.createLineBorder(
Color.DARK_GRAY.darker(), 5, true));
}
public void setXYColourValues(int x, int y
, Color bColor, Color fColor)
{
this.x = x;
this.y = y;
backgroundColor = bColor;
foregroundColor = fColor;
repaint();
}
public Dimension getPreferredSize()
{
return (new Dimension(500, 400));
}
public void paintComponent(Graphics g)
{
g.setColor(backgroundColor);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(foregroundColor);
g.fillOval(x, y, ballDiameter, ballDiameter);
}
}
maybe will help you with two parts of, I think that Graphics/2D is designated to use Swing Timer exclusively,
I am unsure whether I found a solution for your system, but adjusting the code to
colourButton = new JButton( "BALL COLOUR" );
colourButton.setOpaque( true );
colourButton.setBackground( colours[ colourCounter ] );
colourButton.setForeground( Color.WHITE );
works on my system (OS X with Java 1.7). Note the setOpaque call, which is needed so that the setBackground call has any effect as stated in the javadoc of that method:
Sets the background color of this component. The background color is used only if the component is opaque
On OS X, without that setOpaque call your code does not even work before a resize

Categories