我有一个小程序,正如现在所写的那样,应该在按下“运行”按钮后在顶部(代码中的drawingpanel
)上绘制并弹出一个球。在线查看其他示例并使用不使用Canvas的其他程序中的代码,我无法弄清楚为什么我的Ball对象没有显示出来。我已经测试了程序的流程,并且所有的方法都按照它们应该被调用,因此不是代码没有进入paint
方法的情况。使用Canvas / Thread的任何好资源都会很棒,或者对以下applet的任何建议都会很有用。谢谢!
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);
}
}
答案 0 :(得分:3)
说实话,我不知道从哪里开始。
这是一个坏主意。
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组件,如果没有其他原因,它们会被双重缓冲。
你看看
您还可以查看
对于某些例子;)