2012-04-20 44 views
3

這是我當前的RectangleComponent類,我將它添加到我的主JFrame中的面板,但它從不出現。我認爲它沒有繪製,所以我決定在Rectangle的構造函數中調用paintComponent方法,在對4-5 nullPointerExceptions進行排序後,沒有任何變化。我已經閱讀了關於如何繪製矩形的多個指南,並且我已經看到了多個代碼示例,但是我無法讓面板與多個JComponent一起工作。如果可以的話,請簡單看看我的代碼,看看你能否設計一個解決方案。 謝謝你的時間。還列出了我所說的矩形構造框架。在Java中創建矩形時,我實際上調用了paintComponent方法嗎?

public class GameFrame extends JFrame 
{ 
    private SpellBarComponent bar; 
    private JPanel mainPanel = new JPanel(); 
    private JPanel buttonPanel = new JPanel(); 
    private JPanel healthPanel = new JPanel(); 
    Color green = new Color(29, 180, 29); 
    Color red = new Color(255, 0, 0); 
    private RectangleComponent life; 
    private RectangleComponent death; 
    private JFrame frame = new JFrame(); 

    public GameFrame(char x) 
    { 
     frame.setSize(1024, 768); 
     frame.setTitle("Game"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setVisible(true); 
     FlowLayout layout = new FlowLayout(); 
     createPanels(x); 
     healthPanel.setLayout(layout); 
     buttonPanel.setLayout(layout); 
     mainPanel.setLayout(layout); 
     frame.getContentPane().add(mainPanel); 
     frame.pack(); 
     repaint(); 
    } 

    public RectangleComponent getLife() 
    { 
     return life; 
    } 

    private void createHealth() 
    { 
     life = new RectangleComponent(green, healthPanel); 
     death = new RectangleComponent(red, healthPanel); 
    } 

    private void createPanels(char x) 
    { 
     add(healthPanel); 
     pack(); 
     createBar(x); 
     createHealth(); 
     mainPanel.add(buttonPanel); 
     mainPanel.add(healthPanel); 
     healthPanel.add(death); 
     healthPanel.add(life); 
     buttonPanel.add(bar.getSpell1()); 
     buttonPanel.add(bar.getSpell2()); 
     buttonPanel.add(bar.getSpell3()); 
     add(mainPanel); 
    } 

    private void createBar(char x) 
    { 
     bar = new SpellBarComponent(x, mainPanel); 
    } 
} 


public class RectangleComponent extends JComponent 
{ 
    Color color; 
    int width; 
    int height = 18; 
    RoundRectangle2D roundedRectangle; 
    private JPanel panel; 
    public RectangleComponent(Color color, JPanel panel) 
    { 
     this.panel = panel; 
     this.color = color; 
     paintComponent(panel.getGraphics()); 
    } 

    public void paintComponent(Graphics g) 
    { 
     Graphics2D graphics2 = (Graphics2D) g; 
     width = 125; 
     roundedRectangle = new RoundRectangle2D.Float(10, 10, width, height, 10, 10); 
     graphics2.setPaint(color); 
     graphics2.fill(roundedRectangle); 
     graphics2.draw(roundedRectangle); 
    } 

    public void subtractLife(int amount) 
    { 
     width -= amount; 
     roundedRectangle.setRoundRect(10, 10, width, height, 10, 10); 
     repaint(); 
    } 
} 
+0

你可以顯示你實際將RectangleComponent添加到任何東西的位置,因爲我在上面的文章中看不到這段代碼嗎?另外,你不應該直接調用'paintComponent(...)'或者'paint(...)。你可以在組件或容器層次結構中的容器上調用repaint(),這會建議JVM開始一個繪製週期,但是你不要直接自己做。 – 2012-04-20 02:36:34

+0

@HovercraftFullOfEels - 在'GameFrame'構造函數調用的'createPanels()'中添加RectangleComponent字段'life'和'death'。它們在'createHealth()'中創建,從'createPanels()' – 2012-04-20 03:10:41

回答

3

爲了讓您的Swing應用程序按預期工作,您需要記住許多事項。爲避免可能出現的某些障礙,總會有一些步驟必須遵循,因爲您以錯誤的方式編碼。爲此,嚴格遵守Swing編程的基礎知識,並遵循它們。

  • 通過@HovercraftFullOfEels提到喜歡,你叫你的 圖形直接,哪一個不應該做的。

  • 其次,看你的GameFrame()構造,可以將其設置爲 可見,你又增加了,甚至之前,它和任何組件多 之前它的真實大小已經建立

這樣的循環孔內你的編碼可能會引起許多令人頭疼的問題,當你坐下來編寫大型節目時,最好是從一開始就安全的路上,然後在後期詛咒自己。正如他們所說的預防勝於治療。

由於未能指定CustomComponent的大小(即JComponent),因此您無法在屏幕上看到它,現在即將到達您的程序中,您錯過了主要的東西。當您將JCompoent擴展到您的班級時,請將其設爲習慣性習慣來覆蓋它的getPreferredSize(),方法與覆蓋方法相同。

看看這個我爲你製作的小程序,可能會幫助你理解邏輯。

import java.awt.*; 
import java.awt.event.*; 
import java.awt.geom.RoundRectangle2D; 
import javax.swing.*; 

public class CustomPainting { 

    private RectangleComponent life; 
    private RectangleComponent death; 

    private void createAndDisplayGUI() { 
     JFrame frame = new JFrame("Custom Painting"); 
     frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 

     JPanel centerPanel = new JPanel(); 
     centerPanel.setLayout(new GridLayout(0, 2, 5, 5)); 
     // Specifying the WIDTH, HEIGHT and Colour for this JComponent. 
     life = new RectangleComponent(Color.GREEN.darker(), 20, 20); 
     death = new RectangleComponent(Color.RED.darker(), 20, 20); 
     centerPanel.add(life); 
     centerPanel.add(death); 

     JPanel buttonPanel = new JPanel(); 
     buttonPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 5)); 
     JButton incLifeButton = new JButton("INCREASE LIFE"); 
     incLifeButton.addActionListener(new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent ae) { 
       life.addLife(1); 
      } 
     }); 

     JButton decLifeButton = new JButton("DECREASE LIFE"); 
     decLifeButton.addActionListener(new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent ae) { 
       life.subtractLife(1); 
      } 
     }); 

     JButton incDeathButton = new JButton("INCREASE DEATH"); 
     incDeathButton.addActionListener(new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent ae) { 
       death.addLife(1); 
      } 
     }); 

     JButton decDeathButton = new JButton("DECREASE DEATH"); 
     decDeathButton.addActionListener(new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent ae) { 
       death.subtractLife(1); 
      } 
     }); 

     buttonPanel.add(incLifeButton); 
     buttonPanel.add(decLifeButton); 
     buttonPanel.add(incDeathButton); 
     buttonPanel.add(decDeathButton); 

     frame.getContentPane().add(centerPanel, BorderLayout.CENTER); 
     frame.getContentPane().add(buttonPanel, BorderLayout.PAGE_END); 
     frame.pack(); 
     frame.setLocationByPlatform(true); 
     frame.setVisible(true); 
    } 

    public static void main(String\u005B\u005D args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       new CustomPainting().createAndDisplayGUI(); 
      } 
     }); 
    } 
} 

class RectangleComponent extends JComponent { 

    private Color colour; 
    private static final int MARGIN = 10; 
    private int width; 
    private int height; 
    private int originalWidth; 
    private RoundRectangle2D roundedRectangle; 

    public RectangleComponent(Color c, int w, int h) { 
     colour = c; 
     width = w; 
     height = h; 
     originalWidth = width; 
    } 

    /* 
    * Overriding this method, so that 
    * the size of the JComponent 
    * can be determined, on the screen 
    * or by the LayoutManager concern. 
    */ 
    @Override 
    public Dimension getPreferredSize() { 
     return (new Dimension(width, height)); 
    } 

    @Override 
    protected void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     Graphics2D g2d = (Graphics2D) g; 
     roundedRectangle = new RoundRectangle2D.Float(MARGIN, MARGIN, 
             width, height, MARGIN, MARGIN); 
     g2d.setPaint(colour); 
     g2d.draw(roundedRectangle); 
     g2d.fill(roundedRectangle); 
    } 

    public void subtractLife(int amount) { 
     width -= amount; 
     System.out.println("ORIGINAL Width : " + originalWidth); 
     System.out.println("Width : " + width); 
     if (width > 0) { 
      roundedRectangle.setRoundRect(MARGIN, MARGIN, width, height, 
              MARGIN, MARGIN); 
      /* 
      * This repaint() will call the paintComponent(...) 
      * by itself, so nothing else to be done. 
      */ 
      repaint(); 
     } else { 
      width += amount; 
     } 
    } 

    public void addLife(int amount) { 
     width += amount; 
     System.out.println("ORIGINAL Width : " + originalWidth); 
     System.out.println("Width : " + width); 
     if (width < originalWidth) { 
      roundedRectangle.setRoundRect(MARGIN, MARGIN, width, height, 
              MARGIN, MARGIN); 
      repaint(); 
     } else { 
      width -= amount; 
     } 
    } 
} 

