gpt4 book ai didi

java - 在线程中使用 Canvas 对象做简单的动画 - Java

转载 作者:行者123 更新时间:2023-12-04 05:26:43 25 4
gpt4 key购买 nike

我有一个小程序,就像现在写的那样,在按下“运行”按钮后,它应该在顶部(代码中的 drawingpanel)绘制和弹跳一个球。在线查看其他示例并使用来自未使用 Canvas 的其他程序的代码,我无法弄清楚为什么我的 Ball 对象没有显示。我已经测试了程序的流程,并且所有方法都按应有的方式调用,因此代码没有到达paint 的情况并非如此。方法。任何关于使用 Canvas/Thread 的好资源都会很棒,或者对以下小程序的任何建议都会非常有用。谢谢!

import java.awt.*;
import java.applet.*;
import java.awt.event.*;

public class Bounce2 extends Applet implements ActionListener, AdjustmentListener, Runnable
{
private final static long serialVersionUID = 1L;

//runtime variables
boolean running = false;
boolean currentlyCircle = true;
boolean showtails = false;
boolean kill = false;

//buttons
Button runbutton = new Button("Run");
Button pausebutton = new Button("Pause");
Button quitbutton = new Button("Quit");

//text
Label speedlabel = new Label("Speed");
Label sizelabel = new Label("Size");

//scrollbars
private final int barHeight = 20;
private final int SLIDER_WIDTH = 10;
private final int MAXSPEED = 110;
private final int MINSPEED = 0;
private final int MAX_SIZE = 110;
private final int MIN_SIZE = 10;
Scrollbar speedbar = new Scrollbar(Scrollbar.HORIZONTAL, MAXSPEED/2, SLIDER_WIDTH, MINSPEED, MAXSPEED);
Scrollbar sizebar = new Scrollbar(Scrollbar.HORIZONTAL, MAX_SIZE/2, SLIDER_WIDTH, MIN_SIZE, MAX_SIZE);

//drawn objs
Ball ball;
Image buffer;
int size = 50;
private Graphics obj;
Point currentlocation = new Point(100,100);
Point previouslocation;
Point nextlocation;

Rectangle circle;
Rectangle screen;
private Thread ballThread;

//boundaries
int bound_x;
int bound_y;

//directions
int dx = 1; //1 = left, -1 = right
int dy = 1; //1 = up, -1 = down

//speed
int speed = speedbar.getValue();
int delay;

//initialize the applet and draw everything
public void init()
{
double colWeight[] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};//15 cols
double rowWeight[] = {1,1,1,1,1,1,1,1,1,1}; //10 rows
int colWidth[] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};//15 cols
int rowHeight[] = {1,1,1,1,1,1,1,1,1,1}; //10 rows
GridBagConstraints c = new GridBagConstraints();
GridBagLayout gbl = new GridBagLayout();
gbl.rowHeights = rowHeight;
gbl.rowWeights = rowWeight;
gbl.columnWeights = colWeight;
gbl.columnWidths = colWidth;
c.anchor = GridBagConstraints.CENTER;

setBounds(0,0,480,640);
setLayout(new BorderLayout());
Panel controlpanel = new Panel();
controlpanel.setLayout(gbl);
controlpanel.setSize(640,80);

Panel drawingpanel = new Panel(null);
drawingpanel.setSize(640,400);
ball = new Ball();
drawingpanel.add("Center", ball);
Rectangle circle = new Rectangle(size, size);
Rectangle screen = new Rectangle(0,0,640,400);
drawingpanel.setVisible(true);

//speed scrollbar
c.weightx = 1;
c.weighty = 1;
c.gridwidth = 3;
c.gridheight = 1;
c.gridx = 1;
c.gridy = 7;
c.fill= GridBagConstraints.HORIZONTAL;
gbl.setConstraints(this.speedbar,c);

