java jpanel与repaint()或同步:是一个监听器可以添加到swing'重绘吗?

时间:2017-10-17 18:34:25

标签: java multithreading swing jpanel jcomponent

我正在为一个错误的程序编写一个插件,并且在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,它也显示在另一个窗口中,一切正常。 但是我真的不喜欢那里的睡眠(100)...没有它我要求重画但是在我尝试保存"快照&#之前它还没有完成34; (那就是savePlot正在做的......)。我知道,其他线程和这些该死的同步问题...... 随着睡眠,我只是让它变得不必要慢,如果我等待的时间不够长,那么图像就不会被完全绘制(例如,下半部分缺失)

有没有办法在重绘完成后立即得到通知?对于一个监听器,我可能也会很好,更好的是使用监视器或类似的解决方案或者现在重新绘制的方法(据我所知,它不存在?) 主GUI(包括JPanel spectrumWindow)和早期粘贴的代码在不同的线程中运行。

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

感谢 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;
}
}

1 个答案:

答案 0 :(得分:1)

  

我想绘制并保存为图像。

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

    注意,您实际上并不需要步骤4-5。我刚添加它们,因此您可以看到正在处理的图形。如果您不想要视觉,那么您可能只是在JLabel上显示文本,指示当前正在转换哪个地块。