我正在使用Java创建一个Tic-Tac-Toe游戏。现在,我点击按钮,JButton
将从JPanel
中移除,将添加包含X或O图像的JLabel
,以及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();
}
}
答案 0 :(得分:3)
尝试在您的revalidate();
实例上调用repaint();
然后JPanel
,如下所示:
p11.revalidate();
p11.repaint();
添加或删除Component
时,必须致电revalidate()
此调用是指示LayoutManager
根据新的Component
列表重置的说明。 revalidate()
将触发对repaint()
组件认为“脏区”的调用。显然,JPanel
并未将RepaintManager
上的所有区域视为脏。
repaint()
用于告诉组件重绘自己。通常情况下,您需要调用此方法来清理诸如您的条件。
答案 1 :(得分: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
等组件的父组件只有一个字段。因此,不能重用一个组件。因此new JLabel()
。
关于重新涂漆;总是先尝试一下,不要自己触发它。