I am trying to learn the paint method and get a ball to move across the frame. here is my code so far. w=.
I currently have two classes One is the main and one for the ball.
this is the main class import java.awt. ; import javax.swing. ;
public class PaintTest extends JPanel {
int x = 0;
int y = 0;
public void moveBall(){
x = x + 1;
y = y + 1;
}
public static void main(String[] args){
JFrame frame = new JFrame();
frame.setSize(500,500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
Ball ball = new Ball(x,y);
while(true){
ball.moveBall();
repaint();
}
}
protected void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g.setColor(Color.magenta);
g.drawLine(0,100,500,100);
g.drawLine(0,101,500,101);
g.drawLine(0,102,500,102);
g.drawLine(0,103,500,103);
g2.fillOval(x,y,35,35);
}
}
and here is the ball class
public class Ball {
int x,y;
public Ball(int x, int y){
this.x = x;
this.y = y;
}
}
now when i compile I get an error saying cannot find symbol ball in class PaintTest even though I am calling it from the class Ball. I am aware of the repaint error as i do not know what to put in front of it.
paintComponent
method not in its paint method -- this gives you double buffering. while (true)
loop as this can cause serious Swing threading issues. Use a Swing Timer instead. repaint()
. This will tell Swing to repaint the component which will re-draw the oval in the new location. For example:
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Stroke;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
@SuppressWarnings("serial")
public class PaintTest extends JPanel {
private static final int PREF_W = 600;
private static final int PREF_H = PREF_W;
private static final int TIMER_DELAY = 20;
private static final Stroke STROKE = new BasicStroke(5f);
private int x;
private int y;
public PaintTest() {
new Timer(TIMER_DELAY, new TimerListener()).start();
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
// to smooth graphics
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(Color.magenta);
Stroke initialStroke = g2.getStroke();
g2.setStroke(STROKE);
g.drawLine(0, 100, 500, 100);
g2.setStroke(initialStroke);
g2.fillOval(x, y, 35, 35);
}
@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) {
x++;
y++;
repaint();
}
}
private static void createAndShowGui() {
PaintTest mainPanel = new PaintTest();
JFrame frame = new JFrame("PaintTest");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
You have to put the paintComponent
method in a JPanel. You can do it by using something like this.
JPanel panel = new JPanel(){
@Overide
public void paintComponent(Graphics g){
super.paint();
// Draw Stuff Here
}
};
The reason you are not getting the ball to move across the frame is that you are not calling the repaint method. You should do so on a thread.
Thread th = new Thread(new Runnable(){
@Overide
public void run(){
while(frame.isVisible()){
ball.moveBall();
panel.repaint();
try{Thread.sleep(5);}catch(Exception e){e.printStackTrace();}
}
}
});
Also, why are you making ball a instance of the PaintTest class? To get only one frame and ball you would want to add a class named Ball
and use that to make an instance:
public class Ball{
int x, y;
public Ball(int x, int y){
this.x = x;
this.y = y;
}
}
That is why you were getting 2 frames.
Then you would want to get rid of the x and y variables in the main class. To make an instance using this class you would do:
Ball ball = new Ball(x, y);
Then to paint the ball in the paintComponent
method you would do:
g.fillOval(ball.x, ball.y, 35, 35);
repaint();
method. y + 1
part. while(true)
loop, you should use a for
loop. super.paint()
method. Thread.sleep()
, which made the ball move across instantaneously. Here is the code:
import java.awt.*;
import javax.swing.*;
public class PaintTest extends JFrame {
int x = 8;
int y = 30;
public void moveBall(){
x = x + 1;
//y = y + 1;
try{
Thread.sleep(500);
} catch(InterruptedException e){
}
repaint();
}
public static void main(String[] args){
PaintTest frame1 = new PaintTest();
PaintTest ball = new PaintTest();
for(int i = 0; i<100; i++){
//while(true){
ball.moveBall();
}
}
public PaintTest() {
super("Paint Test");
setSize(500,500);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
public void paint(Graphics g){
Graphics2D g2 = (Graphics2D) g;
super.paint(g);
super.paint(g2);
g.setColor(Color.magenta);
g.drawLine(0,100,500,100);
g.drawLine(0,101,500,101);
g.drawLine(0,102,500,102);
g.drawLine(0,103,500,103);
g.fillOval(x,y,35,35);
}
}
This code will make the ball move across the screen VERY slowly. If you want to speed it up, change the number of miliseconds in the Thread.sleep(miliseconds)
part to a smaller number of miliseconds.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.