【问题标题】:java jpanel synchronization with repaint() or: Is a Listener addable to swing's repaint?java jpanel 与 repaint() 同步或:监听器是否可添加到 swing 的重绘中?
【发布时间】:2017-10-17 18:34:25
【问题描述】:

我正在为错误程序编写插件,但 repaint() 方法有问题。

简短的问题: 有什么方法可以在 JPanel 的重绘完成或与它同步代码后立即获得通知?

详细版本:

我的程序可以将 xy 图表中的一组数据绘制到 JPanel 并使用 jfree.chart 显示它;在程序的另一部分,我有许多数据集(~100),我想绘制并保存为图像。我也找到了解决方案,但我真的不喜欢它。该问题可以简化为有关 JPanel 绘制状态的通知。

在保存所有图像的部分我有这个解决方案:

PlotSpectrum spectrumWindow = getTheWindow(); //pseudo code...
// some stuff
ti = storage.getImage(channel, slice, frame, position);
spectrumWindow.plotData(false, andor.captureSpectrum(ti.pix), wave,
                 centerWave, fineGrating, exposureTime,
                 slitWidth, substractBackground);
spectrumWindow.repaint(); // probably not necessary
sleep(100);               // this annoys me...
spectrumWindow.savePlot(path, true, config, null);

spectrumWindow 是一个 JPanel,它也显示在另一个窗口中,并且一切正常。 但是我真的不喜欢那里的 sleep(100) ... .)。我知道,其他线程和这些该死的同步问题...... 随着睡眠,我只是让它变得不必要的慢,如果我等待的时间不够长,图像就没有完全绘制(例如下半部分丢失)

有什么方法可以在重绘完成后立即获得通知?我可能也可以使用监听器,更好的是具有监视器或类似的解决方案或现在重新绘制的方法(据我所知不存在?) 主 GUI(包括 JPanel 频谱窗口)和之前粘贴的代码在不同的线程中运行。

我的代码中可能也很重要的部分如下。如果某些括号不匹配或未声明某些变量,请原谅,我删除了很多代码。

谢谢 schetefan24

class PlotSpectrum extends ApplicationFrame // that extends JFrame
{
public void plotData(boolean backgroundGiven, int[] spect, double[] wave_,
                     double centerWave, boolean fineGrating_, double exposureTime,
                     double slitWidth, boolean substractBackground)
{
//process data and store internally
replot();
}

private void replot()
{
XYSeries series = new XYSeries("Spectrum");
//add data to series
XYSeriesCollection collection = new XYSeriesCollection(series);
//setting up some labels and such stuff...
 JFreeChart chart = ChartFactory.createXYLineChart(
        title,
        "Wavelength [nm]", 
        yLabel, 
        collection,
        PlotOrientation.VERTICAL,
        false,
        false,
        false
    );
 dataPanel.add(new ChartPanel(chart)); // this is contained in a Frame
}

public void savePlot(String path, boolean overWriteAll, HashMap<String,String> config, int[][] addData)
{
File output = new File(path);
//some more stuff, ask overwrite etc
if(image)
{
    BufferedImage im = createImage();
    String extension = path.substring(path.lastIndexOf(".")+1, path.length());
    ImageIO.write(im, extension, output);
} else {
//that is an textexport, works fine
}
}

public BufferedImage createImage()
{
    JPanel panel = (JPanel) flipChart.getSelectedComponent();
    int w = panel.getWidth();
    int h = panel.getHeight();
    BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
    Graphics2D g = bi.createGraphics();
    panel.paint(g);
    return bi;
}
}

【问题讨论】:

    标签: java multithreading swing jpanel jcomponent


    【解决方案1】:

    我想绘制并保存为图像。

    1. 将数据添加到不可见的面板中。
    2. 创建一个BufferedImage的面板
    3. 使用上面的图片创建一个ImageIcon
    4. 使用setIcon(...) 方法更新JLabel(已添加到框架中)
    5. 上述步骤应在图标更改时生成PropertyChange 事件。您可以使用ProperChangeListener 来监听此事件。收到活动后,您可以重复步骤 1 - 4。

    查看Screen Image。它将帮助您创建不可见组件的图像。

    请注意,您实际上并不需要步骤 4-5。我刚刚添加了它们,这样您就可以在处理它们时看到这些图。如果您不想要视觉效果,那么您可能只是在 JLabel 上显示文本,指示当前正在转换哪个绘图。

    【讨论】:

    • 第 1 步:您是指新的 JPanel 还是我可以采用现有的 JFrame(PlotSpectrum 类)?通过对我的代码进行一些小的更改,我应该能够只使用图像创建面板......与 BufferedImage 相比,ImageIcon 上的可视化不一定有什么不同?
    • @schetefan24 这个想法是在内存中创建面板而不是将其添加到框架中,因为您的问题是您不知道面板何时会被绘制。通过在内存中创建面板并创建您自己的面板图像,您控制的是过程,而不是 Swing 的绘制机制。
    • 我已经对可见性和事件触发器进行了一些测试:最简单的方法是,在我开始保存之前将整个 Frame 设置为不可见,然后调用 pack() 来刷新图像:D看起来仍然有点脏,但表现完美:)并感谢可见性的提示;看来我是通过它从 Swings 控件中删除框架
    猜你喜欢
    • 1970-01-01
    • 2012-06-02
    • 2013-04-24
    • 1970-01-01
    • 1970-01-01
    • 2010-11-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多