可能會問任何問題,可能會出現,可能與您經過這個程序:-),我很樂意幫助上:-)

**兩種顏色最新編輯:**

import java.awt.*; 
import java.awt.event.*; 
import java.awt.geom.RoundRectangle2D; 
import javax.swing.*; 

public class CustomPainting { 

    private RectangleComponent lifeDeath; 

    private void createAndDisplayGUI() { 
     JFrame frame = new JFrame("Custom Painting"); 
     frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 

     JPanel centerPanel = new JPanel(); 
     centerPanel.setLayout(new GridLayout(0, 2, 5, 5)); 
     // Specifying the WIDTH, HEIGHT and Colour for this JComponent. 
     lifeDeath = new RectangleComponent(Color.GREEN, Color.RED, 20, 20); 
     centerPanel.add(lifeDeath); 

     JPanel buttonPanel = new JPanel(); 
     buttonPanel.setLayout(new GridLayout(1, 2, 5, 5)); 
     JButton incLifeButton = new JButton("INCREASE LIFE"); 
     incLifeButton.addActionListener(new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent ae) { 
       lifeDeath.addLife(1); 
      } 
     }); 

     JButton decLifeButton = new JButton("DECREASE LIFE"); 
     decLifeButton.addActionListener(new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent ae) { 
       lifeDeath.subtractLife(1); 
      } 
     }); 

     buttonPanel.add(incLifeButton); 
     buttonPanel.add(decLifeButton); 

     frame.getContentPane().add(centerPanel, BorderLayout.CENTER); 
     frame.getContentPane().add(buttonPanel, BorderLayout.PAGE_END); 
     frame.pack(); 
     frame.setLocationByPlatform(true); 
     frame.setVisible(true); 
    } 

    public static void main(String\u005B\u005D args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       new CustomPainting().createAndDisplayGUI(); 
      } 
     }); 
    } 
} 

class RectangleComponent extends JComponent { 

    private Color lifeColour; 
    private Color deathColour; 
    private static final int MARGIN = 10; 
    private int widthLife; 
    private int widthDeath; 
    private int height; 
    private int originalWidth; 
    private RoundRectangle2D roundedRectangle; 

    public RectangleComponent(Color lc, Color dc, int w, int h) { 
     lifeColour = lc; 
     deathColour = dc; 
     widthLife = w; 
     height = h; 
     originalWidth = widthLife; 
     widthDeath = 0;  
    } 

    /* 
    * Overriding this method, so that 
    * the size of the JComponent 
    * can be determined, on the screen 
    * or by the LayoutManager concern. 
    */ 
    @Override 
    public Dimension getPreferredSize() { 
     return (new Dimension(originalWidth, height)); 
    } 

    @Override 
    protected void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     Graphics2D g2d = (Graphics2D) g; 

     roundedRectangle = new RoundRectangle2D.Float((MARGIN + widthDeath), MARGIN, 
             widthLife, height, MARGIN, MARGIN); 
     g2d.setPaint(lifeColour); 
     g2d.draw(roundedRectangle); 
     g2d.fill(roundedRectangle); 

     roundedRectangle.setRoundRect(MARGIN, MARGIN, 
             widthDeath, height, MARGIN, MARGIN); 
     g2d.setPaint(deathColour); 
     g2d.draw(roundedRectangle); 
     g2d.fill(roundedRectangle); 
    } 

    public void subtractLife(int amount) { 
     widthLife -= amount; 
     widthDeath += amount; 
     System.out.println("ORIGINAL Width : " + originalWidth); 
     System.out.println("Width Life : " + widthLife); 
     System.out.println("Width Death : " + widthDeath); 
     if (widthLife > 0 && widthDeath < originalWidth) { 
      /* 
      * This repaint() will call the paintComponent(...) 
      * by itself, so nothing else to be done. 
      */ 
      repaint(); 
     } else { 
      widthLife += amount; 
      widthDeath -= amount; 
     } 
    } 

    public void addLife(int amount) { 
     widthLife += amount; 
     widthDeath -= amount; 
     System.out.println("ORIGINAL Width : " + originalWidth); 
     System.out.println("Width Life : " + widthLife); 
     System.out.println("Width Death : " + widthDeath); 
     if (widthLife < originalWidth && widthDeath > 0) { 
      repaint(); 
     } else { 
      widthLife -= amount; 
      widthDeath += amount; 
     } 
    } 
} 
+0

