Java 在 EDT 之外在自己的线程中绘制图形?
Java draw to Graphics in own thread, outside EDT?
我正在编写一个 Swing 应用程序,它使用 Apache PDFBox 在 paintComponent 方法中将 PDF 页面绘制到 JPanel 的 Graphics2D 对象。绘图需要一段时间,所以当我的应用程序需要同时显示许多 PDF 页面时,它变得缓慢而滞后。我知道,因为我绘制 PDF 页面的 JPanel 是 GUI 的一部分,所以它需要在事件调度线程中绘制。但是绝对不可能在自己的线程中绘制每个 JPanel 吗?比如使用 SwingWorker 之类的?
示例代码(简体):
public class PDFPanel extends JPanel {
@Override
protected void paintComponent(Graphics graphics) {
super.paintComponent(graphics);
Graphics2D g2 = (Graphics2D) graphics;
int scale = 1; // (simplified this line)
g2.setColor(getBackground());
g2.fillRect(0, 0, getWidth(), getHeight());
try {
pdfRenderer.renderPageToGraphics(pageNumber, g2, (float) scale, (float) scale);
} catch (IOException e) {
e.printStackTrace();
}
}
}
使用 BufferedImage
图片字段。它有一个方法 createGraphics()
,您可以在其中绘图。之后调用 Graphics.dispose()
清理资源。
然后在 paintComponent
检查图像的可用性,以便显示它。
渲染可以在 Future、SwingWorker 或其他任何东西中完成。你是对的,永远不要在 paintComponent
中进行繁重的操作,尤其是因为它可能会被重复调用。
最好在构造函数或控制器中启动渲染。
BufferedImage image = new BufferedImage(getWidth(), getHeight(),
BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = image.createGraphics();
try {
pdfRenderer.renderPageToGraphics(pageNumber, g2, (float) scale, (float) scale);
} finally {
g2d.dispose();
}
最初没有填充宽度和高度,所以最好使用 PDF 中的宽度和高度。也不是说 Graphics2D 允许缩放;你可以很容易地添加缩放。
如何自动处理渲染图像的传递可能很清楚。
我正在编写一个 Swing 应用程序,它使用 Apache PDFBox 在 paintComponent 方法中将 PDF 页面绘制到 JPanel 的 Graphics2D 对象。绘图需要一段时间,所以当我的应用程序需要同时显示许多 PDF 页面时,它变得缓慢而滞后。我知道,因为我绘制 PDF 页面的 JPanel 是 GUI 的一部分,所以它需要在事件调度线程中绘制。但是绝对不可能在自己的线程中绘制每个 JPanel 吗?比如使用 SwingWorker 之类的?
示例代码(简体):
public class PDFPanel extends JPanel {
@Override
protected void paintComponent(Graphics graphics) {
super.paintComponent(graphics);
Graphics2D g2 = (Graphics2D) graphics;
int scale = 1; // (simplified this line)
g2.setColor(getBackground());
g2.fillRect(0, 0, getWidth(), getHeight());
try {
pdfRenderer.renderPageToGraphics(pageNumber, g2, (float) scale, (float) scale);
} catch (IOException e) {
e.printStackTrace();
}
}
}
使用 BufferedImage
图片字段。它有一个方法 createGraphics()
,您可以在其中绘图。之后调用 Graphics.dispose()
清理资源。
然后在 paintComponent
检查图像的可用性,以便显示它。
渲染可以在 Future、SwingWorker 或其他任何东西中完成。你是对的,永远不要在 paintComponent
中进行繁重的操作,尤其是因为它可能会被重复调用。
最好在构造函数或控制器中启动渲染。
BufferedImage image = new BufferedImage(getWidth(), getHeight(),
BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = image.createGraphics();
try {
pdfRenderer.renderPageToGraphics(pageNumber, g2, (float) scale, (float) scale);
} finally {
g2d.dispose();
}
最初没有填充宽度和高度,所以最好使用 PDF 中的宽度和高度。也不是说 Graphics2D 允许缩放;你可以很容易地添加缩放。
如何自动处理渲染图像的传递可能很清楚。