但是如果长期任务是在Graphics2D中绘制应用程序1000例怎么办?这是相互矛盾的要求吗?
public class MyObject extends JPanel {
...
public void paintComponent(Graphics g) {...}
...
}
如果我需要多次调用此方法,它可以被视为一项长期任务,我应该怎么做,以避免阻止GUI?据我所知,不允许在SwingWorker中委托它。对于这种“长期任务”有没有解决办法?
答案 0 :(得分:1)
我认为这是一个例外。只要您没有绘制到屏幕上,就可以在后台线程中调用它。关键是实际的UI内容应该发生在事件派发线程上,这样所有的更改都将对用户可见。
这是如何发生这种情况的一个框架:
public class MyObject extends JPanel {
private static final int NUMBER_OF_PDFS = 10_000;
private JProgressBar progressBar = new JProgressBar(0, NUMBER_OF_PDFS);
public void paintPdfs() {
ExecutorService threadPool = Executors.newFixedThreadPool(5); // this can come somewhere else too
for (int i = 0; i < NUMBER_OF_PDFS; i++) {
final int newProgressBarValue = i; // you might need some mapping, depends on the setup of the taskbar
threadPool.execute(() -> {
try {
Graphics pdfG2 = getPdfGraphics();
MyObject.this.paintComponent(pdfG2);
} finally {
SwingUtilities.invokeLater(() -> {
int progressBarValue = progressBar.getValue();
if (progressBarValue < newProgressBarValue) {
progressBar.setValue(newProgressBarValue);
}
});
}
});
}
}
private Graphics getPdfGraphics() {
// I don't know how to do this. On the other hand, you do :)
return null;
}
@Override
public void paintComponent(Graphics g) {
// ...
}
}
我只能看到一个警告:在此打印过程中,摆动物体不应改变。如果他们这样做,那么你需要另一个技巧。另一个技巧是逐个在事件派发线程中打印pdf:
public void paintPdfs() {
for (int i = 0; i < NUMBER_OF_PDFS; i++) {
final int newProgressBarValue = i; // you might need some mapping, depends on the setup of the taskbar
SwingUtilities.invokeLater(() -> {
try {
Graphics pdfG2 = getPdfGraphics();
MyObject.this.paintComponent(pdfG2);
} finally {
int progressBarValue = progressBar.getValue();
if (progressBarValue < newProgressBarValue) {
progressBar.setValue(newProgressBarValue);
}
}
});
}
}
第二种方法一次运行一个paintComponent()
,因此不会冻结您的UI。这就是为什么它不需要任何执行程序或工作线程。它只是确保它添加