ループ内のJLabelを別のスレッドから継続的に更新する方法はありますか?現在、Jlabelはループが終了すると更新されます。ループ内のJLabelを別のスレッドから連続的に更新する
私が間違っている場合は、私はこれを修正してください。これは、他のスレッドが実行を終了するまでイベントディスパッチャスレッドが停止しているためです。
両方のスレッドを同時に実行できる方法はありますか?
私はループ内にThread.sleep(300)を与えようとしましたが、動作しませんでした。
ループ内のJLabelを別のスレッドから継続的に更新する方法はありますか?現在、Jlabelはループが終了すると更新されます。ループ内のJLabelを別のスレッドから連続的に更新する
私が間違っている場合は、私はこれを修正してください。これは、他のスレッドが実行を終了するまでイベントディスパッチャスレッドが停止しているためです。
両方のスレッドを同時に実行できる方法はありますか?
私はループ内にThread.sleep(300)を与えようとしましたが、動作しませんでした。
私が間違っている場合は、私には間違いがないと修正してください。これは、他のスレッドが実行を終了するまでイベントディスパッチャスレッドが停止しているためです。
これは間違っています。他のスレッドが本当にSwingイベントスレッドから実行されている場合は、両方とも同時に実行する必要があります。
ボトムラインは、表示されていないコードにバグがあり、より適切な回答を表示するために適切なコードを表示することです。
例えば、
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.util.concurrent.TimeUnit;
import javax.swing.*;
@SuppressWarnings("serial")
public class UpdateLabel extends JPanel {
// label to update
private JLabel statusLabel = new JLabel("");
public UpdateLabel() {
JPanel topPanel = new JPanel(new FlowLayout(FlowLayout.LEADING, 3, 3));
topPanel.add(new JLabel("Counter:"));
topPanel.add(statusLabel);
JPanel bottomPanel = new JPanel();
bottomPanel.add(new JButton(new StartThreadAction("Start Thread")));
setLayout(new BorderLayout());
add(topPanel, BorderLayout.PAGE_START);
add(bottomPanel, BorderLayout.PAGE_END);
}
// fail safe method that is guaranteed to add text to the label
// **on the Swing event thread**
public void setLabelText(final String text) {
if (SwingUtilities.isEventDispatchThread()) {
statusLabel.setText(text);
} else {
SwingUtilities.invokeLater(() -> {
statusLabel.setText(text);
});
}
}
// Abstract Action for our JButton
private class StartThreadAction extends AbstractAction {
protected static final int MAX_COUNT = 10;
protected static final long SLEEP_TIME = 1;
public StartThreadAction(String name) {
super(name);
}
@Override
public void actionPerformed(ActionEvent e) {
// start a new thread
new Thread(new Runnable() {
private int counter = 0;
@Override
public void run() {
// within the background thread update a counter and sleep
while (counter < MAX_COUNT) {
String text = "" + counter;
setLabelText(text); // call our fail safe method
counter++;
try {
// sleep for 1 second
TimeUnit.SECONDS.sleep(SLEEP_TIME);
} catch (InterruptedException e) {
// rare time it's OK to leave this blank
}
}
}
}).start();
}
}
private static void createAndShowGui() {
UpdateLabel mainPanel = new UpdateLabel();
JFrame frame = new JFrame("UpdateLabel");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
// start GUI on the Swing event thread
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
はすべてこの、EDTオンまたはオフコードを呼び出すの心配がありませんので、遅れたシンプルな数のようなもののために、私はタイマーいるので、スイングタイマーを使用したいと言ってすべての呼び出しがこのスレッド上にあることを保証します。
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.*;
@SuppressWarnings("serial")
public class UpdateLabel2 extends JPanel {
// label to update
private JLabel statusLabel = new JLabel("");
private Timer timer;
public UpdateLabel2() {
JPanel topPanel = new JPanel(new FlowLayout(FlowLayout.LEADING, 3, 3));
topPanel.add(new JLabel("Counter:"));
topPanel.add(statusLabel);
JPanel bottomPanel = new JPanel();
bottomPanel.add(new JButton(new StartTimerAction("Start Timer")));
setLayout(new BorderLayout());
add(topPanel, BorderLayout.PAGE_START);
add(bottomPanel, BorderLayout.PAGE_END);
}
// Abstract Action for our JButton
private class StartTimerAction extends AbstractAction {
protected static final int MAX_COUNT = 10;
private static final int TIMER_DELAY = 1000; // 1 second
private int counter = 0;
public StartTimerAction(String name) {
super(name);
putValue(MNEMONIC_KEY, KeyEvent.VK_S);
}
@Override
public void actionPerformed(ActionEvent e) {
if (timer != null && timer.isRunning()) {
return; // wait until timer finishes
}
timer = new Timer(TIMER_DELAY, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e2) {
if (counter >= MAX_COUNT) {
timer.stop();
counter = 0;
} else {
counter++;
statusLabel.setText("" + counter);
}
}
});
timer.start();
}
}
private static void createAndShowGui() {
UpdateLabel2 mainPanel = new UpdateLabel2();
JFrame frame = new JFrame("UpdateLabel");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
// start GUI on the Swing event thread
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
もちろんあります。しかし、コードなしでは、問題がどこで発生するかを知ることは難しいです。 – Paul
[mcve]を考えてみてください。しかし、たぶんあなたはhttp://stackoverflow.com/questions/6567870/what-does-swingutilities-invokelater-doを調べる必要があります...あなたはSwingUtilties.invokeLater()を呼び出して、そのラベルを他のラベルから更新する必要があります糸。そして確かに、あなたはEDTで眠りたくありません。 – GhostCat
スイングで作業し、UIの更新に関する悪夢を避けたい場合は、 "SwingWorker"を試してみてください。これらのスレッドには、(Swing Frameworkの)イベントディスパッチスレッドの底に潜入しなければならないUIを更新する機能を備えた地下タスクを実行できる機能が追加されています。 – Victor