2012-10-30 26 views
2

我有一個小程序,像現在寫的,應該繪畫和「運行」按鈕後,蹦跳着頂部的球(drawingpanel代碼)時。在線查看其他示例並使用來自不使用Canvas的其他程序的代碼,我無法弄清楚爲什麼我的Ball對象沒有顯示出來。我已經測試了程序的流程,並且所有的方法都應該被調用,所以不是代碼不符合paint方法的情況。任何有關使用Canvas/Thread的好資源都會很棒,或者關於下面的applet的任何建議都會非常有用。謝謝!在一個線程中使用Canvas對象做簡單的動畫 - Java的

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); 
    } 
} 

回答

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組件替代,如果沒有其他原因,他們是雙緩衝。

你把通過

看看你也可以看看

對於一些例子;)

+0

好了哈哈我想通有很多的錯誤,感謝逐點去點。我對Ball類進行了更改,並更新(以前的繪畫),並在Ball中添加了您的建議塗裝方法。它確實有用,有點兒;球是不固體的,並且以一個像素的自由空間在一個小矩形內反彈。 – zakparks31191

+0

是的,那就是我要去的地方,我認爲你在球的移動範圍內使用的計算方法是錯誤的,但我認爲我會把它留給你;)。你可以將'paint'方法中的'g.drawOval(0,0,size,size)'調用改爲'g.fillOval(0,0,size,size);'替換它來代替 – MadProgrammer

+0

haha​​ ok是一個非常簡單的修復。奇怪的是,移動球的計算與另一個不使用畫布的類似程序相同。我將不得不重寫那個... – zakparks31191