4

Java を使用して Tic-Tac-Toe ゲームを作成しています。今のところ、ボタンをクリックするJButtonと から削除されJPanelJLabelX または O の画像を含む が追加され、JPanelが再描画されます。ただし、ボタンをクリックすると、画像は表示されませんが、ボタンは消えます。

ボタンと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();
}
}

問題の写真

4

2 に答える 2

3

revalidate();次にrepaint();、次JPanelのように s インスタンスで呼び出してみてください。

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

Componentが追加または削除された場合、この呼び出しを呼び出す必要があります。これは、新しいリストに基づいて にリセットrevalidate()するように指示する命令です。コンポーネントが「ダーティ領域」と見なすものへの呼び出しをトリガーします。明らかに、すべての領域がによってダーティと見なされるわけではありません。LayoutManagerComponentrevalidate()repaint()JPanelRepaintManager

repaint()コンポーネントに自分自身を再描画するように指示するために使用されます。あなたのような条件をクリーンアップするために、これを呼び出す必要がある場合がよくあります。

于 2012-08-02T18:55:48.397 に答える
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 の応答が遅くなります。(Runnable オブジェクトは、外部からのみ最終的な変数にアクセスできます。つまり、割り当てられなくなった変数です。)

コンポーネントにJLabelは、親コンポーネント用の単一のフィールドがあります。したがって、1 つのコンポーネントを再利用することはできません。したがって、new JLabel().

塗り直しについて; 常に最初に自分でトリガーせずに試してください。

于 2012-08-02T19:07:07.017 に答える