//run button
c.weightx = 1;
c.weighty = 1;
c.gridwidth = 2;
c.gridheight = 1;
c.gridx = 5;
c.gridy = 7;
c.fill= GridBagConstraints.HORIZONTAL;
gbl.setConstraints(this.runbutton,c);

//pause button
c.weightx = 1;
c.weighty = 1;
c.gridwidth = 2;
c.gridheight = 1;
c.gridx = 8;
c.gridy = 7;
c.fill= GridBagConstraints.HORIZONTAL;
gbl.setConstraints(this.pausebutton,c);

//size scrollbar
c.weightx = 1;
c.weighty = 1;
c.gridwidth = 3;
c.gridheight = 1;
c.gridx = 11;
c.gridy = 7;
c.fill= GridBagConstraints.HORIZONTAL;
gbl.setConstraints(this.sizebar,c);

//speed text label
c.weightx = 1;
c.weighty = 1;
c.gridwidth = 3;
c.gridheight = 1;
c.gridx = 1;
c.gridy = 8;
c.fill= GridBagConstraints.HORIZONTAL;
gbl.setConstraints(this.speedlabel,c);

//size text label
c.weightx = 1;
c.weighty = 1;
c.gridwidth = 3;
c.gridheight = 1;
c.gridx = 11;
c.gridy = 8;
c.fill= GridBagConstraints.HORIZONTAL;
gbl.setConstraints(this.sizelabel,c);

//quit button
c.weightx = 1;
c.weighty = 1;
c.gridwidth = 3;
c.gridheight = 1;
c.gridx = 6;
c.gridy = 9;
c.fill= GridBagConstraints.HORIZONTAL;
gbl.setConstraints(this.quitbutton,c);

//add to the screen
controlpanel.add(this.speedbar);
controlpanel.add(this.runbutton);
controlpanel.add(this.pausebutton);
controlpanel.add(this.sizebar);
controlpanel.add(this.speedlabel);
controlpanel.add(this.sizelabel);
controlpanel.add(this.quitbutton);

//add listners
speedbar.addAdjustmentListener(this);
runbutton.addActionListener(this);
pausebutton.addActionListener(this);
sizebar.addAdjustmentListener(this);
quitbutton.addActionListener(this);

//add the panels
add("South", controlpanel);
add("Center", drawingpanel);

//drawing paramaters, draw the first object
System.err.println(obj);
obj = drawingpanel.getGraphics();
nextlocation = new Point(currentlocation.x+dx, currentlocation.y+dy);

setVisible(true);
validate();
}

public void start()
{
if (ballThread == null)
{
ballThread = new Thread(this);
ballThread.start();
repaint();
}
}

public void run()
{
Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
while (!kill)
{
if (running)
{
ball.move();
repaint();
}
try
{
Thread.sleep(delay);
}
catch(InterruptedException e){System.err.println("Interrupted.");}
}
stop();
}

public void update(Graphics g)
{
Graphics buffer;
Image offscreen = null;

offscreen = createImage(bound_x, bound_y);
buffer = offscreen.getGraphics();
buffer.setColor(getBackground());
buffer.fillRect(0,0,bound_x, bound_y);
//update

previouslocation = new Point(currentlocation);
currentlocation = nextlocation;

//draw
buffer.setColor(Color.black);
buffer.drawOval(nextlocation.x, nextlocation.y, size, size);
buffer.fillOval(nextlocation.x, nextlocation.y, size, size);

//draw rectangles out of vector
g.drawImage(offscreen, 0,0, null);
paint(buffer);
}

//class to handle animations
class Ball extends Canvas
{
public void move()
{
nextlocation = new Point(currentlocation.x+dx, currentlocation.y+dy);
//if it will hit the right or left, flip the x direction and set it
if (nextlocation.x+size >= bound_x || nextlocation.x <= 0)
{ dx *= -1; }
nextlocation.x += dx;
//if it will hit the top or bottom, flip the y direction and set it
if (nextlocation.y+size >= bound_y + 100 || nextlocation.y <= 0)
{ dy *= -1; }
nextlocation.y += dy;
setBounds(dx,dy,size,size);
System.out.println(dx + "," + dy);
}

public void paint(Graphics g)
{
super.paint(g);
g.setColor(Color.black);
g.drawOval(0, 0, size, size);
}
}

