我正在编写一个具有许多不同视图的程序。其中之一是图形密集型(显示互连的图形)。其他人只显示较小但复杂的图表。
我发现主视图的绘制时间很长(甚至只是绘制当前可见的区域),并且在绘制时,界面的其余部分变得很慢。
我的问题是,我可以创建一个新线程来处理绘画吗?如果是这样,是否会导致性能提高,我怀疑它不会。我尝试了以下方法:
创建一个抽象类ThreadPaintablePanel,我的复杂视图将继承该类。
public abstract class ThreadPaintablePanel extends JPanel{
private Thread painter;
public abstract void paintThread(Graphics g);
protected void callPaintThread(Graphics g){
if(painter != null){
painter.interrupt();
}
painter = new Thread(new PaintRunnable(this, g));
painter.start();
}
}
在我的复杂观点中,我的paintComponent
方法很简单:super.callPaintThread(g);
被覆盖的paintThread
方法包含我所有的绘画代码。但是,这导致未上漆的面板。我是否错过了明显的事情?
谢谢
除了事件分发线程(EDT),您不能让任何线程接触GUI。让其他线程与GUI混乱会导致麻烦和异常。您可以采用多线程多缓冲技术。它涉及两个步骤:
为了并行化复杂的绘制例程,您可以简单地将整个“视图”划分为小块,然后让一个线程将一个小块绘制为一张图像。这是有关使用Java处理图像的教程。
获得图像后,可以通过将相应补丁的图像拼接在一起,来覆盖paintComponent
并使用Graphics.drawImage方法让EDT显示完整视图或部分视图。
为了避免不必要的工作,请确保先执行第一步,然后再更改视图后再html" target="_blank">执行,否则只需再次绘制先前计算的结果即可。此外,如果可以缩小视图内部在框架之间更改的区域的范围,请尝试仅更新部分补丁。
让我们假设您的视图至少与最佳线程数一样高,因此我们可以垂直划分视图。另外,我们假设绘制任何像素所需的工作量与其他像素差不多,因此我们可以为每个色块使用相同的大小。这两个假设使事情变得容易得多。
代码如下。如果您不需要计算机执行任何其他操作,则可以设置nThreads
内核数。请注意,该代码还将伪代码用于“ parallel
for”,在此处进行了说明:
// let multiple threads write all patches
public 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];
// ...
// pseudocode 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
@Override
void 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, ...);
}
}
所以我在只用线绘制形状时遇到了一个大问题。假设我从屏幕中间的一个点开始画一条线,然后以100个像素的距离向前画,角度为0,然后我用角度72度画另一条相同长度的线,以此类推,直到360度。它应该给我一个完美的五边形,一条线结束,另一条线从那个点开始,但是线在末端不相交,它非常适合角度为0/90/180/270的正方形,但我需要让它适用于每个形状,甚至是圆。我用这个东西来计算: 其中_cosinuse
问题内容: 我正在用Piccolo编写一个交互式applet,并且需要在其中包含高斯曲线(又称正态分布图)。 我想象任何一种Java实现都足够,但是我找不到。理想情况下,我想传递一组值并将图表绘制在面板,图像对象或可以嵌入在applet中的任何对象中。 在让我自己动手编写代码之前,有人知道做这件事的有用代码吗? 欢迎使用其他语言的实现,只要它们易于移植到Java中即可。 问题答案: 不知道它是否有
问题内容: 我正在尝试用Java绘制曲线。一个简单的以(X,Y)开始,(X,Y)结束和曲线量的贝塞尔曲线就足够了。 我找不到在Swing中执行此操作的方法。如果不在Swing中,我可以使用一些简单的数学方法吗?我将如何在Swing中实现它? 编辑:我知道如何通过重写paint(Graphics g)方法绘制形状和线条。 问题答案: 您可以使用Java 2D Object Path2D.Double
问题内容: 我已经使用样条插值法来平滑时间序列,并且还想在绘图中添加一条水平线。但是似乎有一个我无法控制的问题。任何帮助都会非常有帮助。这是我所拥有的: 问题似乎与我对水平线图的使用有关。 问题答案: 您是正确的,我认为这使您失望。您将要重用原始的x轴变量,并使用另一个包含变量的相同长度的numpy数组对其进行绘制。 希望可以解决问题!
我使用样条插值来平滑时间序列,还想在图中添加一条水平线。但是似乎有一个问题超出了我的控制范围。任何帮助都会很有帮助。这是我所拥有的: 问题似乎在于我使用进行水平线绘制。
问题内容: 我试图在bufferedimage上绘制水平和垂直线。它最终应该看起来像一个网格单元。但是,当我运行代码时,我只看到两行:最左边的行和最上面的行(即,从0,0到0,图像的高度和从0,0到图像的宽度,0的一行),这里是代码段: 和覆盖的绘制方法: 所有这些都在扩展了JPanel的名为RobotMaze的类中。任何帮助表示赞赏。 问题答案: