Swing Worker: функция get()
Моя проблема в том, что я не понимаю, как swingworker
работает, потому что я пытаюсь сделать, это сделать fa=worker.get()
потому что у меня есть длинный метод, который вычисляет много точек, работающих в фоновом режиме, потому что я не хочу замораживать свой интерфейс, и я хочу получить ее результаты, чтобы нарисовать изображение компонента. Но я не понимаю, куда это идет, когда я делаю fa=worker.get()
потому что моя консоль печатает "titi"
и я положил много другой печати, чтобы увидеть следующую часть программы достигнута, но никто не печатается. Пожалуйста, помогите мне узнать, где идет компиляция после get()
или пока он выполняется, и если у вас есть представление о том, как реализовать то, что мне нужно, каждый блок кода приветствуется.
public void paintComponent(final Graphics g1){
// TODO Auto-generated method stub
final int width=getWidth();
final int height=getHeight();
image= new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
//On transforme le rectangle de base en un rectangle qui a le meme ratio que le cadre contenant l'ancien
//(Il yaura dessus la meme fractale mais avec plus de fond noir) afin que l'on puisse zoomer sans deformer la fractale
frame = frame.expandToAspectRatio((double)getWidth()/getHeight());
FlameAccumulator fa=null;
worker= new SwingWorker<FlameAccumulator,FlameAccumulator>(){
@Override
protected FlameAccumulator doInBackground() throws Exception {
// TODO Auto-generated method stub
System.out.println("exception");
return builder.build().compute(frame,width,height,density);
}
};
try {
System.out.println("titi");
fa=worker.get();
} catch (InterruptedException | ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Graphics g0=(Graphics2D)g1;
if(fa==null){
System.out.println("toto");
for (int i = 0; i <height; i++) {
for (int j = 0; j < width; j++) {
image.setRGB(j,i,0);
}
}
}
else{
System.out.println("tata");
for (int i = 0; i <height; i++) {
for (int j = 0; j < width; j++) {
image.setRGB(j,i,fa.color(palette, background, j, height-1-i).asPackedRGB());
}
}
}
g0.drawImage(image,0,0,null);
}
2 ответа
Вместо блокировки на get()
, вам следует publish()
промежуточные результаты и process()
их на EDT, например.
Приложение: Похоже, вы пытаетесь смоделировать пламя, используя фрактальный подход. Поскольку это может быть в вычислительном отношении дорогим, может быть полезно построить изображение как TexturePaint
, который может быть использован для заполнения любого Shape
в Graphics
контекст. В примере SwingWorker<TexturePaint, TexturePaint>
публикует простую последовательность кадров с искусственной частотой ~25 Гц. Так как process()
выполняется на EDT, можно ссылаться на каждую новую краску при обновлении TexturePanel
,
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.TexturePaint;
import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
import java.util.List;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingWorker;
/**
* @see https://stackru.com/a/16880714/230513
*/
public class HeatTest {
private static final int N = 256;
private TexturePanel p = new TexturePanel();
private void display() {
JFrame f = new JFrame("HeatTest");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(p);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
new HeatWorker().execute();
}
private class TexturePanel extends JPanel {
private TexturePaint paint;
public void setTexture(TexturePaint tp) {
this.paint = tp;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setPaint(paint);
g2d.fillRect(0, 0, getWidth(), getHeight());
}
@Override
public Dimension getPreferredSize() {
return new Dimension(N, N);
}
}
private class HeatWorker extends SwingWorker<TexturePaint, TexturePaint> {
private final Random random = new Random();
@Override
protected TexturePaint doInBackground() throws Exception {
BufferedImage image = new BufferedImage(N, N, BufferedImage.TYPE_INT_ARGB);
TexturePaint paint = new TexturePaint(image, new Rectangle(N, N));
int[] iArray = {0, 0, 0, 255};
while (true) {
WritableRaster raster = image.getRaster();
for (int row = 0; row < N; row++) {
for (int col = 0; col < N; col++) {
iArray[0] = 255;
iArray[1] = (int) (128 + 32 * random.nextGaussian());
iArray[2] = 0;
raster.setPixel(col, row, iArray);
}
}
publish(paint);
Thread.sleep(40); // ~25 Hz
}
}
@Override
protected void process(List<TexturePaint> list) {
for (TexturePaint paint : list) {
p.setTexture(paint);
p.repaint();
}
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new HeatTest().display();
}
});
}
}
Вы не должны звонить get()
в paintComponent()
метод. Это заблокирует и подождет, пока рабочий не закончит вычисления. get() должен вызываться только в done()
метод вашего работника, когда вы уверены, что работник завершил свои вычисления, как показано в примере, приведенном в документации.