2014-05-13 38 views
-1

我正在努力嘗試在頁面中間使用矩形車輛對象的圖形用戶界面關於車輛兩側的x座標和兩個矩形對象。paintComponent和重繪方法不適用於我的JPanel,Graphics2D

我擴展了一個JPanel,所以我調用repaint在run方法中調用paintComponent方法,但我甚至沒有輸入paintComponent方法。另外,因爲我正在使用Graphics2D,所以我需要做不同的事情嗎?

import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.geom.Path2D; 
import java.awt.geom.Rectangle2D; 

import javax.swing.JFrame; 
import javax.swing.JPanel; 

public class Display extends JPanel implements Runnable{ 
    public static final int frameWidth=1300; 
    public static final int frameHeight=800; 
    public double score; 
    public double updateTimeInterval=25; 
    public double prevUpdatedTime=0; 

public Display(){ 
    JFrame frame = new JFrame(); 
    frame.setSize(frameWidth, frameHeight); 
    frame.setTitle("You are playing HoverTeam!!!"); 
    frame.setVisible(true); 
    JPanel panel = new JPanel(); 
    frame.getContentPane().add(panel); 
    System.out.println("completed constructor."); 
} 
public void paintComponent(Graphics g){ 
    System.out.println("currently painting."); 
    Graphics2D g2 = (Graphics2D) g; 
    /* 
    * Testing with random GameState 
    */ 
    double[] pos = {28,6,Math.PI/8}; 
    double[] vel = {5,5,0}; 
    int[] nearList = {4,8,7,5}; 
    GameState gs = new GameState(pos,vel,2,2,nearList,3); 
    //GameState gs = GameClient.getGameState(); 
    /* 
    * Drawing the vehicle in the center of the screen with regards to the x-coordinate and then referencing the walls to it. 
    */ 
    Path2D.Double vehic = gs.getVehicleShapePath(frameWidth/2, gs.getPosition()[1]); 
    g2.draw(vehic); 
    int[] nearObstHeights = gs.getNearObstList(); 
    double vehiclePast = gs.getPosition()[0]%5; //distance that the vehicle is past the second obstacle--reference to where to draw obstacles 
    for (int i =0; i<nearObstHeights.length;i++){ 
     Rectangle2D.Double obstacle = new Rectangle2D.Double(frameWidth/2 -vehiclePast+5*(i-1),nearObstHeights[i],1,nearObstHeights[i]); 
     g2.draw(obstacle); 
    } 
    score = gs.getPosition()[0]/5; 
    g.drawString("Score:"+score, frameWidth/2, frameHeight-10); 

} 
public void run(){ 
    /* 
    * No maximum score, game goes on forever. 
    */ 

    System.out.println("entereed run method."); 
    while (true){ 
     long currentTime = System.currentTimeMillis(); 
     if (currentTime-prevUpdatedTime>updateTimeInterval){ 
      System.out.println("entered if statement"); 
      prevUpdatedTime = currentTime; 
      repaint(); 
      System.out.println("should have just repainted."); 
     } 
    } 

} 
public static void main(String[] args){ 
    (new Thread(new Display())).start(); 
} 

}

感謝

+1

你認爲你在哪裏實例化一個將使用'paintComponent'(即它在GUI中顯示)的對象'Display'? – DSquare

+0

是的,您正在向JFrame中添加一些普通的JPanel,並且不會將Display類的任何對象添加到顯示的任何對象中。另外,另一方面,你的paintComponent方法看起來很危險,因爲你看起來在這個方法中有代碼邏輯,它改變了你的類的狀態,而這不應該是。 –

+0

我想通過在main方法中調用(new Thread(new Display()))。start()我將調用Display對象的run方法,當我在run方法中調用repaint時,它將調用paintComponent。 – user3014093

回答

0

您的代碼非常混亂,每個對象都有掌握自己的responsabilities而已照顧。特別是:

  • 顯示是一個JPanel ...也是一個Runnable?這是爲什麼?你可以有一個可運行的GUI(仔細地)工作,但它不應該是GUI本身。
  • 顯示是一個JPanel,但其構造函數正在做各種事情,如創建一個框架。 Display的構造函數只需要處理構造的JPanel。創建您自己的類MyApplication,完成所有工作,或者創建一個靜態方法createAndShowGUI(),並從您的main中調用它。
  • 你爲什麼要在主體中創建一個線程?或者說,爲什麼創建

相同statment然後,你必須在你的代碼的一些問題:

  • 你幾乎certianly做的第一件事你paintComponent呼籲super.paintComponent(g)
  • 您應該瞭解事件派發線程是什麼。看看如何設置initial threads in Swing。總之,你必須在你的主要電話invokeLater並擺脫new Thread()。然而,你組織你的代碼,不要在EDT中執行那個可運行的代碼,它有一個無限循環,GUI會凍結。
  • 您從未在您的框架中放置任何Display對象。創建GUI的代碼應該是這樣的:

//we create the GUI here, this is called by main inside the runnable of `invokeLater`. 
public static creteAndShowGUI(){ 
    JFrame frame = new JFrame(); 
    frame.setSize(frameWidth, frameHeight); 
    frame.setTitle("You are playing HoverTeam!!!"); 


    //JPanel panel = new JPanel(); //this is an empty panel, you want the Display subclass that you created. 

    //we use the Display panel that will use the `paintComponent` to paint itself 
    Display panel = new Display(); 

    frame.getContentPane().add(panel); 
    System.out.println("completed constructor."); 

    frame.setVisible(true); 
} 

你並不需要一個可運行在所有的,必要時由它自己的GUI被粉刷一新。如果您使用代碼進行更改,則只需調用repaint()。

編輯:按你的意見,我會澄清一些什麼repaint()確實是計劃的對象的重畫屏幕,這一過程包括,在某些時候,調用paintComponent。但是,如果對象不在屏幕中,請致電repaint()。您的電話repaint()或者更確切地說this.repaint()正在重繪您在main中創建的對象new Display()(並且是new Thread()的參數,但是您不會將該對象添加到任何幀,它不在GUI中,因此在屏幕上沒有任何重新繪製。

相關問題