2017-10-17 66 views
0

我正在为miscropy程序编写一个插件,并且存在与repaint()方法有关的问题。java jpanel与repaint()或同步同步:是一个Listener可添加到swing的重绘?

简短问题: 当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)...没有它我正在要求重绘,但它没有完成,直到我试图保存一个“快照”(这就是savePlot正在做什么。 ..)。我知道,其他线程这些该死的同步问题... 随着睡觉我只是使它不必要的慢,如果我等待不够长,图像不完全地绘制(如下半部缺失)

有一旦完成重新绘制,任何方式都可以得到通知?我可能会听Listener也不错,更好的解决方法是使用显示器或可比较的方法或现在正在重新绘制的方法(目前为止我所知道的并不存在) 主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

,我要绘制并保存为图像。

  1. 将数据添加到不可见的面板。
  2. 创建面板
  3. BufferedImage使用Image从上方
  4. 更新一个JLabel使用setIcon(...)方法(已经被添加到帧)
  5. 上述步骤应该产生一个PropertyChange创建ImageIcon当图标改变时的事件。您可以使用ProperChangeListener来收听此事件。当您收到活动时,您可以重复步骤1至4.

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

请注意,您并不需要步骤4-5。我只是添加了它们,因此您可以看到它们正在处理的情节。如果你不想要视觉效果,那么也许你只是在JLabel上显示文本,指出哪些情节正在被转换。

+0

第1步:你的意思是一个新的JPanel,还是我可以把现有的JFrame(PlotSpectrum类)? 我的代码中有一些小的变化我应该能够创建与图像面板...可视化不一定是 ImageIcon与BufferedImage相比有什么不同? – schetefan24

+0

@ schetefan24这个想法是在内存中创建面板,而不是将其添加到框架,因为你的问题是你不知道什么时候面板将被绘制。通过在内存中创建面板并创建自己的面板图像,您正在控制该过程,而不是Swing的绘制机制。 – camickr

+0

我已经测试了一下可见性和事件触发器: 最简单的方法是,在我开始保存并调用pack()刷新图像之前设置整个Frame不可见:D似乎仍然有点脏,但完美表演:)并感谢提示的可见性;似乎我从Swings控件中删除了框架 – schetefan24