我喜歡你對我的減法所作的改變,並增加生活方式,這些都是完美的!還有一件事,無論什麼時候我創建我的2個矩形,它們都是分開的,儘管它們的構造方式是相同的。我該如何做到讓死亡落後於生活,並且他們處於同一個位置? – keyert 2012-04-23 00:54:28

+0

我覺得你評論正確,因爲我對上述評論進行了編輯,你是否看到我添加的內容?謝謝。 – keyert 2012-04-23 01:26:37

+0

我錯過了新的編輯:(你的意思是說,一個在其他之上? – 2012-04-23 02:21:51

3

無需通過JPanelRectangleComponent構造只是爲了獲得Graphics,並且無需手動調用paintComponent。請參閱Painting in AWT and Swing。看看這個example,演示了一個繪製矩形的自定義組件。

+0

+1中爲TIP和相應鏈接指向源:-) – 2012-04-20 07:38:14

3

你的代碼有點創意,有點瘋狂,而且邏輯非常難以遵循。最不尋常的方面是它有兩個JFrames,一個叫做「frame」,另一個叫做GameFrame對象本身,它們都會添加組件,但其中只有一個顯示。你也有很多方法返回void(如果過度使用會增加代碼的氣味),只會增加代碼的混淆。

例如,

public GameFrame(char x) { 

    // here you set up the "frame" JFrame 
    frame.setSize(1024, 768); 
    frame.setTitle("Game"); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    frame.setVisible(true); 
    FlowLayout layout = new FlowLayout(); 
    createPanels(x); 
    healthPanel.setLayout(layout); 
    buttonPanel.setLayout(layout); 
    mainPanel.setLayout(layout); 

    // here you add content to the frame JFrame, and pack it 
    frame.getContentPane().add(mainPanel); 
    frame.pack(); 
    repaint(); // and then call repaint on the "this" JFrame? 
} 

public RectangleComponent getLife() { 
    return life; 
} 

private void createHealth() { 
    life = new RectangleComponent(green, healthPanel); 
    death = new RectangleComponent(red, healthPanel); 
} 

private void createPanels(char x) { 
    add(healthPanel); // now you add content to the "this" JFrame 
    pack(); // and pack it 
    createBar(x); 
    createHealth(); 
    mainPanel.add(buttonPanel); 
    mainPanel.add(healthPanel); // and then re-add a JPanel into a second JPanel? 
    healthPanel.add(death); 
    healthPanel.add(life); 
    buttonPanel.add(bar.getSpell1()); 
    buttonPanel.add(bar.getSpell2()); 
    buttonPanel.add(bar.getSpell3()); 
    add(mainPanel); // and then re -add the mainPanel into the "this" JFrame??? 
} 

這是非常混亂,不太可能去上班。

然後,您就試圖直接調用paintComponent並在JComponent上調用getGraphics,而這兩者都不應該這樣做。你會想通過圖形教程來看看如何正確地做到這一點。

我建議您考慮重新編寫此代碼,並首先僅使用一個JFrame,並更好地組織代碼。

+0

+1,用於從您的知識中共享的精彩部分10)10-):-) – 2012-04-20 07:37:27

+0

我不使用多個JFrame的遊戲。我有一個框架的標題屏幕,然後我有一個單獨的框架,這是實際的遊戲。我想要2幀,因爲在完成當前遊戲後,您可以從標題屏幕重新打開新遊戲。 – keyert 2012-04-22 21:32:09

+1

@keyert:這與標題scrren沒有任何關係。您不需要在上面的代碼中編寫兩個JFrame,特別是當您將兩個相同的組件對象添加到兩者時。再一次,你原來的帖子中的代碼有點精神分裂症。 – 2012-04-22 21:59:39

相關問題