public void actionPerformed(ActionEvent e)
{
Object source = e.getSource();
if (source == this.runbutton)
{
running = true;
}
else if (source == this.pausebutton)
{
running = false;
}
else if (source == this.quitbutton)
{
//kill processes
kill = true;
//remove listeners
stop();
}
}

public void adjustmentValueChanged(AdjustmentEvent e)
{
Object source = e.getSource();
//set the new size.
if (source == sizebar)
{
//check for clipping
int newsize = sizebar.getValue();

// x
if (currentlocation.x+newsize >= bound_x)
{
newsize = bound_x - currentlocation.x - 1;
sizebar.setValue(newsize);
}

// y
if (currentlocation.y+newsize >= bound_y + 100)
{
newsize = bound_y+100 - currentlocation.y - 1;
sizebar.setValue(newsize);
}
size = newsize;
}
if (source == speedbar)
{
speed = speedbar.getValue();
delay = MAXSPEED - speedbar.getValue();
}
}

public void stop()
{
this.speedbar.removeAdjustmentListener(this);
this.runbutton.removeActionListener(this);
this.pausebutton.removeActionListener(this);
this.sizebar.removeAdjustmentListener(this);
this.quitbutton.removeActionListener(this);
Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
}
}

最佳答案

老实说,我不知道从哪里开始。

这是一个坏主意。

private Graphics obj;
.
.
.
obj = drawingpanel.getGraphics();

任何组件图形都只是一个及时的快照。在下一次重绘时,它将失效(我实际上是一个不同的对象)

你的绘画方法是错误的。以任何方式这样做实际上都是错误的地方,但有很多事情是错误的。除此之外,您应该很少覆盖顶级容器 paint方法
public void paint(Graphics obj)
{
// I can see you're trying to double buffer the graphics, but I would have a
// buffer already set up...
buffer = createImage(640,400);
// You should NEVER dispose of Graphics context you didn't created...
if (obj != null)
obj.dispose();

// Now we're really stuffed. You've just overridden the screen graphics context
obj = buffer.getGraphics();
obj.setColor(getBackground());
//update
previouslocation = new Point(currentlocation);
currentlocation = nextlocation;

//draw
obj.fillRect(currentlocation.x, currentlocation.y, size, size);
obj.setColor(Color.black);
obj.drawOval(nextlocation.x, nextlocation.y, size, size);
obj.fillOval(nextlocation.x, nextlocation.y, size, size);
/*
*draw rectangles out of vector
*/
// Now you drawing the buffer onto itself...???
obj.drawImage(buffer, 0,0, null);
}

回顾你的代码,我发现你正在添加一个 Ball组件到您的主要绘画区域,并且您正在使用 null此油漆区域的布局。

如果丢弃布局管理器,则需要接管对子组件布局的控制...

你需要离开画 Ball ...所以在您的 Ball类,您需要覆盖 paint方法...
public void paint(Graphics g) {
super.paint(g);
g.setColor(Color.black);
g.drawOval(0, 0, size, size);
}

在您的 Ball#move方法,你需要更新球的位置...
public void move() {
// You've previous move code
setBounds(dx, dy, size, size);
}

这会让你绘画工作......或多或少......

但是,我建议您放弃 AWT 并改用 Swing 组件,如果没有其他原因,它们是双缓冲的。

你看一看
  • Creating a GUI With JFC/Swing
  • Performing Custom Painting
  • 2D Graphics

  • 你也可以看看
  • Java Bouncing Ball
  • the images are not loading

  • 对于一些例子;)

    关于java - 在线程中使用 Canvas 对象做简单的动画 - Java,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13132491/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com