2013-05-15 102 views
1

我有一个GUI类GUI:GUI线程更新问题

public class Gui extends JFrame implements Runnable 
{ 

private JPanel outer, inner; 
private JLabel[][] labels = new JLabel[22][12]; 
private Color[][] defaultMap, map; 
Thread t; 
private int row, col; 
private Color color; 

public Gui() 
{ 
    Container content = getContentPane(); 
    content.setLayout(new BorderLayout()); 

    setBackground(Color.BLACK); 
    setSize(1000, 1000); 
    setLocation(300, 0); 
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    setResizable(false); 

    defaultMap = createMap(); 
    draw(defaultMap); 
} 

public Color[][] createMap() 
{ 
    Color[][] map = new Color[22][12]; 
    for (int i = 0; i < 22; i++) 
    { 
     for (int j = 0; j < 12; j++) 
     { 
      map[i][j] = Color.WHITE; 
     } 
    } 
    for (int i = 0; i < 22; i++) 
    { 
     map[i][0] = Color.GRAY; 
     map[i][11] = Color.GRAY; 
    } 
    for (int i = 0; i < 12; i++) 
    { 
     map[0][i] = Color.GRAY; 
     map[21][i] = Color.GRAY; 
    } 
    return map; 
} 

public void draw(Color[][] map) 
{ 

    outer = new JPanel(); 
    outer.setLayout(new BorderLayout()); 
    outer.setBackground(Color.WHITE); 
    outer.setPreferredSize(new Dimension()); 

    inner = new JPanel(); 
    inner.setLayout(new GridLayout(22, 12, 2, 2)); 
    inner.setBackground(Color.BLACK); 

    for (int i = 0; i < 22; i++) 
    { 
     for (int j = 0; j < 12; j++) 
     { 
      labels[i][j] = new JLabel(); 
      JLabel label = labels[i][j]; 
      label.setPreferredSize(new Dimension(20, 20)); 
      label.setBackground(map[i][j]); 
      label.setOpaque(true); 
      inner.add(label); 
     } 
    } 

    add(outer); 
    add(inner); 
    pack(); 
} 

public void move(int row, int col, Color color) 
{ 
    System.out.println(row+","+col); 
    map = defaultMap; 
    map[row][col] = color; 
    t = new Thread(this); 
    t.start(); 
} 

@Override 
public void run() 
{ 
    draw(map); 
} 
} 

这是从我的主类称为像这样:

public static void main(String[] args) 
{ 
    SwingUtilities.invokeLater(new Runnable() 
    { 
     @Override 
     public void run() 
     { 
      try 
      { 
       gui = new Gui(); 
       gui.setVisible(true); 
       gui.move(2,5,Color.GREEN); 
       Thread.sleep(1000); 
       gui.move(3,5,Color.GREEN); 
       Thread.sleep(1000); 
       gui.move(4,5,Color.GREEN); 
      } catch (InterruptedException ex) 
      { 
       Logger.getLogger(Tetris.class.getName()).log(Level.SEVERE, null, ex); 
      } 
     } 
    }); 
} 

所以怪异的东西正在发生的事情时,gui.move( )函数被调用。您可以忽略其余部分或在有帮助时使用它。但是,每次在2,5应该“添加”一个绿色块, 3,5;和4,5; 1秒后,另一个。

问题:

桂一段时间保持为黑色,然后立即重绘/更新与适当的网格和颜色与前两个块正确地显示为绿色,但它缺少最后一块在4,5。同样,初始的“defaultMap”应该立即被绘制,但不是,JFrame是黑色的,直到所有东西都被一起绘制在一起减去最后一个绿色块。然后每个绿色块应该在另一个之后1秒内涂上。

有趣的部分是,Gui中移动方法中的System.out.println()位打印出行和列,正如我所期望的那样...他们在出现约一秒之后出现终点站。所以这告诉我有什么事情是正确的。但我不知道桂的情况如何...

编辑:故事中的细微差异。经仔细检查,我注意到最后一个绿色区块在整个地图绘制后立即出现一秒钟,但立即“消失”重新涂上白色。

+1

1)为了更好地提供帮助,请发布[SSCCE](http://sscce.org/)。 2)不要延长框架或其他顶层容器。而是创建并使用一个实例。 3)不要设置顶级容器的大小。而是布置内容并调用'pack()'。 4)对于帧定位,你不能通过'setLocationByPlatform(true)'去。查看[这个答案](http://stackoverflow.com/a/7143398/418556)进行演示。 –

回答

6

您正在EDT(Event Dispatching Thread)上睡觉。你不应该阻止美国东部时间。

  • (使用ExecutorsSwingWorker
  • 对于UI的重复或延迟更新,一定不要调用sleepwait在EDT
  • 移动所有长时间运行的任务分派给其他线程,你可以使用javax.swing.Timer
  • 所有UI操作应在EDT上执行(使用SwingUtilities.invokeLaterjavax.swing.TimerSwingWorker

了解关于swing tag wiki中Swing并发性的更多信息。