图形和 SwingWorker

问题描述 投票:0回答:1

我正在尝试绘制具有几千个点的动态图。我正在使用获取 Graphics 对象作为参数的 SwingWorker 类。我在 SwingWorker 类的构造函数中初始化图形对象,然后在 done() 方法中调用主绘图函数 doGraph(),即在完成所有计算之后。我在绘画方面遇到问题,不确定发生了什么。如果我从 SwingWorker 类的构造函数调用 doGraph() 代码有效,但当我将它放在 done() 中时则无效。

非常感谢任何帮助。为了便于理解,我简化了代码。为了简单起见,我只是想在 doGraph() 中绘制一个矩形。

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.RenderingHints.Key;

import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;

@SuppressWarnings("serial")
public class UIGraph extends JPanel {

private double minX, maxX;
private double minY, maxY;
private SWPaint swPaint; //Swing Worker object
private Graphics2D g2D;
public Key key = RenderingHints.KEY_ANTIALIASING;
public Object obj = RenderingHints.VALUE_ANTIALIAS_ON;
private int labelPadding = 25;
private int padding = 25;
private int padConst = (2 * padding) - labelPadding;
private double xScale;
private double yScale;

/**
 * Crate Panel
 */
private void createUI() {
    setBackground(new Color(245, 255, 250));
    setLayout(new BorderLayout(0, 0));
}

/**
 * Constructor
 * 
 */
public UIGraph() {
    createUI();
    getMinMax();
}

/**
 * Paint Component. Do all the calculations and graphing
 */
@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);

    if (swPaint != null) {
        if (!swPaint.isDone()) { // The swing worker is busy with tasks. Set Visibility to false and return.
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    setVisible(false);
                }
            });
            return;
        }
    }

    swPaint = new SWPaint(g);  //Create a swing worker class, pass graphics object as argument
    swPaint.execute();
    }
}

/**
 * Get the Min and Max values of Data
 */
private void getMinMax() {
  //obtain min and max values
}



/**
 * Main method for graphing
 * 
 * @param g2D 
 */
private void doGraph() {
    xScale = (double) (getWidth() - padConst) / (maxX - minX);
    yScale = (double) (getHeight() - padConst) / (maxY - minY);

    g2D.setColor(Color.WHITE);
    g2D.fillRect(padding + labelPadding, padding, getWidth() - (2 * padding) - labelPadding, getHeight() - 2 * padding
            - labelPadding);
    g2D.setColor(Color.BLACK);
}

/**
 * Swing Worker to handle Paint
 *
 */
public class SWPaint extends SwingWorker<Void, Void> {

    /**
     * Constructor
     * 
     * @param g
     */
    public SWPaint(Graphics g) {
        g2D = (Graphics2D) g;
        g2D.setRenderingHint(key, obj);

       //doGraph() //This works
    }

    /**
     * Do graphing calculations here
     */
    @Override
    protected Void doInBackground() throws Exception {
        // do all calculations here
        return null;
    }

    /*
     * The SW is done. Paint the graph. Set Visibility to true
     */
    protected void done() {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                doGraph();  //This doesn`t work here.
                setVisible(true);
            }
        });
    }
  }
}
java swingworker graphing
1个回答
0
投票

几件事:

  • SwingWorker.done()
    在EDT上执行,使用
    SwingUtilities.invokeLater
    没有必要
  • paintComponent()
    方法触发 SwingWorker 不是一个好主意,因为它可能会进行不必要的计算。您应该在状态更改时执行 SwingWorker,并让
    paintComponent()
    绘制上次计算的数据。
  • 在类级别持有对组件 Graphics2D 对象的引用是可疑的,不能保证实例在两次
    paintComponent()
    调用之间是相同的,因此您最终可能会在错误的图形上下文中绘制。
  • 如果渲染时间很重要,即使计算完成后,您也应该考虑先绘制到屏幕外图像。
© www.soinside.com 2019 - 2024. All rights reserved.