正确更新swing组件?(Updating swing components correctly?)

2019-07-05 06:03发布

我是新来的摆动,任何帮助表示赞赏。

在这段代码,我在脸上了转动卡,如果事实证明,它们不匹配我希望他们回头再朝下。

目前正在发生的事情:1,点击时的第一张牌翻转2.当第二个卡被点击以下两种事情发生(一)如果他们是他们都熬到这就是我想要的是相同的(b)如他们是不一样的我从来没有看到第二个卡,就好象它立即重新显示卡的背面(也为我的方法定义的前面卡的背面)。

我以为在睡眠定时器将可能保持一段时间显示在第二个卡在扭转之前,但事实并非如此。

我试图使用contentPane.revalidate(); &contentPane.repaint(); 但它不会改变任何东西。

我已经把一些控制台输出:

Console output:
Card: 0 set
Card: 6 set
Sleeping now
Card: 6 unset
Card: 0 unset

以上是导致控制台输出点击两张牌不匹配时

@Override
public void actionPerformed(ActionEvent e) 
{
    String buttonPressed = e.getActionCommand();
    int pos = Integer.valueOf(buttonPressed);
    action = Control.model.ReceiveCardsTurned(pos);

    keypadArray[pos].setIcon(myIcons[pos]);     
    System.out.println("Card: "+pos+" set");
    currentTime.setText("" + Control.model.time);
    currentScore.setText("" + Control.model.score);

    //contentPane.revalidate();
    //contentPane.repaint();        

    if(Control.model.twoCardsTurned == false)
    {
        if (action == "unturn") 
        {
            System.out.println("Sleeping now");

            try 
            {
                Thread.sleep(1000);
            }

            catch (InterruptedException e1) 
            {
                e1.printStackTrace();
            }

            keypadArray[pos].setIcon(back);
            keypadArray[Control.model.lastCard].setIcon(back);
            System.out.println("Card: "+pos+" unset");
            System.out.println("Card: "+Control.model.lastCard+" unset");
        }
    }
}

Answer 1:

有一些重要的概念,你似乎丢失。

  1. Swing是一个事件驱动环境。 这意味着,有没有办法(或至少只有极少数的),您可以“等待”用户输入,通常情况下,你只需要到它们的交互反应。
  2. 摆动是由一个单一的线程,被称为事件调度线程(AKA EDT)驱动。 正是这种线程进入应用程序到应用程序,使他们能够采取行动的适当部位调度/处理事件的责任。
  3. 重绘经理职位的更新请求到EDT。

你把从开展这项工作停止EDT任何动作会让你的应用程序看起来像它的悬挂。

你绝不能进行任何耗时的操作(如I / O,循环或Thread#sleep例如)在美国东部时间,这样做将会使你的应用程序“暂停”,这是从来没有漂亮。

有一个通读并发Swing中获取更多信息。

现在,你有多种选择。 你可以使用一个Thread在后台“等待”,然后打开卡背面或者你可以使用SwingWorkerjavax.swing.Timer

你有,另一个问题是,你不应该在任何更新任何UI组件Thread比其他EDT。 这意味着,如果你使用一个Thread ,你将成为负责重新同步与EDT该线程。 虽然并不难,它只是变得混乱。

SwingWorkerjavax.swing.Timer具有的功能,使这个容易得多。

线程和SwingWorker是伟大的进行后台处理,并会仅仅是矫枉过正了这个问题。 相反, javax.swing.Timer会伏贴在这里。

if (!Control.model.twoCardsTurned)
    {
        if ("unturn".equals(action)) 
        {
            new Timer(1000, new ActionListener() {
                public void actionPerformed(ActionEvent evt) {
                    keypadArray[pos].setIcon(back);
                    keypadArray[Control.model.lastCard].setIcon(back);
                    System.out.println("Card: "+pos+" unset");
                    System.out.println("Card: "+Control.model.lastCard+" unset");
                }
            }).start();
        }
    }

这是一个非常简单的例子。 你可能会喜欢把一些控件,这将阻止用户点击任何东西,直到计时器火灾,例如;)



Answer 2:

你不能在事件调度线程睡觉,因为你的GUI将冻结。 你必须使用Swing的计时器 。 对于后台任务,你可能会在将来发愁,看看SwingWorker的 。



文章来源: Updating swing components correctly?