动态更新JLabel会导致GUI失真 - 调整窗口大小

时间:2017-08-15 06:33:46

标签: java multithreading swing

我有一个GUI。 GUI是一个具有Panel [Gridbaglayout]的JFrame。这种网格布局有3个不同的组件。中间组件是一个面板[GridBagLayout],它有我正在谈论的JLabel。它还包含一个JScrollBar,我从中获取值并在用户移动栏时更新JLabel。

我用来获取值并更新JLabel的代码:

public class DrinkAdjustmentListener implements AdjustmentListener{

    @Override
    public void adjustmentValueChanged(AdjustmentEvent e) {
        drinkLabel.setText("Percentage " + e.getValue() + "%");
    }
}

我理解在为Android编码时,主线程也是UI线程。使用Swing我不相信这种情况,我不确定如何正确更新GUI。这是好的,它是导致失真的其他因素,也许是布局管理器?

在:

Before

后:

After

这是一个示例代码,用于演示我想要实现的目标。令人惊讶的是它有效。我将不得不做一个更长的例子来解决这个问题。

public class Gui {

private JLabel jLabel;

public void displayGui(){

    JFrame jFrame = new JFrame();
    jFrame.setSize(500,500);

    JPanel mainPanel = new JPanel(new GridBagLayout());
    mainPanel.setPreferredSize(new Dimension(400,400));

    jLabel = new JLabel("Some Percentage 0%");

    GridBagConstraints c = new GridBagConstraints();
    c.gridx = 0;
    c.gridy = 0;

    mainPanel.add(jLabel,c);

    JScrollBar jScrollBar = new JScrollBar();
    jScrollBar.addAdjustmentListener(new MyAdjustmentListener());

    c = new GridBagConstraints();
    c.gridx = 0;
    c.gridy = 1;

    mainPanel.add(jScrollBar,c);

    jFrame.add(mainPanel);

    jFrame.pack();
    jFrame.setVisible(true);
}

public class MyAdjustmentListener implements AdjustmentListener{

    @Override
    public void adjustmentValueChanged(AdjustmentEvent e) {
        jLabel.setText("Some Percentage " + e.getValue() + "%");
    }
}

}

编辑8/15/2017,上午11:30: 我找到了一个解决方法。我认为,因为当我调整窗口大小时,它似乎重新绘制并看起来正确。每次在AdjustmentListener中调用setText后,我都会放入jFrame.repaint()。作为旁注,看起来好像整个gui正在重新绘制在“选项JPanel”中,如图所示。

1 个答案:

答案 0 :(得分:3)

在Swing中,Listener在UI线程上执行。也就是说,直接从adjustmentValueChangedactionPerformed等方法更新UI元素是安全的。

只有从另一个线程启动更新时,您才必须使用SwingUtilities.invokeLater()和类似的方法。