Related
I made a fairly simple code and i got into an error which confused me.
So I have a class that creates two totally different variables and creating them using the new keyword
Player playerLeft = new Player(5,150);
Player playerRight = new Player( 150,150);
Player class:
import javax.swing.*;
import java.awt.*;
public class Player extends JComponent {
private int posY;
private int posX;
public Player(int x, int y) {
posX = x;
posY = y;
//repaint();
}
public float getMovementY() {
return movementY;
}
public void setMovementY(int movementY) {
this.movementY = movementY;
}
int movementY = 0;
public void paintComponent(Graphics g) {
Graphics2D _g2 = (Graphics2D) g;
Rectangle rect = new Rectangle(posX, posY, 20, 150);
_g2.fill(rect);
}
public void setLocation(int x, int y) {
posY = y;
posX = x;
repaint();
}
public void move() {
setLocation(posX, posY + movementY);
}
}
It's probably me not knowing something about Java but for me when I try to instantiate playerRight it just overwrites player left and drawsOut playerRight only.
Here is the complete code:
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Timer;
import java.util.TimerTask;
public class mainJFrame extends JFrame implements KeyListener {
int relativeTimeMillsec = 0;
Player playerLeft = new Player(5, 150);
Player playerRight = new Player(150, 150);
Timer timer = new Timer();
TimerTask task = new TimerTask() {
#Override
public void run() {
relativeTimeMillsec++;
refreshTimeText(relativeTimeMillsec);
calcMovements();
}
};
//components
JLabel timeCounterLabel = new JLabel("Time: " + 0, SwingConstants.CENTER);
public mainJFrame() {
createComponents();
addKeyListener(this);
}
public void createComponents() {
this.setTitle("The title");
this.setSize(800, 600);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
timer.scheduleAtFixedRate(task, 0, 10);
JButton testButton = new JButton("Label");
testButton.setSize(100, 25);
testButton.setLocation(this.getWidth() / 2 - testButton.getWidth() / 2, this.getHeight() / 2 - testButton.getHeight() / 2);
timeCounterLabel.setSize(200, 25);
timeCounterLabel.setLocation(this.getWidth() / 2 - timeCounterLabel.getWidth() / 2, 10);
//playerRight = new Player(this.getWidth()-45,this.getHeight()/2);
// this.add(testButton);
this.add(timeCounterLabel);
this.add(playerLeft);
this.add(playerRight);
}
public void paintComponent(Graphics g) {
{
super.repaint();
}
}
#Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_S) {
playerLeft.movementY = +2;
} else if (e.getKeyCode() == KeyEvent.VK_W) {
playerLeft.movementY = -2;
}
if (e.getKeyCode() == KeyEvent.VK_UP) {
playerRight.movementY = +2;
} else if (e.getKeyCode() == KeyEvent.VK_DOWN) {
playerRight.movementY = -2;
}
}
#Override
public void keyReleased(KeyEvent e) {
}
#Override
public void keyTyped(KeyEvent e) {
}
private double calcRealRelativeTime(int _relTime) {
return relativeTimeMillsec / (double) 100;
}
private void refreshTimeText(int _relTime) {
timeCounterLabel.setText("Time: " + Math.round(calcRealRelativeTime(_relTime)));
}
private void calcMovements() {
playerLeft.move();
playerRight.move();
}
}
Understand that a JFrame's contentPane (the container that holds its components) uses BorderLayout by default, and this code:
this.add(timeCounterLabel);
this.add(playerLeft);
this.add(playerRight);
is adding all components to the same default BorderLayout.CENTER position, meaning any components added will replace components added previously.
But more importantly, yours is a common problem and stems from your having your Player class extend from a GUI component. Don't do this, as then you will have a great deal of difficulty drawing multiple Player objects and having them interact easily (as you're finding out). Instead have Player be a logical (non-component) class, and have only one class extend JPanel and do all the drawing. This class can hold Player objects, perhaps held in a collection such as an ArrayList<Player>, and then iterate through the collection within its paintComponent method.
Other issues:
Do not use java.util.Timer and java.util.TimerTask for Swing animations since these classes do not follow Swing threading rules. Use instead a javax.swing.Timer.
Learn and use Java naming conventions. Variable names should all begin with a lower letter while class names with an upper case letter. Learning this and following this will allow us to better understand your code, and would allow you to better understand the code of others
If/when you do override a painting method such as paintComponent, be sure to call the super's method within your override, usually on the first line, so as not to break the painting chain. Also, use the #Override annotation before this method and any other methods that you think that you may be overriding so that the compiler catches possible errors with this.
For example (but not a complete example)
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
#SuppressWarnings("serial")
public class SimpleAnimation extends JPanel {
private static final int PREF_W = 800;
private static final int PREF_H = 600;
private static final int TIMER_DELAY = 20;
private Player2 playerLeft = new Player2(5, 150, Color.RED);
private Player2 playerRight = new Player2(150, 150, Color.BLUE);
public SimpleAnimation() {
playerLeft.setySpeed(1);
playerRight.setySpeed(-1);
new Timer(TIMER_DELAY, new TimerListener()).start();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
playerLeft.draw(g);
playerRight.draw(g);
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private class TimerListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
playerRight.move();
playerLeft.move();
repaint();
}
}
private static void createAndShowGui() {
SimpleAnimation mainPanel = new SimpleAnimation();
JFrame frame = new JFrame("SimpleAnimation");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
class Player2 {
private static final int RECT_WIDTH = 20;
private static final int RECT_HEIGHT = 50;
private int x;
private int y;
private int ySpeed;
private Color color;
public Player2(int x, int y, Color color) {
this.x = x;
this.y = y;
this.color = color;
}
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public void setySpeed(int ySpeed) {
this.ySpeed = ySpeed;
}
public int getySpeed() {
return ySpeed;
}
public void setLocation(int x, int y) {
setX(x);
setY(y);
}
public void move() {
setLocation(x, y + ySpeed);
}
public void draw(Graphics g) {
g.setColor(color);
g.fillRect(x, y, RECT_WIDTH, RECT_HEIGHT);
}
}
My experience in Java is very little but I like programming and everything I make I want it to be as good as possible. Having studied Java for a total time of at most 2 days, it is not so easy.
I've been asked to make a Logic Gate Simulator. I've done everything besides the GUI. It is not necessary as given by our teacher but it is for me as communication with the user in such a program is complicated. A GUI will make it much more clear.
I would like to create the gates on a canvas and then be able to move them around. I started by making an AND gate and got it to move around with the mouse when clicked.
I noticed, however, that now I have a canvas on top of everything. Every label,button, etc I add is behind the canvas. It seems like the canvas is necessary in order to move the gate as it is actually repainted when I move it.
The gate AND is made inside a class with paintComponent. Will I have to make every gate in this single class so they can be on the same canvas? How can I make every gate,label,button share the same canvas ?
Here is my code finally.Gates move with a double-click. It is long though.
Main:
package Pack;
import java.util.Scanner;
import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;
public class Main {
public static JFrame f;
public static void main(String[] args) {
ShapeAnd sh=new ShapeAnd();
ShapeOr sh2=new ShapeOr();
f=new JFrame();
f.add(sh);
f.add(sh2);
f.setVisible(true);
f.setSize(700,600);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setTitle("LGS");
f.getContentPane().setBackground(Color.RED);
}
}
OR:
package Pack;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
public class ShapeOr extends JPanel implements MouseListener,MouseMotionListener{
int preX,preY,preX2,preY2,difX,difY;
Graphics g2;
GeneralPath Or;
int lim1x,lim2x,lim1y,lim2y;
boolean check;
public ShapeOr() {
preX=15;
preY=0;
addMouseMotionListener(this);
addMouseListener(this);
}
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
lim1x=preX;
lim2x=preX+80;
lim1y=preY;
lim2y=preY+60;
int x1Points[] = {preX,preX+50,preX+60,preX+70,preX+80,preX+70,preX+60,preX+50,preX,preX+10,preX+20,preX+30,preX+20,preX+10,preX};
int y1Points[] = {preY,preY,preY+5,preY+15,preY+30,preY+45,preY+55,preY+60,preY+60,preY+55,preY+45,preY+30,preY+15,preY+5,preY};
GeneralPath Or = new GeneralPath(GeneralPath.WIND_EVEN_ODD,
x1Points.length);
Or.moveTo(preX-15,preY+15);
Or.lineTo(preX+20,preY+15);
Or.moveTo(preX-15,preY+45);
Or.lineTo(preX+20,preY+45);
Or.moveTo(preX,preY);
for (int index = 1; index < x1Points.length; index++) {
Or.lineTo(x1Points[index], y1Points[index]);
};
Or.closePath();
g2.draw(Or);
//check=false;
}
public void mousePressed(MouseEvent e) {
difX=preX-e.getX();
difY=preY-e.getY();
}
public void updateLocation(MouseEvent e){
preX=e.getX()+difX;
preY=e.getY()+difY;
repaint();
}
public void mouseReleased(MouseEvent e) {
check=false;
}
public void mouseMoved(MouseEvent e) {
}
public void mouseClicked(MouseEvent e) {
int mouseX=e.getX();
int mouseY=e.getY();
if(mouseX>lim1x && mouseX<lim2x && mouseY>lim1y && mouseY<lim2y){
check=true;
}
}
public void mouseExited(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
public void mouseDragged(MouseEvent e) {
if(check==true){
updateLocation(e);
}
}
}
AND:
package Pack;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
public class ShapeAnd extends JPanel implements MouseListener,MouseMotionListener{
int preX,preY,preX2,preY2,difX,difY;
Graphics g2;
GeneralPath And;
int lim1x,lim2x,lim1y,lim2y;
boolean check;
public ShapeAnd() {
addMouseMotionListener(this);
addMouseListener(this);
}
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
lim1x=preX+15;
lim2x=preX+95;
lim1y=preY;
lim2y=preY+75;
int x1Points[] = {preX,preX+ 50, preX+60,preX +70,preX+80,preX+70,preX+60,preX+50,preX+0};
int y1Points[] = {preY+0,preY+ 0,preY+5,preY+15,preY+30,preY+45,preY+55,preY+60,preY+60};
GeneralPath And = new GeneralPath(GeneralPath.WIND_EVEN_ODD,
x1Points.length);
And.moveTo(preX,preY+15);
And.lineTo(preX+15,preY+15);
And.moveTo(preX,preY+45);
And.lineTo(preX+15,preY+45);
And.moveTo(preX+15,y1Points[0]);
for (int index = 1; index < x1Points.length; index++) {
And.lineTo(x1Points[index]+15, y1Points[index]);
};
And.closePath();
g2.draw(And);
//check=false;
}
public void mousePressed(MouseEvent e) {
difX=preX-e.getX();
difY=preY-e.getY();
}
public void updateLocation(MouseEvent e){
preX=e.getX()+difX;
preY=e.getY()+difY;
repaint();
}
public void mouseReleased(MouseEvent e) {
check=false;
}
public void mouseMoved(MouseEvent e) {
}
public void mouseClicked(MouseEvent e) {
int mouseX=e.getX();
int mouseY=e.getY();
if(mouseX>lim1x && mouseX<lim2x && mouseY>lim1y && mouseY<lim2y){
check=true;
}
}
public void mouseExited(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
public void mouseDragged(MouseEvent e) {
if(check==true){
updateLocation(e);
}
}
}
PS:Needs a better title, I know.
Thank you for your code post as that helps clarify things quite a bit. My assumption was correct -- you're making your gates extend a GUI component, adding a lot of unnecessary "weight" to them, and making them hard to move around as you'd like, or place multiple ones of them on your GUI.
Suggestions for a solution include:
Make your gates much more light-weight by not having them extend JPanel or any GUI component.
Instead make them "logical" (non-GUI components) that can be drawn by a single drawing component via a public void draw(Graphics2d g2) method. I usually use the paintComponent(Graphics g) method of a single JPanel to do this drawing.
Give this drawing JPanel an ArrayList of your gate objects, and then draw the gates by iterating through the list in the JPanel's single paintComponent method.
Add to the same JPanel a MouseAdapter as both mouse listener and motion listener, and allow this listener to change the state of any of your gate shapes that have been clicked or dragged on.
Allow the gates to draw themselves by giving them a draw(...) method that a drawing component can call,
Give your gate objects a public boolean contains(Point p) method that allows you to tell if the mouse clicks on them
And give them getter and setter methods for their positions, so that this can be checked and changed.
Utilize the functionality classes that derive from the Shape interface (by composition) to help give your own shape the ability to draw itself and move. I've used Path2D objects for this as they can be easily moved by using AffineTransforms.
Example code forthcoming....
All Gate objects can share the same interface,...
interface MyGate {
void draw(Graphics2D g2);
void setPoint(Point p);
Point getPoint();
boolean contains(Point p);
}
an example gate class that implements the above interface
class OrGate implements MyGate {
private Path2D path;
private Point point = new Point(0, 0); // initial Point
public OrGate() {
// initialize the Path2D and give it a winding rule
path = new Path2D.Double(Path2D.WIND_EVEN_ODD);
// lots of "magic" numbers below, a code design "smell"
// better to not do this. Perhaps have a data file to hold
// this information, and have it read on program startup
int preX = 15;
int preY = 0;
int x1Points[] = { preX, preX + 50, preX + 60, preX + 70, preX + 80, preX + 70, preX + 60,
preX + 50, preX, preX + 10, preX + 20, preX + 30, preX + 20, preX + 10, preX };
int y1Points[] = { preY, preY, preY + 5, preY + 15, preY + 30, preY + 45, preY + 55,
preY + 60, preY + 60, preY + 55, preY + 45, preY + 30, preY + 15, preY + 5, preY };
path.moveTo(preX - 15, preY + 15);
path.lineTo(preX + 20, preY + 15);
path.moveTo(preX - 15, preY + 45);
path.lineTo(preX + 20, preY + 45);
path.moveTo(preX, preY);
for (int index = 1; index < x1Points.length; index++) {
path.lineTo(x1Points[index], y1Points[index]);
}
path.closePath();
}
#Override
public void draw(Graphics2D g2) {
// simple method that leverages the Path2D path object
g2.draw(path);
}
#Override
public boolean contains(Point p) {
// simple method that leverages the Path2D path object
return path.contains(p);
}
#Override
public Point getPoint() {
return point;
}
#Override
public void setPoint(Point p) {
Point pOld = this.point;
Point pNew = p;
this.point = p;
// create a transform that helps us move our Path2D
int tx = pNew.x - pOld.x;
int ty = pNew.y - pOld.y;
AffineTransform at = AffineTransform.getTranslateInstance(tx, ty);
path.transform(at); // and then move it
}
}
Main JPanel that shows use of the MouseAdapter and drawing/dragging of shapes:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
#SuppressWarnings("serial")
public class MainGates2 extends JPanel {
private static final int PREF_W = 700;
private static final int PREF_H = 600;
private List<MyGate> gates = new ArrayList<>();
public MainGates2() {
// create a few Gates
MyGate gate1 = new OrGate();
gate1.setPoint(new Point(200, 300)); // move this guy
MyGate gate2 = new OrGate();
// add them to the gates ArrayList
gates.add(gate1);
gates.add(gate2);
// create our mouse listener / adapter and add to JPanel
MyMouse myMouse = new MyMouse();
addMouseListener(myMouse);
addMouseMotionListener(myMouse);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
// rendering hints to smooth graphics
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// iterate through collection and draw
for (MyGate myGate : gates) {
myGate.draw(g2);
}
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
// give our JPanel some size
return new Dimension(PREF_W, PREF_H);
}
private class MyMouse extends MouseAdapter {
private MyGate selectedGate = null;
private Point p0; // initial Gate location
private Point p1; // first mouse press location
#Override
public void mousePressed(MouseEvent e) {
if (e.getButton() != MouseEvent.BUTTON1) {
return;
}
p1 = e.getPoint();
for (int i = gates.size() - 1; i >= 0; i--) {
if (gates.get(i).contains(e.getPoint())) {
selectedGate = gates.get(i);
p0 = selectedGate.getPoint();
return;
}
}
p1 = null;
}
#Override
public void mouseReleased(MouseEvent e) {
if (selectedGate != null) {
dragShape(e);
// de-select the gate
selectedGate = null;
p0 = null;
p1 = null;
}
}
public void mouseDragged(MouseEvent e) {
if (selectedGate != null) {
dragShape(e);
}
}
private void dragShape(MouseEvent e) {
Point p2 = e.getPoint(); // current mouse location
int x = p0.x + p2.x - p1.x;
int y = p0.y + p2.y - p1.y;
Point p = new Point(x, y);
selectedGate.setPoint(p);
repaint();
};
}
private static void createAndShowGui() {
// main JPanel
MainGates2 mainPanel = new MainGates2();
JFrame frame = new JFrame("Main Gates2");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
These are the specific instruction but they are kind of confusing to me (are the instructions confusing/ambiguous or am I just not getting it?)
write a method public static void draw shooter(Graphics g, Color c);
call draw shooter using the shooter color as the last parameter in drawAll(?)
test the program you should see a red disk centered near the bottom of the screen(?)
import java.awt.*;
public class Project2{
public static final int PANEL_WIDTH = 300;
public static final int PANEL_HEIGHT = 300;
public static final int SLEEP_TIME = 50;
public static Color SHOOTER_COLOR = Color.RED;
public static Color BACKGROUND_COLOR = Color.WHITE;
public static final int SHOOTER_SIZE = 20; //diameter of the shooter
public static final int GUN_SIZE = 10; //length og the gun
public static final int SHOOTER_POSITION_Y = PANEL_HEIGHT - SHOOTER_SIZE;
public static final int SHOOTER_INITIAL_POSITION_X = 150;
int shooterPosition;
public static void initialize(){
int shooterPositionX = SHOOTER_INITIAL_POSITION_X;
}
public static void main(String[] args) {
DrawingPanel panel = new DrawingPanel(PANEL_WIDTH, PANEL_HEIGHT);
Graphics g = panel.getGraphics( );
initialize();
startGame(panel, g);
drawShooter(g, SHOOTER_COLOR);
}
public static void drawShooter(Graphics g, Color C){
g.setColor(Color);
g.fillOval(shooterPosition, SHOOTER_POSITION_Y, SHOOTER_SIZE, SHOOTER_SIZE);
}
public static void drawAll(Graphics g){
g.drawString("Project 2 by Jasmine Ramirez", 10, 15);
}
public static void startGame(DrawingPanel panel, Graphics g) {
for (int i = 0; i <= 10000; i++) {
panel.sleep(SLEEP_TIME);
drawAll(g);
}
}
}
this is my code I guessed that I needed to draw and color in a circle inside the method but I am getting errors with the g.setColor inside the method and I'm not sure what the second step means. Thanks just started learning to program.
Drawing Panel
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.swing.*;
import javax.swing.event.*;
import java.util.ArrayList;
public class DrawingPanel implements ActionListener {
private static final String versionMessage =
"Drawing Panel version 1.1, January 25, 2015";
private static final int DELAY = 100; // delay between repaints in millis
private static final boolean PRETTY = false; // true to anti-alias
private static boolean showStatus = false;
private static final int MAX_KEY_BUF_SIZE = 10;
private int width, height; // dimensions of window frame
private JFrame frame; // overall window frame
private JPanel panel; // overall drawing surface
private BufferedImage image; // remembers drawing commands
private Graphics2D g2; // graphics context for painting
private JLabel statusBar; // status bar showing mouse position
private volatile MouseEvent click; // stores the last mouse click
private volatile boolean pressed; // true if the mouse is pressed
private volatile MouseEvent move; // stores the position of the mouse
private ArrayList<KeyInfo> keys;
// construct a drawing panel of given width and height enclosed in a window
public DrawingPanel(int width, int height) {
this.width = width;
this.height = height;
keys = new ArrayList<KeyInfo>();
image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
statusBar = new JLabel(" ");
statusBar.setBorder(BorderFactory.createLineBorder(Color.BLACK));
statusBar.setText(versionMessage);
panel = new JPanel(new FlowLayout(FlowLayout.CENTER, 0, 0));
panel.setBackground(Color.WHITE);
panel.setPreferredSize(new Dimension(width, height));
panel.add(new JLabel(new ImageIcon(image)));
click = null;
move = null;
pressed = false;
// listen to mouse movement
MouseInputAdapter listener = new MouseInputAdapter() {
public void mouseMoved(MouseEvent e) {
pressed = false;
move = e;
if (showStatus)
statusBar.setText("moved (" + e.getX() + ", " + e.getY() + ")");
}
public void mousePressed(MouseEvent e) {
pressed = true;
move = e;
if (showStatus)
statusBar.setText("pressed (" + e.getX() + ", " + e.getY() + ")");
}
public void mouseDragged(MouseEvent e) {
pressed = true;
move = e;
if (showStatus)
statusBar.setText("dragged (" + e.getX() + ", " + e.getY() + ")");
}
public void mouseReleased(MouseEvent e) {
click = e;
pressed = false;
if (showStatus)
statusBar.setText("released (" + e.getX() + ", " + e.getY() + ")");
}
public void mouseEntered(MouseEvent e) {
// System.out.println("mouse entered");
panel.requestFocus();
}
};
panel.addMouseListener(listener);
panel.addMouseMotionListener(listener);
new DrawingPanelKeyListener();
g2 = (Graphics2D)image.getGraphics();
g2.setColor(Color.BLACK);
if (PRETTY) {
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setStroke(new BasicStroke(1.1f));
}
frame = new JFrame("Drawing Panel");
frame.setResizable(false);
try {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // so that this works in an applet
} catch (Exception e) {}
frame.getContentPane().add(panel);
frame.getContentPane().add(statusBar, "South");
frame.pack();
frame.setVisible(true);
toFront();
frame.requestFocus();
// repaint timer so that the screen will update
new Timer(DELAY, this).start();
}
public void showMouseStatus(boolean f) {
showStatus = f;
}
public void addKeyListener(KeyListener listener) {
panel.addKeyListener(listener);
panel.requestFocus();
}
// used for an internal timer that keeps repainting
public void actionPerformed(ActionEvent e) {
panel.repaint();
}
// obtain the Graphics object to draw on the panel
public Graphics2D getGraphics() {
return g2;
}
// set the background color of the drawing panel
public void setBackground(Color c) {
panel.setBackground(c);
}
// show or hide the drawing panel on the screen
public void setVisible(boolean visible) {
frame.setVisible(visible);
}
// makes the program pause for the given amount of time,
// allowing for animation
public void sleep(int millis) {
panel.repaint();
try {
Thread.sleep(millis);
} catch (InterruptedException e) {}
}
// close the drawing panel
public void close() {
frame.dispose();
}
// makes drawing panel become the frontmost window on the screen
public void toFront() {
frame.toFront();
}
// return panel width
public int getWidth() {
return width;
}
// return panel height
public int getHeight() {
return height;
}
// return the X position of the mouse or -1
public int getMouseX() {
if (move == null) {
return -1;
} else {
return move.getX();
}
}
// return the Y position of the mouse or -1
public int getMouseY() {
if (move == null) {
return -1;
} else {
return move.getY();
}
}
// return the X position of the last click or -1
public int getClickX() {
if (click == null) {
return -1;
} else {
return click.getX();
}
}
// return the Y position of the last click or -1
public int getClickY() {
if (click == null) {
return -1;
} else {
return click.getY();
}
}
// return true if a mouse button is pressed
public boolean mousePressed() {
return pressed;
}
public synchronized int getKeyCode() {
if (keys.size() == 0)
return 0;
return keys.remove(0).keyCode;
}
public synchronized char getKeyChar() {
if (keys.size() == 0)
return 0;
return keys.remove(0).keyChar;
}
public synchronized int getKeysSize() {
return keys.size();
}
private synchronized void insertKeyData(char c, int code) {
keys.add(new KeyInfo(c,code));
if (keys.size() > MAX_KEY_BUF_SIZE) {
keys.remove(0);
// System.out.println("Dropped key");
}
}
private class KeyInfo {
public int keyCode;
public char keyChar;
public KeyInfo(char keyChar, int keyCode) {
this.keyCode = keyCode;
this.keyChar = keyChar;
}
}
private class DrawingPanelKeyListener implements KeyListener {
int repeatCount = 0;
public DrawingPanelKeyListener() {
panel.addKeyListener(this);
panel.requestFocus();
}
public void keyPressed(KeyEvent event) {
// System.out.println("key pressed");
repeatCount++;
if ((repeatCount == 1) || (getKeysSize() < 2))
insertKeyData(event.getKeyChar(),event.getKeyCode());
}
public void keyTyped(KeyEvent event) {
}
public void keyReleased(KeyEvent event) {
repeatCount = 0;
}
}
}
1st Error
In your drawShooter() method you do:
g.setColor(Color)
This is incorrect, since you need to pass an instance of the class Color not the class itself.
So instead use this:
g.setColor(C);
2nd Error
change the shooterPosition to static so that it can be accessed by a static method.
I assume that the method initialize() is also wrong because you are declaring a new shooterPosition int for no reason so do these changes:
int shooterPosition;
To:
public static int shooterPosition;
And
public static void initialize(){
int shooterPositionX = SHOOTER_INITIAL_POSITION_X;
}
To:
public static void initialize() {
shooterPosition = SHOOTER_INITIAL_POSITION_X;
}
3rd Error
In startGame() you are looping for 10000 times and each time you are waiting for a bit more than 1/20th of a second, which means that you will have to wait for almost 10 minutes until the red circle is drawn. So you have two options.
1st option: decrease the amount of iterations or even better remove the loop.
public static void startGame(DrawingPanel panel, Graphics g) {
for (int i = 0; i <= 10000; i++) {
panel.sleep(SLEEP_TIME);
drawAll(g);
}
}
To:
public static void startGame(DrawingPanel panel, Graphics g) {
for (int i = 0; i <= 1; i++) {
panel.sleep(SLEEP_TIME);
drawAll(g);
}
}
or
public static void startGame(DrawingPanel panel, Graphics g) {
panel.sleep(SLEEP_TIME);
drawAll(g);
}
2nd option: execute the drawShooter() method before the startGame() method or don't execute the startGame() at all.
startGame(panel, g); drawShooter(g, SHOOTER_COLOR);
To:
drawShooter(g, SHOOTER_COLOR);
startGame(panel, g);
or
drawShooter(g, SHOOTER_COLOR);
Didn't you ask this same question or something similar to it yesterday? And you're passing in the class name to g.setColor(Color) method and need to pass in the parameter which holds the object: g.setColor(C)
Your use of Graphics is not good, as you shouldn't use a Graphics obtained from a component via getGraphics(), but I'm guessing that it's because that's what your instructor told you to do. Same for use of a while (true) loop. Instead you should use a Swing Timer.
Like stated before g.setcolor(c) is required
check your error msgs since it allows you to gather that error and the shooterPosition error(its not public so cant be used inside a method)
When I create a Board instance from my Square instance, I try to assign the size of the window to the integers x and y. I fail to do this because it seems like on start the size is 0. In the constructor in Board.java, x and y shouldn't be -50 like they end up now.
Square.java:
package Square;
import javax.swing.*;
public class Square extends JFrame {
public Square(){
add(new Board());
setSize(800, 800);
setVisible(true);
}
public static void main(String[] args){
new Square();
}
}
Board.java
package Square;
import javax.swing.*;
import java.awt.*;
public class Board extends JPanel{
int x,y;
public Board(){
x = width-50;
y = height-50;
}
public int width = (int) getSize().getWidth();
public int height = (int) getSize().getHeight();
public void paintComponent(Graphics g){
super.paintComponent(g);
g.fillRect(x,y, 100, 100);
}
}
Full Code for clarification:
Square.java
package Square;
import javax.swing.*;
public class Square extends JFrame {
public Square(){
Board board = new Board();
board.start();
add(board);
setTitle("Square");
setSize(800, 800);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
public static void main(String[] args){
Square square = new Square();
square.setVisible(true);
square.setLocation(2000, 150);
}
}
Board.java
package Square;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Board extends JPanel implements ActionListener{
Timer timer;
int x, y;
int velX = 0;
int velY = 0;
public Board(){
setFocusable(true);
timer = new Timer(1, this);
addKeyListener(new TAdapter());
}
class TAdapter extends KeyAdapter{
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
switch(keyCode){
case KeyEvent.VK_ESCAPE: x = width()/2-50; y = height()/2-50; break;
case KeyEvent.VK_RIGHT: velX = 1; break;
case KeyEvent.VK_DOWN: velY = 1; break;
case KeyEvent.VK_LEFT: velX = -1; break;
case KeyEvent.VK_UP: velY = -1; break;
}
}
public void keyReleased(KeyEvent e){
velX = 0;
velY = 0;
}
}
public int width(){ return (int) getSize().getWidth();}
public int height(){ return (int) getSize().getHeight();}
public void start(){
timer.setInitialDelay(100);
timer.start();
x = width()/2-50;
y = height()/2-50;
}
#Override
public void actionPerformed(ActionEvent e) {
x += velX;
y += velY;
repaint();
}
public void paintComponent(Graphics g){
super.paintComponent(g);
g.setColor(Color.RED);
g.fillRect(x,y, 100, 100);
}
}
Put the calculation into your paintComponent method. In general you want to avoid having code in paintComponent that will slow it down, but these calls shouldn't give too much penalty. Also, if your program is re-sizable, you'll need to be able to re-calculate the sizes of things on the go like this:
public void paintComponent(Graphics g){
super.paintComponent(g);
int x = getWidth() - 50;
int y = getHeight() - 50;
g.fillRect(x, y, 100, 100);
}
but of course in your real program, you will want to avoid "magic" numbers
Another issue: don't call setSize() on your JFrame. Instead, if you want to specify a hard size, do so in the JPanel by overriding its getPreferredSize() method. This will also then give you the suggested parameters that can be used for your calculations.
For example:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
#SuppressWarnings("serial")
public class DrawRect extends JPanel {
private static final int PREF_W = 800;
private static final int PREF_H = PREF_W;
private static final int DELTA = 50;
private static final Color RECT_COLOR = Color.red;
private static final int RECT_WIDTH = 100;
private static final int TIMER_DELAY = 15;
private int rectX = PREF_W - DELTA;
private int rectY = PREF_H - DELTA;
public DrawRect() {
new Timer(TIMER_DELAY, new TimerListener()).start();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(RECT_COLOR);
g.fillRect(rectX, rectY, RECT_WIDTH, RECT_WIDTH);
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private class TimerListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
rectX--;
rectY--;
repaint();
}
}
private static void createAndShowGui() {
JFrame frame = new JFrame("DrawRect");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new DrawRect());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
Also, check out the key bindings animation code from this answer of mine.
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.Map;
public class GamePanel extends JPanel {
private static final int ANIMATION_DELAY = 15;
private final int HEIGHT = 400;
private final int WIDTH = 600;
private Square square;
private EnumMap<Direction, Boolean> dirMap = new EnumMap<>(Direction.class);
private Map<Integer, Direction> keyToDir = new HashMap<>();
// !! private Circle circle;
private Timer animationTimer;
public GamePanel() {
for (Direction dir : Direction.values()) {
dirMap.put(dir, Boolean.FALSE);
}
keyToDir.put(KeyEvent.VK_UP, Direction.UP);
keyToDir.put(KeyEvent.VK_DOWN, Direction.DOWN);
keyToDir.put(KeyEvent.VK_LEFT, Direction.LEFT);
keyToDir.put(KeyEvent.VK_RIGHT, Direction.RIGHT);
// !! addKeyListener(new DirectionListener());
setKeyBindings();
setBackground(Color.white);
setPreferredSize(new Dimension(WIDTH, HEIGHT));
setFocusable(true);
square = new Square();
animationTimer = new Timer(ANIMATION_DELAY, new AnimationListener());
animationTimer.start();
}
private void setKeyBindings() {
int condition = WHEN_IN_FOCUSED_WINDOW;
final InputMap inputMap = getInputMap(condition);
final ActionMap actionMap = getActionMap();
boolean[] keyPressed = { true, false };
for (Integer keyCode : keyToDir.keySet()) {
Direction dir = keyToDir.get(keyCode);
for (boolean onKeyPress : keyPressed) {
boolean onKeyRelease = !onKeyPress; // to make it clear how bindings work
KeyStroke keyStroke = KeyStroke.getKeyStroke(keyCode, 0,
onKeyRelease);
Object key = keyStroke.toString();
inputMap.put(keyStroke, key);
actionMap.put(key, new KeyBindingsAction(dir, onKeyPress));
}
}
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
square.display(g);
}
private class AnimationListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent evt) {
boolean repaint = false;
for (Direction dir : Direction.values()) {
if (dirMap.get(dir)) {
square.move(dir);
repaint = true;
}
}
if (repaint) {
repaint();
}
}
}
private class KeyBindingsAction extends AbstractAction {
private Direction dir;
boolean pressed;
public KeyBindingsAction(Direction dir, boolean pressed) {
this.dir = dir;
this.pressed = pressed;
}
#Override
public void actionPerformed(ActionEvent evt) {
dirMap.put(dir, pressed);
}
}
private static void createAndShowGUI() {
GamePanel gamePanel = new GamePanel();
JFrame frame = new JFrame("GamePanel");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(gamePanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
gamePanel.requestFocusInWindow();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
enum Direction {
UP(0, -1), DOWN(0, 1), LEFT(-1, 0), RIGHT(1, 0);
private int incrX;
private int incrY;
private Direction(int incrX, int incrY) {
this.incrX = incrX;
this.incrY = incrY;
}
public int getIncrX() {
return incrX;
}
public int getIncrY() {
return incrY;
}
}
class Square {
private int x = 0;
private int y = 0;
private int w = 20;
private int h = w;
private int step = 1;
private Color color = Color.red;
private Color fillColor = new Color(255, 150, 150);
private Stroke stroke = new BasicStroke(3f, BasicStroke.CAP_ROUND,
BasicStroke.JOIN_ROUND);
public void display(Graphics g) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(fillColor);
g2d.fillRect(x, y, w, h);
g2d.setStroke(stroke);
g2d.setColor(color);
g2d.drawRect(x, y, w, h);
g2d.dispose();
}
public void setStep(int step) {
this.step = step;
}
public void move(Direction dir) {
x += step * dir.getIncrX();
y += step * dir.getIncrY();
}
}
Hey your codestyle is horrible, but i try to help :). You can't get a size of an undrawn window. First Things first, your Constructor is wrong, you add the Board that actually create the Board Obj. Calling the Constructor of Board, which has no drawn parent yet and no x,y set. Try to initialize your variables in the Constructor. So just use width and height and fill the values in the constructor. Next, just tell your board its creation size by passing its parent size trough constructor variables.
I think you try to learn java and this is much more elegant. Furthermore, try to do all parent modification before adding some to it. So first setSize, add some Layout (Border/Flow/whatuwish) then get the frames ContentPane and add your Board component. To make things clear, you can't get e.g. the parent and parent size in Contructor because your board Obj isn't created and added yet. If you wish to getParent() and its size, create the Object add it to JFrame and than you can call getParent().getSize(). You get 0 because your JPanel isn't drawn at this time (before creation). If you wish to get the Parent Size just pass the JFrame Ref to Constructor or its size. Another Advise, don't create things in things in things, keep in mind with your code you create your JPanel as first Obj... Here is some example code:
Square:
public class Square extends JFrame {
public static void main(String[] args){
Square square = new Square();
square.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Dimension d = new Dimension(800,800);
square.setPreferredSize(d);
square.setSize(d);
//too much, every Jframe has BorderLayout enabled
square.getContentPane().setLayout(new BorderLayout());
square.getContentPane().add(new Board(square), BorderLayout.CENTER);
square.pack();
square.setVisible(true);
}
}
Board:
public class Board extends JPanel{
int x,y;
JFrame parent;
public Board(JFrame parent){
int width = parent.getPreferredSize().width;
int height = parent.getPreferredSize().height;
x = width-50;
y = height-50;
}
public void paintComponent(Graphics g){
super.paintComponent(g);
g.fillRect(x,y, 100, 100);
}
}
You can take x and y values after the panel has become visible, in the next EDT cycle, by using SwingUtilities.invokeLater, for example.
I have it set up so all it does is draw a light gray background and some rectangles to create a grid. My next goal was to assign two images so I can default the grid to load as one, and then eventually add some listeners to let me change them to the other.
However, when I assign the image (png format) to the Image object through an ImageIcon (created and assigned previously and creating a new one on the spot were tested) it causes the default background color to be shown, and nothing drawn.
This occurs no matter where I move the assignments to except if I put the assignment into the draw method itself.
The image that I'm trying to use works fine, I pulled it straight from a previously working project, the location hadn't changed. But to be sure, I copied the address and put it in again.
Here is the code (The assignment causing the issue is in Block):
Main:
package BLURGpackage;
import javax.swing.JFrame;
public class Main extends JFrame
{
private final int FRAME_WIDTH = 1200, FRAME_HEIGHT = 1034; // add 34 onto height
//to show all of the panel
public Main()
{
setSize(FRAME_WIDTH, FRAME_HEIGHT);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
setVisible(true);
Panel panel = new Panel();
add(panel);
}
public static void main(String[] args)
{
Main m = new Main();
}
}
Panel:
package BLURGpackage;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
public class Panel extends JPanel implements Runnable
{
public final static int PANEL_WIDTH = 1200, PANEL_HEIGHT = 1000;
private Dimension panelDimension = new Dimension(PANEL_WIDTH, PANEL_HEIGHT);
private Thread panelThread = null;
private boolean threadRunning = false;
private Image dbi = null;
private Graphics dbg = null;
Grid grid;
private int mouseX = 0, mouseY = 0;
// ============ CHANGE THESE TO CHANGE THE LOCATION OF WHERE THE X AND Y COORDS ARE PRINTED ON THE SCREEN =============
private int printXCoordsX = 10; // X-Coordinate for where to print the current mouse X location
private int printXCoordsY = 855; // Y-Coordinate for where to print the current mouse X location
private int printYCoordsX = printXCoordsX; // X-Coordinate for where to print the current mouse Y location
private int printYCoordsY = printXCoordsY + 15; // Y-Coordinate for where to print the current mouse Y location
// ====================================================================================================================
public Panel()
{
grid = new Grid();
setPreferredSize(panelDimension);
setBackground(Color.LIGHT_GRAY);
// ===== Listeners ==========
addMouseMotionListener(new MouseMotionAdapter()
{
public void mouseMoved(MouseEvent e)
{
mouseX = e.getX();
mouseY = e.getY();
}
});
// ====== Start ============= (if startPanel is before listeners, dbi is null... dunno why)
startPanel();
}
private void startPanel()
{
if(panelThread == null || threadRunning == false)
{
panelThread = new Thread(this);
threadRunning = true;
panelThread.start();
}
else
System.out.println("panelThread is NOT null on startup");
}
#Override
public void run()
{
while(threadRunning)
{
update();
render();
paintScreen();
}
}
public void update()
{
// Logic here
}
public void render()
{
if(dbi == null)
{
dbi = createImage(PANEL_WIDTH, PANEL_HEIGHT);
if(dbi == null)
System.err.println("dbi is NULL");
else
{
dbg = dbi.getGraphics();
}
}
dbg.setColor(Color.LIGHT_GRAY);
dbg.fillRect(0, 0, PANEL_WIDTH, PANEL_HEIGHT);
draw(dbg);
}
public void paintScreen()
{
Graphics g;
try
{
g = this.getGraphics();
if(dbi != null && g != null)
{
g.drawImage(dbi, 0, 0, null);
}
Toolkit.getDefaultToolkit().sync();
g.dispose();
}catch(Exception e)
{
e.printStackTrace();
}
}
public void draw(Graphics g)
{
g.setColor(Color.BLACK);
g.drawString("X: "+mouseX, printXCoordsX, printXCoordsY);
g.drawString("Y: "+mouseY, printYCoordsX, printYCoordsY);
// Allow the Grid to draw
grid.draw(g);
}
}
Grid:
package BLURGpackage;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import javax.swing.ImageIcon;
public class Grid
{
// ======== CHANGE THESE VARIABLES TO CHANGE THE SIZE OF THE GRID =============
public final static int GRID_ROWS = 21, GRID_COLUMNS = 25;
private final int RECT_WIDTH = 48, RECT_HEIGHT = 40;
private final int NUM_BLOCKS = GRID_ROWS*GRID_COLUMNS;
/*public final static int GRID_ROWS = 25, GRID_COLUMNS = 25;
private final int RECT_WIDTH = Panel.PANEL_WIDTH / GRID_ROWS; // 1200 / 25 = 48 px width per rect
private final int RECT_HEIGHT = Panel.PANEL_HEIGHT / GRID_COLUMNS; // 1000 / 25 = 40 px height per rect
private final int NUM_BLOCKS = GRID_ROWS*GRID_COLUMNS;*/
// ============================================================================
private Block[] blockArray;
private int[] blockSelectArray; // numbers for which block is selected. Feed in through file reader
public Grid()
{
// ===== FOR TESTING ONLY======
blockArray = new Block[NUM_BLOCKS];
blockSelectArray = new int[NUM_BLOCKS];
for(int i=0; i < NUM_BLOCKS; i++)
{
blockSelectArray[i] = 0;
}
// ============================
loadBlocks();
}
private void loadBlocks()
{
int x, y;
x = y = 0;
for(int i = 0; i < NUM_BLOCKS; i++)
{
if(x >= Panel.PANEL_WIDTH) // if x hits right boundary, reset x and increment y by the px height of a single block
{
x = 0;
y += RECT_HEIGHT;
}
blockArray[i] = new Block(blockSelectArray[i], x, y);
x += RECT_WIDTH;
}
}
public void draw(Graphics g)
{
g.setColor(Color.BLACK);
for(int i=0;i<NUM_BLOCKS;i++)
{
g.drawRect(blockArray[i].getBlockX(), blockArray[i].getBlockY(), RECT_WIDTH, RECT_HEIGHT);
blockArray[i].draw(g);
}
}
}
Block:
package BLURGpackage;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
import javax.swing.ImageIcon;
public class Block
{
private Image blockImage = null;
private Image DIRT_IMG = new ImageIcon("C:/Users/Tyler/workspace/IntTut1/src/thejavahub/images/dirt.png").getImage();
// ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ Problem assignment
private Rectangle blockRect = null;
private boolean solid;
private final int RECT_WIDTH = Panel.PANEL_WIDTH / Grid.GRID_ROWS; // 1200 / 25 = 48 px width per rect
private final int RECT_HEIGHT = Panel.PANEL_HEIGHT / Grid.GRID_COLUMNS; // 1000 / 25 = 40 px height per rect
public Block(int blockNum, int x, int y)
{
// switch statement on blockNum for what block
switch(blockNum)
{
default:
System.out.println("Default of switch in Block constrcutor hit");
break;
case 0: // background block
solid = false;
break;
case 1: // dirt block
blockImage = DIRT_IMG; // <---- uses the assigned image --------
solid = true;
break;
}
// set the coordinates of the block
blockRect = new Rectangle(x, y, RECT_WIDTH, RECT_HEIGHT);
}
public void draw(Graphics g)
{
// draw the image here (.... g.drawImage(blockImage, blockRect.x, blockRect.y, null); )
g.drawImage(blockImage, blockRect.x, blockRect.y, null);
}
// ==== GETTERS AND SETTERS ===
public int getBlockX()
{
return this.blockRect.x;
}
public void setBlockX(int x)
{
this.blockRect.x = x;
}
public int getBlockY()
{
return this.blockRect.y;
}
public void setBlockY(int y)
{
this.blockRect.y = y;
}
public boolean isSolid() {
return solid;
}
public void setSolid(boolean solid) {
this.solid = solid;
}
}
Some Points:
Call frame.setVisible(true) in the end after adding all the components.
Use frame.pack() instead of frame.setSize() that fits the components as per component's preferred size.
Override getPreferredSize() to set the preferred size of the JPanel in case of custom painting.
Use Swing Timer instead of Thread that is most suitable for swing application in two ways:
To perform a task once, after a delay.
To perform a task repeatedly.
Read more How to Use Swing Timers
Use SwingUtilities.invokeLater() or EventQueue.invokeLater() to make sure that EDT is initialized properly.
Read more
Why to use SwingUtilities.invokeLater in main method?
SwingUtilities.invokeLater
Should we use EventQueue.invokeLater for any GUI update in a Java desktop application?
sample code:
private Timer timer;
...
// 1 second delay
timer = new javax.swing.Timer(1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
// next call
}
});
timer.setRepeats(true);
timer.start();
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
Main m = new Main();
}
});
}
class MyRoll extends JPanel {
// override paintComponent in case of custom painting
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
...
}
#Override
public Dimension getPreferredSize() {
return new Dimension(..., ...);
}
}