2015-06-07 16 views
0

我在学习如何用java创建一个游戏循环,并且每秒钟绘制一个新的屏幕一定的时间。游戏循环工作正常,但是当我尝试用repaint()调用paint方法时,paint方法不会被调用。 这里是我的代码:如何在游戏循环中使用repaint()方法

import javax.swing.JButton; 
import javax.swing.JComponent; 
import java.awt.Graphics; 
import javax.swing.JFrame; 
import java.awt.image.*; 
import javax.swing.Icon; 
import javax.swing.ImageIcon; 
import java.awt.event.*; 
import java.awt.*; 
import javax.swing.*; 

public class mainFrame extends Thread{ 
static boolean gameIsRunning = false; 
MyCanvas2 myCanvas2 = new MyCanvas2(); 
static final int TARGET_FPS = 1; 
static int x = 10; 
static int y = 10; 
static long startTime = 0; 
static long elapsedTime = 0; 
static long waitTime = 0; 
public void createFrame(){ 
    JFrame window = new JFrame("Out from Eden"); 
    window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    window.setBounds(30, 30, 700, 500); 
    window.setVisible(true); 
    gameIsRunning = true; 
    gameStart(); 

} 

public void setGame(boolean game){ 
    gameIsRunning = game; 
} 

public void gameStart(){ 
    (new Thread(new mainFrame())).start(); 
} 


public void run(){ 
     while(gameIsRunning == true){ 
      startTime = System.nanoTime(); 
      myCanvas2.updateGame(); 
      myCanvas2.renderGame(); 
      elapsedTime = System.nanoTime() - startTime; 
      waitTime = (TARGET_FPS*10) - (elapsedTime/1000000); 

      if (waitTime < 0) { 
       waitTime = 5; 
      } 


      try { 
        Thread.sleep(waitTime); 
       } catch (Exception e) { 
        e.printStackTrace(); 
       } 

     } 
    } 
} 






class MyCanvas2 extends JPanel{ 
private static int x = 100; 
private static int y = 100; 
static int i =0; 
public void updateGame(){ 

} 

public void renderGame(){ 
    repaint(); 
    System.out.println("Hello"); 
} 


public void paint(Graphics g){ 

    Graphics2D g2 = (Graphics2D) g; 
    g.setColor(Color.blue); 
    g2.drawString("Test", x,y); 
    System.out.println("Goodbye"); 
} 

} 

你好印了很多次,但再见不会被调用,这使我相信,油漆方法不会被调用。为什么重绘方法不会更新我的绘画方法?

回答

4

你永远不会将MyCanvas2对象添加到任何东西,所以没有任何东西看起来被渲染,因此被绘制。因此,我的主要建议是,如果您想要渲染,请将MyCanvas2 JPanel添加到GUI。另外:

  • 你永远不会调用createFrame(),所以GUI(JFrame的),从未创建 - 所以请确保您调用它。
  • 您的gameStart()方法,一个MainFrame的实例方法创建一个新的 MainFrame实例,一个危险的和不必要的递归 - 不要这样做。

其他方建议和注意事项:

  • 您将要覆盖paintComponent油漆,因为这会自动给你双缓冲,因此一个平滑的动画/图形。
  • 不要忘记在你的覆盖范围内调用super的绘画方法,以免打破绘画链。所以如果你重写paintComponent方法,然后调用super paintComponent方法。
  • 调用repaint()并不能保证绘画完成,因为它只是一个建议。如果重新绘制请求叠加起来,例如由于繁重的处理或等待时间太短,则会忽略一些重新绘制请求。
  • 一般来说,您应该避免扩展Thread并改为实现Runnable,或者在这里使用Swing Timer。
  • 您将需要学习并遵循Java命名规则,以免混淆正在尝试阅读和理解程序并帮助您的其他人。

例如这里使用一个Swing计时器并做了简单的动画:

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.*; 

public class MainGui { 

    private static final int TIMER_DELAY = 100; 

    private static void createAndShowGui() { 
     // create our JPanel 
     MainGuiPanel mainPanel = new MainGuiPanel(); 
     // and create our ActionListener for the Swing Timer 
     MyTimerListener myTimerListener = new MyTimerListener(mainPanel); 

     // create a JFrame 
     JFrame frame = new JFrame("Main Gui"); 
     frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 

     // add our JPanel to it 
     frame.getContentPane().add(mainPanel); 
     frame.pack(); 
     frame.setLocationByPlatform(true); 
     frame.setVisible(true); // display the GUI 

     // create and start the Swing Timer 
     new Timer(TIMER_DELAY, myTimerListener).start(); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      createAndShowGui(); 
     } 
     }); 
    } 
} 

@SuppressWarnings("serial") 
class MainGuiPanel extends JPanel { 
    private static final int PREF_W = 700; 
    private static final int PREF_H = 500; 
    private int textX = 0; 
    private int textY = 10; 

    @Override 
    protected void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     g.setColor(Color.blue); 
     g.drawString("Test", textX, textY); 
     System.out.println("Goodbye"); 
    } 

    @Override 
    // make our GUI larger 
    public Dimension getPreferredSize() { 
     Dimension superSz = super.getPreferredSize(); 
     if (isPreferredSizeSet()) { 
     return superSz; 
     } 
     int prefW = Math.max(superSz.width, PREF_W); 
     int prefH = Math.max(superSz.height, PREF_H); 
     return new Dimension(prefW, prefH); 
    } 

    public void moveText() { 
     textX++; 
     textY++; 
     repaint(); 
    } 
} 

// ActionListener for Swing Timer that drives the game loop 
class MyTimerListener implements ActionListener { 
    private MainGuiPanel mainGuiPanel; 

    public MyTimerListener(pkg.MainGuiPanel mainGuiPanel) { 
     this.mainGuiPanel = mainGuiPanel; 
    } 

    @Override 
    // this method gets called each time the timer "ticks" 
    public void actionPerformed(ActionEvent e) { 
     // make sure our GUI is not null and is displayed 
     if (mainGuiPanel != null && mainGuiPanel.isDisplayable()) { 
     // call method to animate. 
     mainGuiPanel.moveText(); // this method calls repaint 
     } else { 
     ((Timer) e.getSource()).stop(); 
     }  
    } 
} 
+0

我将MyCanvas2对象添加到窗口,但甚至没有被调用的方法有没有输出,我想知道为什么paint方法没有被调用。 – Priyank

+0

那么,是不是因为我有太多的调用重新绘制的调用paint方法? – Priyank

+0

对不起,我不明白,错误在哪里,它在绘制方法中?我应该叫超级?我只是试图让'再见'现在显示。 – Priyank