【问题标题】:Refreshing a JFrame while in an Action Listener在动作侦听器中刷新 JFrame
【发布时间】:2013-08-30 18:21:39
【问题描述】:

下面的代码 sn-p 在 JLabel 中设置文本,该 JLabel 添加到 JPanel,该 JPanel 附加到 JFrame。不管我做什么(例如 repaint()、revalidate() 等),在 Action Listener 完成之前,我都无法让 UI 更新文本。

我以前从来没有遇到过这个问题,这可能是因为我从来没有在一次触发 Action Listener 时发生几件事情。我错过了什么?

TL;DR 为什么在完成触发动作侦听器之前,即使我在每个 listPanel.add() 之后都添加了 repaint(),以下内容也不会更新屏幕上的文本?

final JFrame guiFrame = new JFrame();
final JPanel listPanel = new JPanel();
listPanel.setVisible(true);
final JLabel listLbl = new JLabel("Welcome");
listPanel.add(listLbl);

startStopButton.addActionListener(new ActionListener(){@Override public void         actionPerformed(ActionEvent event){
     if(startStopButton.getText()=="Start"){
                startStopButton.setVisible(false);
                listPanel.remove(0);

     JLabel listLbl2 = new JLabel("Could not contact”);
                listPanel.add(listLbl2);

     JLabel listLbl2 = new JLabel("Success”);
                listPanel.add(listLbl2);
     }
}
guiFrame.setResizable(false);
guiFrame.add(listPanel, BorderLayout.LINE_START);
guiFrame.add(startStopButton, BorderLayout.PAGE_END);

//make sure the JFrame is visible
guiFrame.setVisible(true);

编辑: 我试图实现 SwingWorker,但在操作接口完成触发之前,接口仍然没有更新。这是我的 SwingWorker 代码:

@Override
protected Integer doInBackground() throws Exception{
    //Downloads and unzips the first video.  
    if(cameraBoolean==true)
        panel.add(this.downloadRecording(camera, recording));
    else
        panel.add(new JLabel("Could not contact camera "+camera.getName()));

    panel.repaint();
    jframe.repaint();
    return 1;
}

private JLabel downloadRecording(Camera camera, Recording recording){
    //does a bunch of calculations and returns a jLabel, and works correctly
}

protected void done(){
    try{
        Date currentTime = new Timestamp(Calendar.getInstance().getTime().getTime());
        JOptionPane.showMessageDialog(jframe, "Camera "+camera.getName()+" finished downloading at "+currentTime.getTime());
    }catch (Exception e){
        e.printStackTrace();
    }
}

基本上,SwingWorker(正如我实现的那样)没有正确更新 JPanel 和 JFrame。如果我尝试在“done()”中进行重绘,它们也不会更新。我错过了什么?

此外,一旦 JOptionPane 显示出来,就不能再向我的 jframe 添加面板了。我也不确定是什么原因造成的。

【问题讨论】:

  • 您要更新什么文本? startStopButton 还是两个 JLabel 之一?
  • 我希望尽快以图形方式添加标签(我去掉了在创建标签之前必须进行的一系列处理,用户现在需要知道发生了什么) .
  • 尝试离开 remove() 方法和 setVisible() 来检查 JLabels 是否会出现,尽管按钮仍然可见。或者您可以尝试先添加所有内容,将两个 JLabel 设置为不可见,然后不要从按钮添加它们,将它们设置为可见并重新绘制()。
  • 按钮可见性没有改变。此外,我不能无形地添加所有内容,因为这是动态代码(它必须处理最初未知数量的变量并从中创建输出)。不过感谢您的建议。

标签: java swing actionlistener repaint


【解决方案1】:

动作监听器正在Event Dispatch Thread 上执行。对于此类任务,请考虑使用SwingWorker

这将允许您在不阻塞 JFrame 的更新(以及重绘)的情况下处理您的逻辑。

在高层次上,这就是我的意思:

startStopButton.addActionListener(new ActionListener(){@Override public void         actionPerformed(ActionEvent event){
     if(startStopButton.getText()=="Start"){
          // Start SwingWorker to perform whatever is supposed to happen here.
     }

您可以找到一些有关如何使用SwingWorker here 的信息,如果您需要的话。

【讨论】:

  • 嗯。看起来很有希望。基本上我会从我的 Action Listener 中调用一个 SwingWorker 方法,SwingWorker 会做所有的处理,然后将控制权返回给 Action Listener 以完成触发?
  • 您不一定需要交还控制权。由于 Swing Worker 将在单独的线程中运行,所有侦听器所要做的就是启动进程并让它流动。
  • 监听线程会在每个工作线程计算时等待,还是会启动所有工作线程(不考虑一个先完成)。我问所以我知道如何设计我的工人
  • 侦听器的活动发生在 EDT(事件调度线程)上。 worker 将在单独的线程中进行,但能够通过回调机制与 EDT 通信。在我之前提出的一个问题中,我很好地解释了这一点 - 看看是否有任何信息可以帮助你 here。澄清一下 - EDT 不会在工作线程上等待。这就是使用它的意义所在。
  • 这很有帮助,感谢您的解释和链接。我试试看。
猜你喜欢
  • 1970-01-01
  • 2013-03-27
  • 2016-08-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多