Привет стек обменников,
У меня проблема с индикаторами выполнения в java Swing. Я думаю, что мои недоразумения возникают из-за моего плохого понимания потоков и очереди событий Swing (я мало знаю о java потоках и о том, что именно происходит на AWTEventQueue
, хотя я обычно понимаю, что такое многопоточность).
Контекст заключается в том, что JButton
нажимается, чтобы начать длинный расчет. Перед началом расчета я делаю индикатор выполнения в JFrame
, который, как я думал, будет нарисован, но это не так. Рамка появляется, но она просто серая. На кнопке, в этом примере, написано "clickMe".
В прослушивателе действий "clickMe" я сначала создаю и отображаю JFrame
в подзадаче, которая называется "run" (я не ясно, когда это запланировано TBH). Затем я вызываю doTask()
, который работает в том же потоке, что и прослушиватель действий (который, я думаю, AWTEventThread
??). doTask()
запускается, распечатывая номера на консоль. С выводом doTask()
смешиваются числа итераций индикатора выполнения (с момента, когда слушатель действия запустил makeProgressBar()
).
Таким образом, на выходе получается, что и индикатор выполнения работает, и AWTEventThread
, но значение, установленное в JProgressBar
GUI, никогда не обновляется.
Как я могу изменить свой код, чтобы GUI обновлялся? Я пытался понять учебник JProgressBar
и охотился по сети, но я думаю, что моя проблема - это скорее концептуальное понимание Java Задач.
Это мой код:
package problemclass;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
public class ProblemClass
{
void progressBarButtonClick()
{
JFrame buttonInAFrame = new JFrame();
JPanel buttonInAFramePanel = new JPanel();
JButton clickMe = new JButton("Click me!");
buttonInAFramePanel.add(clickMe);
clickMe.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e)
{
JFrame progBarFrame = makeProgressBar();
doTask();
progBarFrame.dispose();
}
});
buttonInAFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
buttonInAFrame.add(buttonInAFramePanel);
buttonInAFrame.pack();
buttonInAFrame.setVisible(true);
}
private void doTask()
{
for(int i = 0; i < 20000; i++)
{
if (i % 100 == 0)
{
System.out.println("TASK iteration " + i);
try
{
Thread.sleep(1000);
}
catch (InterruptedException e) {}
}
}
}
private JFrame makeProgressBar()
{
JFrame progBarFrame = new JFrame();
JPanel progBarPanel = new JPanel();
JProgressBar progressBar = new JProgressBar();
progBarPanel.add(progressBar);
progressBar.setValue(0);
progressBar.setStringPainted(true);
progressBar.setIndeterminate(true);
new Thread(new Runnable()
{
public void run()
{
for (int i = 0; i <= 100; i++)
{
final int j = i;
System.out.println("Progress Iteration " + j);
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
progressBar.setValue(j);
}
});
try
{
java.lang.Thread.sleep(100);
}
catch(Exception e) { }
}
}
}).start();
progBarFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
progBarFrame.add(progBarPanel);
progBarFrame.pack();
progBarFrame.setVisible(true);
return progBarFrame;
}
public static void main(String[] args)
{
EventQueue.invokeLater(() ->
{
new ProblemClass().progressBarButtonClick();
});
}
}