除了事件分发线程(EDT),您不能让任何线程接触GUI。让其他线程与GUI混乱会导致麻烦和异常。您可以采用多线程多缓冲技术。它涉及两个步骤:
为了并行化复杂的绘制例程,您可以简单地将整个“视图”划分为小块,然后让一个线程将一个小块绘制为一张图像。这是有关使用Java处理图像的教程。
获得图像后,可以通过将相应补丁的图像拼接在一起,来覆盖
paintComponent
并使用Graphics.drawImage方法让EDT显示完整视图或部分视图。
为了避免不必要的工作,请确保先执行第一步,然后再更改视图后再执行,否则只需再次绘制先前计算的结果即可。此外,如果可以缩小视图内部在框架之间更改的区域的范围,请尝试仅更新部分补丁。
让我们假设您的视图至少与最佳线程数一样高,因此我们可以垂直划分视图。另外,我们假设绘制任何像素所需的工作量与其他像素差不多,因此我们可以为每个色块使用相同的大小。这两个假设使事情变得容易得多。
代码如下。如果您不需要计算机执行任何其他操作,则可以设置
nThreads内核数。请注意,该代码还将伪代码用于“ parallel
for”,在此处进行了说明:
// let multiple threads write all patchespublic BufferedImage[] writePatches(...){ // Given data: const int nThreads = ...; // the amount of threads that you want Rectangle viewBox = ...; // The view rectangle // Immediate data: Dimension viewSize = viewBox.getSize(); int defaultPatchHeight = (int)ceil((float)viewSize.height / nThreads); int lastPatchHeight = viewSize.height - (nThreads-1) * defaultPatchHeight; // The actual "buffer" is a set of images BufferedImage[] images = new BufferedImage[nThreads]; // ... // pseudopre for parallel processing of a for loop parallel-for (nThreads, threadId) { // the starting point and size of this thread's patch // handle boundary (last) patch int w = viewBox.width; int h = threadId == nThread-1 ? lastPatchHeight : defaultPatchHeight; int x = viewBox.x; int y = viewBox.y + threadId * defaultPatchHeight; BufferedImage patch = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); Graphics2D g = off_Image.createGraphics(); // use g to draw to patch image here // better yet: Re-use existing patches and only update the parts that changed. images[threadId] = patch; } return images;}// ...// override paintComponent@Overridevoid paintComponent(Graphics gg){ Graphics2D g = (Graphics2D) gg; // ... // stitch all images together (you can also just display only some images here) for (int threadId = 0; threadId < nThreads; ++threadId) { int w = viewBox.width; int h = threadId == nThread-1 ? lastPatchHeight : defaultPatchHeight; int x = viewBox.x; int y = viewBox.y + threadId * defaultPatchHeight; // use pre-computed images here BufferedImage patch = images[threadId]; g.drawImage(patch, x, y, ...); }}


