我正在尝试绘制具有几千个点的动态图。我正在使用获取 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);
}
});
}
}
}
几件事:
SwingWorker.done()
在EDT上执行,使用SwingUtilities.invokeLater
没有必要paintComponent()
方法触发 SwingWorker 不是一个好主意,因为它可能会进行不必要的计算。您应该在状态更改时执行 SwingWorker,并让 paintComponent()
绘制上次计算的数据。paintComponent()
调用之间是相同的,因此您最终可能会在错误的图形上下文中绘制。