2012-08-02 77 views
4

我使用Java創建井字遊戲遊戲。現在,當你點擊一個按鈕時,JButton將被從JPanel中刪除,包含X或O圖像的JLabel將被添加,並且JPanel將被重新繪製。但是,當我點擊按鈕時,圖像不會顯示,但按鈕消失。按鈕的JLabel將不會顯示圖像

創造與JLabel/Image

package tictactoe; 
import javax.swing.*; 
import java.awt.*; 
import java.awt.event.*; 
import javax.swing.ImageIcon; 

public class TicTacToe implements ActionListener 
{ 
private JFrame holder = new JFrame(); 
private GridLayout layout = new GridLayout(3,3); 
private FlowLayout panel = new FlowLayout(FlowLayout.CENTER); 
private JPanel p11, p12, p13, p21, p22, p23, p31, p32, p33; 
private JButton b1, b2, b3, b4, b5, b6, b7, b8, b9; 
private ImageIcon iconX = new ImageIcon("iconX.png"); 
private JLabel xLabel = new JLabel(iconX); 
private ImageIcon iconO = new ImageIcon("iconO.png"); 
private JLabel oLabel = new JLabel(iconO); 
private int turn; 
private char s1, s2, s3, s4, s5, s6, s7, s8, s9; 

public TicTacToe() 
{ 
    paint(); 
} 

private void paint() 
{ 
    holder.setLayout(layout); 
    holder.setSize(300,300); 

    b1 = new JButton("1"); 
    p11 = new JPanel(); 
    p11.setLayout(panel); 
    p11.add(b1); 
    holder.add(p11); 

    //Same block of code for the next 8 buttons/panels inserted here 

    holder.setVisible(true); 

    b1.addActionListener(this); 
    //Other action listeners inserted here 

} 
@Override 
public void actionPerformed(ActionEvent e) 
{ 
    if (e.getSource() == b1) 
    { 
     ++turn; 
     p11.remove(b1); 
     if (turn % 2 == 1) { s1 = 'x'; p11.add(xLabel); } 
     else if (turn % 2 == 0) { s1 = 'o'; p11.add(oLabel); } 
     p11.repaint(); 
    } 
    //Other action events inserted here 
} 
public static void main(String[] args) 
{ 
    TicTacToe game = new TicTacToe(); 
} 
} 

Picture of the problem

回答

3

嘗試調用revalidate();然後repaint();JPanel小號實例是這樣的:

 p11.revalidate(); 
     p11.repaint(); 

Component是添加或刪除它是ne子母線呼叫revalidate()此呼叫是根據新的Component列表來指示LayoutManager重置。 revalidate()將引發repaint()的調用,該組件認爲是「髒區域」。很明顯,JPanel上的所有區域都不被RepaintManager認爲是髒的。

repaint()用於指示組件重新繪製自己。通常情況下,您需要調用它來清理諸如您的條件。

+2

如果你也解釋了爲什麼這種方法可行,這可能會很有用。 – mre 2012-08-02 19:00:35

+1

@mre謝謝你加:) – 2012-08-02 19:07:03

1
@Override 
public void actionPerformed(final ActionEvent e) 
{ 
    SwingUtilities.invokeLater(new Runnable() { 
     @Override 
     public void run() { 
      if (e.getSource() == b1) { 
       ++turn; 
       p11.remove(b1); 
       if (turn % 2 == 1) { s1 = 'x'; p11.add(new JLabel(iconX)); } 
       else { s1 = 'o'; p11.add(new JLabel(iconO)); } 
       //p11.revalidate(); 
       //p11.repaint(); 
      } 
      **Other action events inserted here 
     } 
    }); 
} 

的invokeLater建設是一個有點吃不消了語法,但讓事件處理線程處理按鈕點擊,並做的修改。否則,你不能依靠立即重新繪製,gui變得不太敏感。 (可運行對象只能訪問從外部最終變量,即:它不再被分配給變量)

組件等JLabel具有單個場爲他們的父組件。因此不能重用一個組件。因此new JLabel()

關於重新粉刷;總是先嚐試一下,不要自己觸發它。