Related
I'm trying to develop a game, it's one of my assignments. In this game, I have several ball draw using pain and I have 3 panels. One plays the role of paddle and 2 others play the roles of obstacles. So I have an issue when trying to detect the collision between the balls and the panel (paddle and obstacle), and another issue is when the collision occurs the ball must move in a different position like the reflection of light on an object.
Find down my code:
import java.awt.Color;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;
import java.util.Vector;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class BallWindow extends JFrame implements ActionListener{
JButton btnStop = new JButton("STOP");
JButton btnSave = new JButton("SAVE");
Vector<BallP> ballVector = new Vector<BallP>();
JPanel p1 = createPanel(280, 200, 200, 20, Color.gray);
JPanel p2 = createPanel(280, 300, 200, 20, Color.gray);
JPanel lborder = createPanel(10, 10, 2, 560, Color.black);
JPanel rborder = createPanel(720, 10, 2, 560, Color.black);
JPanel tborder = createPanel(10, 10, 710, 2, Color.black);
//Movement
private static final int Y = 500;
private static final int WIDTH = 60;
private static final int HEIGHT = 10;
int x = 10;
int xa = 0;
JPanel bottomp = createPanel(x, Y, WIDTH, HEIGHT, Color.black);
public BallWindow() {
addKeyListener(new KeyListener()
{
#Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
if (e.getKeyCode() == KeyEvent.VK_LEFT)
bottomp.setLocation(bottomp.getLocation().x -6, bottomp.getLocation().y);
if (e.getKeyCode() == KeyEvent.VK_RIGHT)
bottomp.setLocation(bottomp.getLocation().x + 6, bottomp.getLocation().y);
}
#Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
});
setFocusable(true);
setLayout(null);
btnStop.setBounds(12, 15, 100, 30);
btnStop.addActionListener(this);
add(btnStop);
btnSave.setBounds(12, 50, 100, 30);
//btnSave.addActionListener(this);
add(btnSave);
Random r = new Random();
for(int i=0; i<5; i++){
BallP bp = new BallP(r.nextInt(740), r.nextInt(590));
Thread t = new Thread(bp);
ballVector.add(bp);
t.start();
add(bp);
}
add(p1);
add(p2);
Rectangle b = bottomp.getBounds();
add(bottomp);
// add(lborder);
// add(rborder);
// add(tborder);
setSize(740, 570);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
repaint();
}
JPanel createPanel(int x, int y, int width, int height, Color pColor){
JPanel temp = new JPanel();
temp.setBackground(pColor);
temp.setBounds(x, y, width, height);
return temp;
}
public static void main(String[] args) {
new BallWindow();
}
#Override
public void actionPerformed(ActionEvent arg0) {
for (BallP ball : ballVector) {
ball.pleaseWait = !ball.pleaseWait;
}
if( btnStop.getText().equalsIgnoreCase("STOP"))
btnStop.setText("START");
else
btnStop.setText("STOP");
// if(arg0.getSource())
}
}
Here is the code for the ball
import java.awt.Color;
import java.awt.Graphics;
import java.util.Random;
import javax.swing.JPanel;
public class BallP extends JPanel implements Runnable {
int RED, GREEN, BLUE;
int Xdirection = 1, Ydirection = 1;
boolean pleaseWait = false;
BallP(int X, int Y){
locateBall(X, Y, 30, 30);
/* Random r = new Random();
RED = r.nextInt(255);
GREEN = r.nextInt(255);
BLUE = r.nextInt(255);
*/
}
public void paint(Graphics g){
int panelWidth = this.getWidth();
int panelHeight = this.getHeight();
// g.setColor( new Color(RED, GREEN, BLUE ));
g.setColor(Color.ORANGE);
g.fillOval(panelWidth/2, panelHeight/2,panelWidth/2, panelHeight/2);
}
public void locateBall(int x, int y, int width, int height){
setBounds(x, y, width, height);
repaint();
}
public void run() {
int width = this.getWidth();
int height = this.getHeight();
Random r = new Random();
while(true){
if(!pleaseWait){
int lastX = this.getX();
int lastY = this.getY();
if (lastX > 675) Xdirection = -1;
if (lastY > 485) Ydirection = -1;
if (lastX < -5) Xdirection = 1;
if (lastY < -5) Ydirection = 1;
/* if(lastX > 280 && lastY > 170){
Xdirection = -1;
Ydirection = -1;
}
*/
locateBall(lastX + Xdirection*r.nextInt(3),
lastY + Ydirection*r.nextInt(3),
width, height );
}
try{
Thread.sleep(5);
}catch(Exception e){};
}
}
}
I'm trying to make a JLabel move across other JLabels, only 1 timer works right now. It is supposed to operate like a train moving across a track, going all the way around the track and ending up right back where it started from. I'm not sure how to make it go all the way around, any help is appreciated.
Thank you.
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.JTextField;
import java.awt.Color;
import javax.swing.JSlider;
import javax.swing.SwingConstants;
import javax.swing.border.BevelBorder;
public class MoveLabel {
private JTextField textField;
private JTextField tf;
private JTextField textField_1;
private JTextField textField_2;
private JTextField textField_3;
private JTextField textField_5;
private JTextField textField_6;
private JTextField textField_7;
private JTextField textField_8;
private JTextField textField_9;
private JTextField textField_10;
private JTextField textField_11;
private JTextField textField_12;
private JTextField textField_13;
private JTextField textField_14;
private JTextField textField_15;
private JTextField textField_16;
private JTextField textField_17;
private JTextField textField_18;
private JTextField textField_19;
private JTextField textField_20;
private JTextField textField_21;
private JTextField textField_22;
private JTextField textField_23;
private JTextField textField_24;
private JTextField textField_25;
private JTextField textField_26;
private JSlider slider;
private JSlider slider_1;
private JSlider slider_2;
public static void main(String[] args) {
new MoveLabel();
}
public MoveLabel() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(new BorderLayout());
TestPane testPane = new TestPane();
testPane.setBackground(Color.WHITE);
frame.getContentPane().add(testPane);
textField = new JTextField();
textField.setBounds(100, 138, 20, 20);
testPane.add(textField);
textField.setColumns(10);
textField_1 = new JTextField();
textField_1.setColumns(10);
textField_1.setBounds(80, 44, 20, 20);
testPane.add(textField_1);
textField_2 = new JTextField();
textField_2.setColumns(10);
textField_2.setBounds(120, 44, 20, 20);
testPane.add(textField_2);
textField_3 = new JTextField();
textField_3.setColumns(10);
textField_3.setBounds(160, 44, 20, 20);
testPane.add(textField_3);
textField_5 = new JTextField();
textField_5.setColumns(10);
textField_5.setBounds(140, 138, 20, 20);
testPane.add(textField_5);
textField_6 = new JTextField();
textField_6.setColumns(10);
textField_6.setBounds(160, 138, 20, 20);
testPane.add(textField_6);
textField_7 = new JTextField();
textField_7.setColumns(10);
textField_7.setBounds(120, 138, 20, 20);
testPane.add(textField_7);
textField_8 = new JTextField();
textField_8.setColumns(10);
textField_8.setBounds(80, 59, 20, 20);
testPane.add(textField_8);
textField_9 = new JTextField();
textField_9.setColumns(10);
textField_9.setBounds(80, 75, 20, 20);
testPane.add(textField_9);
textField_10 = new JTextField();
textField_10.setColumns(10);
textField_10.setBounds(80, 90, 20, 20);
testPane.add(textField_10);
textField_11 = new JTextField();
textField_11.setColumns(10);
textField_11.setBounds(80, 106, 20, 20);
testPane.add(textField_11);
textField_12 = new JTextField();
textField_12.setColumns(10);
textField_12.setBounds(80, 123, 20, 20);
testPane.add(textField_12);
textField_13 = new JTextField();
textField_13.setColumns(10);
textField_13.setBounds(179, 44, 20, 20);
testPane.add(textField_13);
textField_14 = new JTextField();
textField_14.setColumns(10);
textField_14.setBounds(199, 44, 20, 20);
testPane.add(textField_14);
textField_15 = new JTextField();
textField_15.setColumns(10);
textField_15.setBounds(80, 138, 20, 20);
testPane.add(textField_15);
textField_16 = new JTextField();
textField_16.setColumns(10);
textField_16.setBounds(100, 44, 20, 20);
testPane.add(textField_16);
textField_17 = new JTextField();
textField_17.setColumns(10);
textField_17.setBounds(140, 44, 20, 20);
testPane.add(textField_17);
textField_18 = new JTextField();
textField_18.setColumns(10);
textField_18.setBounds(179, 138, 20, 20);
testPane.add(textField_18);
textField_19 = new JTextField();
textField_19.setColumns(10);
textField_19.setBounds(199, 138, 20, 20);
testPane.add(textField_19);
textField_20 = new JTextField();
textField_20.setColumns(10);
textField_20.setBounds(219, 63, 20, 20);
testPane.add(textField_20);
textField_21 = new JTextField();
textField_21.setColumns(10);
textField_21.setBounds(219, 138, 20, 20);
testPane.add(textField_21);
textField_22 = new JTextField();
textField_22.setBackground(Color.WHITE);
textField_22.setColumns(10);
textField_22.setBounds(219, 44, 20, 20);
testPane.add(textField_22);
textField_23 = new JTextField();
textField_23.setColumns(10);
textField_23.setBounds(219, 123, 20, 20);
testPane.add(textField_23);
textField_24 = new JTextField();
textField_24.setColumns(10);
textField_24.setBounds(219, 99, 20, 27);
testPane.add(textField_24);
textField_25 = new JTextField();
textField_25.setColumns(10);
textField_25.setBounds(219, 83, 20, 20);
testPane.add(textField_25);
textField_26 = new JTextField();
textField_26.setColumns(10);
textField_26.setBounds(219, 90, 20, 20);
testPane.add(textField_26);
slider_2 = new JSlider();
slider_2.setMaximum(3);
slider_2.setPaintTicks(true);
slider_2.setSnapToTicks(true);
slider_2.setOrientation(SwingConstants.VERTICAL);
slider_2.setBounds(533, 260, 57, 229);
testPane.add(slider_2);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public static class TestPane extends JPanel {
protected static final int PLAY_TIME = 4000;
private JLabel label;
private JTextField tf;
private int targetX;
private int targetY;
private int targetX2;
private int targetY2;
private long startTime;
private long startTime2;
private final int startX;
private final int startY;
private final int startX2;
private final int startY2;
public TestPane() {
setLayout(null);
tf = new JTextField("");
tf.setSize(20,20);
tf.setBackground(Color.red);
add(tf);
Dimension size = getPreferredSize();
startX = 80;
startY = 44;
/* targetX = (size.width - label.getSize().width) / 2;
targetY = (size.height - label.getSize().height) / 2;
*/
targetX = 140;
targetY = 44;
Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
int x = tf.getX();
int y = tf.getY();
long duration = System.currentTimeMillis() - startTime;
float progress = (float)duration / (float)PLAY_TIME;
if (progress > 1f) {
progress = 1f;
((Timer)(e.getSource())).stop();
}
x = startX + (int)Math.round((targetX - startX) * progress);
y = startY + (int)Math.round((targetY - startY) * progress);
tf.setLocation(x, y);
}
});
startTime = System.currentTimeMillis();
timer.start();
/* try {
Thread.sleep(10);
}
catch (InterruptedException ie) {
ie.printStackTrace();
}
if (timer.isRunning() != true)
{
timer.stop();
}*/
startX2 = targetX;
startY2 = targetY;
tf.setLocation(startX,startY);
/* targetX = (size.width - label.getSize().width) / 2;
targetY = (size.height - label.getSize().height) / 2;
*/
targetX2 = 219;
targetY2 = 44;
Timer timer2 = new Timer(40, new ActionListener() {
public void actionPerformed(ActionEvent e) {
int x2 = tf.getX();
int y2 = tf.getY();
long duration = System.currentTimeMillis() - startTime2;
float progress = (float)duration / (float)PLAY_TIME;
if (progress > 1f)
{
progress = 1f;
((Timer)(e.getSource())).stop();
}
x2 = startX2 + (int)Math.round((targetX2 - startX2) * progress);
y2 = startY2 + (int)Math.round((targetY2 - startY2) * progress);
tf.setLocation(x2, y2);
tf.getLocation();
}
});
startTime2 = System.currentTimeMillis();
if (timer.isRunning() == false)
{
//
timer2.start();
}
else
{
timer2.setDelay(10);
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(600, 500);
}
}
}
nb: I don't like null layouts, I don't condone null layouts, I would prefer to have used custom painting, but that's a lot of work not related to the question. This example is intended to focus on the implementation of a Timeline and KeyFrame animation
Because you have to move the object through both the x/y positions, but in different directions over the same time period, this becomes a very complex problem...
You could try and set up four, chained Timers, which trigger the next Timer when they complete, and which all do a different part of the animation...but frankly, that becomes a mess real quick...
A better idea is to use a concept of a time line and key frames. The idea is, that over the time line (0-1), certain events occur at prescribed times (key frames). The time line will then blend between these key frames...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class MoveLabel {
public static void main(String[] args) {
new MoveLabel();
}
public MoveLabel() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(new BorderLayout());
TestPane testPane = new TestPane();
testPane.setBackground(Color.WHITE);
frame.getContentPane().add(testPane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public static class TestPane extends JPanel {
private JTextField tf;
private List<JTextField> tracks;
protected static final int PLAY_TIME = 4000;
private Timeline timeline;
private long startTime;
public TestPane() {
setLayout(null);
tracks = new ArrayList<JTextField>(20);
int x = 20;
int y = 20;
for (int index = 0; index < 6; index++) {
x += 20;
tracks.add(createTrack(x, y, 20, 20));
}
for (int index = 0; index < 6; index++) {
y += 20;
tracks.add(createTrack(x, y, 20, 20));
}
for (int index = 0; index < 6; index++) {
x -= 20;
tracks.add(createTrack(x, y, 20, 20));
}
for (int index = 0; index < 6; index++) {
y -= 20;
tracks.add(createTrack(x, y, 20, 20));
}
for (JTextField track : tracks) {
add(track);
}
tf = new JTextField("");
tf.setSize(20, 20);
tf.setBackground(Color.red);
add(tf);
setComponentZOrder(tf, 0);
timeline = new Timeline();
timeline.add(0, new Point(20, 20));
timeline.add(0.25f, new Point(20 * 7, 20));
timeline.add(0.5f, new Point(20 * 7, 20 * 7));
timeline.add(0.75f, new Point(20, 20 * 7));
timeline.add(1f, new Point(20, 20));
Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
long duration = System.currentTimeMillis() - startTime;
float progress = (float) duration / (float) PLAY_TIME;
if (progress > 1f) {
startTime = System.currentTimeMillis();
progress = 0;
// ((Timer) (e.getSource())).stop();
}
Point p = timeline.getPointAt(progress);
tf.setLocation(p);
}
});
startTime = System.currentTimeMillis();
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(600, 500);
}
protected JTextField createTrack(int x, int y, int width, int height) {
JTextField field = new JTextField();
field.setBounds(x, y, width, height);
field.setEditable(false);
field.setFocusable(false);
return field;
}
}
public static class Timeline {
private Map<Float, KeyFrame> mapEvents;
public Timeline() {
mapEvents = new TreeMap<>();
}
public void add(float progress, Point p) {
mapEvents.put(progress, new KeyFrame(progress, p));
}
public Point getPointAt(float progress) {
if (progress < 0) {
progress = 0;
} else if (progress > 1) {
progress = 1;
}
KeyFrame[] keyFrames = getKeyFramesBetween(progress);
float max = keyFrames[1].progress - keyFrames[0].progress;
float value = progress - keyFrames[0].progress;
float weight = value / max;
return blend(keyFrames[0].getPoint(), keyFrames[1].getPoint(), 1f - weight);
}
public KeyFrame[] getKeyFramesBetween(float progress) {
KeyFrame[] frames = new KeyFrame[2];
int startAt = 0;
Float[] keyFrames = mapEvents.keySet().toArray(new Float[mapEvents.size()]);
while (startAt < keyFrames.length && keyFrames[startAt] <= progress) {
startAt++;
}
if (startAt >= keyFrames.length) {
startAt = keyFrames.length - 1;
}
frames[0] = mapEvents.get(keyFrames[startAt - 1]);
frames[1] = mapEvents.get(keyFrames[startAt]);
return frames;
}
protected Point blend(Point start, Point end, float ratio) {
Point blend = new Point();
float ir = (float) 1.0 - ratio;
blend.x = (int)(start.x * ratio + end.x * ir);
blend.y = (int)(start.y * ratio + end.y * ir);
return blend;
}
public class KeyFrame {
private float progress;
private Point point;
public KeyFrame(float progress, Point point) {
this.progress = progress;
this.point = point;
}
public float getProgress() {
return progress;
}
public Point getPoint() {
return point;
}
}
}
}
You could then do silly things like vary the speed between sections...
timeline = new Timeline();
timeline.add(0, new Point(20, 20));
timeline.add(0.1f, new Point(20 * 7, 20));
timeline.add(0.5f, new Point(20 * 7, 20 * 7));
timeline.add(0.6f, new Point(20, 20 * 7));
timeline.add(1f, new Point(20, 20));
I was given this homework assignment by my professor to implement two buttons and control a fan. I am very new to GUI's and I have not the slightest clue how to call upon my timer in order to increment it using timer.setDelay(); Any help would be greatly appreciated. My code is below:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Fan extends JFrame implements ActionListener{
JButton speedup;
JButton slowdown;
JPanel testPanel = new MyPanel();//trying to inherit properties of MyPanel
public Fan() {
add(testPanel);
GridLayout f = new GridLayout(1,2);
setLayout(f);
JButton speedup = new JButton("Speed Up");
speedup.addActionListener(this);
add(speedup);
JButton slowdown = new JButton("Slow Down");
slowdown.addActionListener(this);
add(slowdown);
}
/* public void actionPerformed(ActionEvent event){
int delay;
String cmd = event.getActionCommand();
if(cmd == "Speed Up" ){
delay = testPanel.getTimer().getDelay();
delay++;
testPanel.getTimer().setDelay(delay);
}
else{
delay = testPanel.getTimer().getDelay();
delay--;
testPanel.getTimer().setDelay(delay);
*/
//My attempt at getting timer to work commented out
}
public class MyPanel extends JPanel {
private static final long serialVersionUID = 1L;
public Timer timer = new Timer(10, new TimerListener());
private int alpha = 0; //angle
public Timer getTimer(){
return timer; //getter method for timer
}
public MyPanel() {
timer.start();
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
alpha = alpha + 1;
int xc = getWidth()/2;
int yc = getHeight()/2;
int rad = (int)(Math.min(getWidth(), getHeight())*0.4);
int x = xc - rad;
int y = yc - rad;
g.fillArc(x, y, 2*rad, 2*rad, 0+alpha, 30);
g.fillArc(x, y, 2*rad, 2*rad, 90+alpha, 30);
g.fillArc(x, y, 2*rad, 2*rad, 180+alpha, 30);
g.fillArc(x, y, 2*rad, 2*rad, 270+alpha, 30);
}
class TimerListener implements ActionListener {
public void actionPerformed(ActionEvent e){
repaint();
}
}
public static void main(String[] args) {
JFrame fan = new Fan();
fan.setSize(700, 700);
fan.setLocationRelativeTo(null);
fan.setDefaultCloseOperation(EXIT_ON_CLOSE);
fan.setTitle("Spinning Fan");
fan.setVisible(true);
}
}
JPanel testPanel = new MyPanel(); will limit testPanel to the methods of JPanel (so you can't use testPanel.getTimer()). Instead use MyPanel testPanel = new MyPanel();, then you will be able to use testTimer.getTimer();
if(cmd == "Speed Up" ){. Don't compare Strings with ==. Instead use equals. So if ("Speed Up".equals(cmd)) {}
If you want to "Speed up" an animation, you should decrease the delay, not increase it. And vice verse.
Side Notes
Run Swings apps on the Event Dispatch Thread. You can achieve this by wrapping the code in your main in a SwingUtilities.invokeLater(...). See more at Initial Threads
Here's a fixed example
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class Fan extends JFrame implements ActionListener {
JButton speedup;
JButton slowdown;
MyPanel testPanel = new MyPanel();// trying to inherit properties of MyPanel
public Fan() {
add(testPanel);
JButton speedup = new JButton("Speed Up");
speedup.addActionListener(this);
JButton slowdown = new JButton("Slow Down");
slowdown.addActionListener(this);
JPanel panel = new JPanel();
panel.add(speedup);
panel.add(slowdown);
add(panel, BorderLayout.SOUTH);
pack();
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setTitle("Spinning Fan");
setVisible(true);
}
public void actionPerformed(ActionEvent event) {
int delay;
String cmd = event.getActionCommand();
if ("Speed Up".equals(cmd)) {
delay = testPanel.getTimer().getDelay();
delay--;
testPanel.getTimer().setDelay(delay);
} else {
delay = testPanel.getTimer().getDelay();
delay++;
testPanel.getTimer().setDelay(delay);
}
}
// My attempt at getting timer to work commented out
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new Fan();
}
});
}
}
class MyPanel extends JPanel {
private static final long serialVersionUID = 1L;
public Timer timer = new Timer(10, new TimerListener());
private int alpha = 0; // angle
public Timer getTimer() {
return timer; // getter method for timer
}
public MyPanel() {
timer.start();
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
alpha = alpha + 1;
int xc = getWidth() / 2;
int yc = getHeight() / 2;
int rad = (int) (Math.min(getWidth(), getHeight()) * 0.4);
int x = xc - rad;
int y = yc - rad;
g.fillArc(x, y, 2 * rad, 2 * rad, 0 + alpha, 30);
g.fillArc(x, y, 2 * rad, 2 * rad, 90 + alpha, 30);
g.fillArc(x, y, 2 * rad, 2 * rad, 180 + alpha, 30);
g.fillArc(x, y, 2 * rad, 2 * rad, 270 + alpha, 30);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(600, 600);
}
class TimerListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
repaint();
}
}
}
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
I have 2 classes, one which extends a panel and other which extends a frame.
First class, the panel(used for drawings):
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class GraficPne extends JPanel{
public int dim1 = 0, dim2 = 0;
public JLabel lblSem1GraficPne, lblSem2GraficPne;
public GraficPne(){
super();
this.setLayout(null);
this.setupComponents();
}
public void setupComponents(){
lblSem1GraficPne = new JLabel("Sem I");
lblSem2GraficPne = new JLabel("Sem II");
lblSem1GraficPne.setFont(new Font("Serif", Font.PLAIN, 12));
lblSem2GraficPne.setFont(new Font("Serif", Font.PLAIN, 12));
this.add(lblSem1GraficPne);
this.add(lblSem2GraficPne);
}
public void layComponents(int firstConv, int secondConv){
lblSem1GraficPne.setBounds(20, getHeight() - firstConv - 20, 100, 20);
lblSem2GraficPne.setBounds(100, getHeight() - secondConv - 20, 100, 20);
}
public void paint(Graphics g){
super.paint(g);
g.setColor(Color.BLACK);
g.drawRect(0, 0, getWidth()-1, getHeight()-1);
this.setBackground(Color.GREEN);
g.setColor(Color.RED);
g.fillRect(20, getHeight()-dim1, 40, dim1);
g.setColor(Color.BLUE);
g.fillRect(100, getHeight()-dim2, 40, dim2);
}
public void setData(int dim1, int dim2){
this.dim1 = dim1;
this.dim2 = dim2;
}
}
Second class, the frame, used to add the panel on it:
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JTextField;
public class GraficFrm extends JFrame implements ActionListener{
private JButton btnApply;
private JLabel lblSem1, lblSem2;
private JTextField txtSem1, txtSem2;
private GraficPne ob; //the object from first class
private int firstConv = 0, secondConv = 0;
public GraficFrm() {
super("Grafic soft");
initSettings();
setupComponents();
}
private void initSettings() {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLayout(null);
this.setSize(400, 450);
this.setLocation(100, 100);
this.setResizable(false);
}
private void setupComponents() {
ob = new GraficPne();
lblSem1 = new JLabel("Sem I");
txtSem1 = new JTextField();
lblSem2 = new JLabel("Sem II");
txtSem2 = new JTextField();
btnApply = new JButton("Apply");
ob.setBounds(30, 50, 340, 200);
lblSem1.setBounds(30, 280, 100, 20);
txtSem1.setBounds(150, 280, 220, 20);
lblSem2.setBounds(30, 330, 100, 20);
txtSem2.setBounds(150, 330, 220, 20);
btnApply.setBounds(170, 380, 80, 30);
this.add(lblSem1);
this.add(ob);
this.add(txtSem1);
this.add(lblSem2);
this.add(txtSem2);
this.add(btnApply);
btnApply.addActionListener(this);
}
public void getConvertedValues(){
String txtField1 = txtSem1.getText();
firstConv = Integer.parseInt(txtField1);
String txtField2 = txtSem2.getText();
secondConv = Integer.parseInt(txtField2);
}
public void getHighValues(){
if((firstConv > 100) || (secondConv > 100)) {
JOptionPane.showMessageDialog(this, "Only values < 100 are allowed");
firstConv = 0;
secondConv = 0;
txtSem1.setText("");
txtSem2.setText("");
ob.removeAll();
ob.repaint();
}
}
public void actionPerformed(ActionEvent e) {
if(e.getSource().equals(btnApply)){
try{
new GraficFrm();
getConvertedValues();
getHighValues();
ob.setData(firstConv, secondConv);
ob.layComponents(firstConv,secondConv);
ob.repaint();
}catch(NumberFormatException ex1){
JOptionPane.showMessageDialog(this, "Only natural numbers are allowed");
}
}
}
public static void main(String[] args) {
GraficFrm frm = new GraficFrm();
frm.setVisible(true);
}
}
All I want to do is to create a new method called getNegativeValues(), which would be called by pressing the Apply button, and this method to be executed when firstConv or secondConv would be < than 0. The block of my method, getNegativeValues(), i want to keep only the green background of the panel, as it is in paint(Graphics g), but to draw a center horizontal line(g.drawLine(0, getHeight()/2, getWidth(), getHeight()/2);). Then, when i execute the program and i type, let's say the value 55 for the first textfield and -40 for the second one, to draw 55 over my center horizontal line and -40 under my center horizontal line, and the 0 point would be on this center horizontal line.
LE:
#nIcE cOw i'll make a short recap: So, first, when i execute my app, i just want to appear my green panel and those 2 labels which have 2 textfields, as in my example(try to follow my example, please)(all good, i already did this, so this part is done). After, when i complete those 2 textfields let's say with 2 positive values, and then when i press the Apply button to happen exactly like in my example(without any center vertical line)(so already did this, also). All good, but my problem is: If complete one of those 2 textfields with a negative value and other with a positive one, and after i press the Apply button, i want that my application to recognize that there is a negative value typped in one of my textfields, thus to draw me on my green panel a center horizontal line(after i press the Apply button) and to draw those 2 rectangles exactly as you did in your first picture uploaded. Please help me, as i said i'll help you to understand what i want to do, and also i want to say i really appreciate your effort and i'm sorry (again) if i was confused(again).
I guess, what you looking for is a method as presented below, that might can calculate, the starting point of Rectangles that you are trying to draw on the JPanel. Here pos is Positive Value and neg is Negative Value:
public void setValues(int above, int below)
{
midPoint = getHeight() / 2;
heightAbove = Math.abs(above);
heightBelow = Math.abs(below);
/*
* If both are negative values,
* we need a Mid-Point in this case.
*/
if (above < 0 && below < 0)
{
rectAbove = midPoint;
diff = 120;
rectBelow = midPoint;
flag = true;
}
else if (above >= 0 && below >= 0)
{
rectAbove = getHeight() - heightAbove;
diff = 120;
rectBelow = getHeight() - heightBelow;
flag = false;
}
else if (above < 0 && below >= 0)
{
rectAbove = midPoint;
diff = 40;
rectBelow = midPoint - heightBelow;
flag = true;
}
else if (above >= 0 && below < 0)
{
rectAbove = midPoint - heightAbove;
diff = 40;
rectBelow = midPoint;
flag = true;
}
repaint();
}
Here is the code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class PaintingRectangles
{
private JTextField aboveField;
private JTextField belowField;
private JButton applyButton;
private MyCanvas canvas;
private void displayGUI()
{
JFrame frame = new JFrame("Painting Rectangles Example");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JPanel contentPane = new JPanel();
contentPane.setLayout(new BorderLayout(5, 5));
JPanel rightPanel = new JPanel();
rightPanel.setLayout(new GridLayout(3, 1, 5, 5));
aboveField = new JTextField(10);
belowField = new JTextField(10);
applyButton = new JButton("Apply");
applyButton.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent ae)
{
int above = 0;
int below = 0;
try
{
above = Integer.parseInt(aboveField.getText());
below = Integer.parseInt(belowField.getText());
}
catch(NumberFormatException nfe)
{
aboveField.setText("0");
belowField.setText("0");
above = 0;
below = 0;
nfe.printStackTrace();
}
canvas.setValues(above, below);
}
});
rightPanel.add(aboveField);
rightPanel.add(belowField);
rightPanel.add(applyButton);
canvas = new MyCanvas();
contentPane.add(canvas, BorderLayout.CENTER);
contentPane.add(rightPanel, BorderLayout.LINE_END);
frame.setContentPane(contentPane);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
#Override
public void run()
{
new PaintingRectangles().displayGUI();
}
});
}
}
class MyCanvas extends JPanel
{
private int midPoint = getHeight() / 2;
private int rectAbove = getHeight() / 2;
private int rectBelow = getHeight() / 2;
private int width = 40;
private int heightAbove = 0;
private int heightBelow = 0;
private int diff = 0;
private boolean flag = false;
public MyCanvas()
{
setBackground(Color.GREEN);
}
public void setValues(int above, int below)
{
midPoint = getHeight() / 2;
heightAbove = Math.abs(above);
heightBelow = Math.abs(below);
/*
* If both are negative values,
* we need a Mid-Point in this case.
*/
if (above < 0 && below < 0)
{
rectAbove = midPoint;
diff = 120;
rectBelow = midPoint;
flag = true;
}
else if (above >= 0 && below >= 0)
{
rectAbove = getHeight() - heightAbove;
diff = 120;
rectBelow = getHeight() - heightBelow;
flag = false;
}
else if (above < 0 && below >= 0)
{
rectAbove = midPoint;
diff = 40;
rectBelow = midPoint - heightBelow;
flag = true;
}
else if (above >= 0 && below < 0)
{
rectAbove = midPoint - heightAbove;
diff = 40;
rectBelow = midPoint;
flag = true;
}
repaint();
}
#Override
public Dimension getPreferredSize()
{
return (new Dimension(400, 400));
}
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setColor(Color.BLACK);
g.drawRect(0, 0, getWidth(), getHeight());
if (flag)
g.drawLine(0, getHeight() / 2, getWidth(), getHeight() / 2);
makeRectangles(g);
}
private void makeRectangles(Graphics g)
{
g.setColor(Color.RED);
g.fillRect(40, rectAbove, width, heightAbove);
g.setColor(Color.BLUE);
g.fillRect(diff, rectBelow, width, heightBelow);
g.dispose();
}
}
Here is the output:
So I have a JSplitPane, and two JPanels - one on top, one on the bottom. In both panels I overrode the paintComponent method and added my own graphics. In the bottom panel, I wanted to add an animation. When the panel does not repaint, it's fine, but as soon as the Timer (javax.swing.Timer) starts to call repaints, the bottom panel mimics the appearance of the top panel and glitches out. The actual animations are not refreshed, but rather it keeps on adding (like a dragged paintbrush instead of a moving object).
Here's the code for the Bottom Panel class:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.JPanel;
import javax.swing.Timer;
public class WaitControls extends JPanel {
private int pos;
public WaitControls(){
setBackground(Color.gray);
pos = 0;
}
public void progress(){
//animation timer:
Timer timer = new Timer(30, new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
pos++;
repaint();
}
});
timer.start();
}
#Override
public void paintComponent(Graphics g){
g.fillRect(pos, pos, 10, 20);
}
}
And here's the code for the Splitpane class:
//my classes (imported packages)
import rcc.controls.ControlPanel;
import rcc.controls.InitControls;
import rcc.controls.WaitControls;
import rcc.video.Screen;
import javax.swing.JSplitPane;
public class MainPanel extends JSplitPane{
public RCC rcc;
public Screen screen;
private int height;
public ControlPanel curPanel;
public MainPanel(RCC rcc, Screen screen, int height){
super(JSplitPane.VERTICAL_SPLIT);
this.rcc = rcc;
this.screen = screen;
this.height = height;
setDividerSize(2);
setEnabled(false);
setTopComponent(screen);
setToInitControls();
}
//sets the control panel to init controls ***WORKS FINE***
public void setToInitControls(){
InitControls initCtrls = new InitControls(this);
setBottomComponent(initCtrls);
curPanel = initCtrls;
setDividerLocation(height / 4 * 3);
}
//sets the control panel to wait controls (trying to connect) ***GLITCHES***
public void setToWaitControls(){
WaitControls waitCtrls = new WaitControls();
setBottomComponent(waitCtrls);
curPanel = waitCtrls;
setDividerLocation(height / 4 * 3);
waitCtrls.progress();
}
}
The top panel is a bit complicated. It involves mouse action (including a MouseEntered listener) and animates to interact with user mouse input.
The strange thing is, I have another bottom panel that was swapped out that also uses animations, and a timer, and does not have this glitch.
Any ideas what may have caused this? Thank you for all your help!
I can't imagine how your animations works,
1/ but if animation(s) depends of by any of Listener then Timer must be Timer#restart();
2/ check (example), how to pass addNotify()/removeNotify() for start/stop animatiom(s)
NOTE required fullHD monitor for better output or change code line
for (int iPanels = 0; iPanels < 3; iPanels++) {
to
for (int iPanels = 0; iPanels < 2; iPanels++) {
Example:
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class AnimationBackground {
public AnimationBackground() {
Random random = new Random();
JFrame frame = new JFrame("Animation Background");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.setLayout(new GridLayout(0, 3, 10, 10));
for (int iPanels = 0; iPanels < 3; iPanels++) {
final MyJPanel panel = new MyJPanel();
panel.setBackground(Color.BLACK);
for (int i = 0; i < 50; i++) {
Star star = new Star(new Point(random.nextInt(490), random.nextInt(490)));
star.setColor(new Color(100 + random.nextInt(155), 100 + random.nextInt(155), 100 + random.nextInt(155)));
star.setxIncr(-3 + random.nextInt(7));
star.setyIncr(-3 + random.nextInt(7));
panel.add(star);
}
panel.setLayout(new GridLayout(10, 1));
JLabel label = new JLabel("This is a Starry background.", JLabel.CENTER);
label.setForeground(Color.WHITE);
panel.add(label);
JPanel stopPanel = new JPanel();
stopPanel.setOpaque(false);
stopPanel.add(new JButton(new AbstractAction("Stop this madness!!") {
private static final long serialVersionUID = 1L;
#Override
public void actionPerformed(ActionEvent e) {
panel.stopAnimation();
}
}));
panel.add(stopPanel);
JPanel startPanel = new JPanel();
startPanel.setOpaque(false);
startPanel.add(new JButton(new AbstractAction("Start moving...") {
private static final long serialVersionUID = 1L;
#Override
public void actionPerformed(ActionEvent e) {
panel.startAnimation();
}
}));
panel.add(startPanel);
frame.add(panel);
}
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
AnimationBackground animationBackground = new AnimationBackground();
}
});
}
class Star extends Polygon {
private static final long serialVersionUID = 1L;
private Point location = null;
private Color color = Color.YELLOW;
private int xIncr, yIncr;
static final int WIDTH = 500, HEIGHT = 500;
Star(Point location) {
int x = location.x;
int y = location.y;
this.location = location;
this.addPoint(x, y + 8);
this.addPoint(x + 8, y + 8);
this.addPoint(x + 11, y);
this.addPoint(x + 14, y + 8);
this.addPoint(x + 22, y + 8);
this.addPoint(x + 17, y + 12);
this.addPoint(x + 21, y + 20);
this.addPoint(x + 11, y + 14);
this.addPoint(x + 3, y + 20);
this.addPoint(x + 6, y + 12);
}
public void setColor(Color color) {
this.color = color;
}
public void move() {
if (location.x < 0 || location.x > WIDTH) {
xIncr = -xIncr;
}
if (location.y < 0 || location.y > WIDTH) {
yIncr = -yIncr;
}
translate(xIncr, yIncr);
location.setLocation(location.x + xIncr, location.y + yIncr);
}
public void setxIncr(int xIncr) {
this.xIncr = xIncr;
}
public void setyIncr(int yIncr) {
this.yIncr = yIncr;
}
public Color getColor() {
return color;
}
}
class MyJPanel extends JPanel {
private static final long serialVersionUID = 1L;
private ArrayList<Star> stars = new ArrayList<Star>();
private Timer timer = new Timer(20, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
for (Star star : stars) {
star.move();
}
repaint();
}
});
public void stopAnimation() {
if (timer.isRunning()) {
timer.stop();
}
}
public void startAnimation() {
if (!timer.isRunning()) {
timer.start();
}
}
#Override
public void addNotify() {
super.addNotify();
timer.start();
}
#Override
public void removeNotify() {
super.removeNotify();
timer.stop();
}
MyJPanel() {
this.setPreferredSize(new Dimension(520, 520));
}
public void add(Star star) {
stars.add(star);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
for (Star star : stars) {
g.setColor(star.getColor());
g.fillPolygon(star);
}
}
}
}