0
我正在使用Java Graphics2D在JPanel中繪製一些行和標籤。繪圖代碼運行非常緩慢(drawString()似乎是最差的,但我不再認爲它是罪魁禍首,只是最忙碌的通話)。Graphics2D.drawString非常慢
執行環境是OSX 10.8.4和VM細節:
JVM: Java HotSpot(TM) 64-Bit Server VM (20.51-b01-457, mixed mode)
Java: version 1.6.0_51, vendor Apple Inc.
Java Home: /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home
JVM Flags: <none>
完全自包含的示例代碼如下:
package com.controlj.test;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.ArrayList;
import java.util.List;
public class TestDrawString {
List<Line2D> lines = new ArrayList<Line2D>();
private Rectangle2D bounds;
public TestDrawString(Rectangle2D rectBounds) {
bounds = rectBounds;
int x0 = (int)Math.floor(bounds.getX());
int y0 = (int)Math.floor(bounds.getY());
int x1 = (int)Math.ceil(bounds.getMaxX());
int y1 = (int)Math.ceil(bounds.getMaxY());
for(int i = x0; i != x1 + 1; i++)
lines.add(new Line2D.Float(i, y0, i, y1));
for(int i = y0; i != y1 + 1; i++)
lines.add(new Line2D.Float(x0, i, x1, i));
}
public void draw(Graphics2D g) {
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
g.setColor(Color.white);
g.setStroke(new BasicStroke(0));
for(Line2D l : lines)
g.draw(l);
AffineTransform current = g.getTransform();
Point2D origin = new Point2D.Double(bounds.getX(), bounds.getY());
origin = current.transform(origin, origin);
g.setTransform(new AffineTransform());
g.setFont(new Font("Monospaced", Font.PLAIN, 12));
for(Line2D l : lines) {
Point2D p = new Point2D.Double(l.getX1(), l.getY1());
p = current.transform(p, p);
if(l.getX1() == l.getX2())
g.drawString(Integer.toString((int)l.getX1()), (int)p.getX() + 1, (int)origin.getY() - 4);
else
g.drawString(Integer.toString((int)l.getY1()), (int)origin.getX() + 1, (int)p.getY() - 4);
}
g.setTransform(current);
}
static class ImageLayers extends JPanel {
private TestDrawString grids;
private Rectangle2D.Double rectBounds;
private AffineTransform at;
private AffineTransform rat = null;
private double ratio;
public ImageLayers() {
MouseAdapter ma = new MouseAdapter() {
private final Point clicked = new Point();
@Override
public void mousePressed(MouseEvent mouseEvent) {
super.mousePressed(mouseEvent);
clicked.setLocation(mouseEvent.getPoint());
}
@Override
public void mouseDragged(MouseEvent mouseEvent) {
super.mouseDragged(mouseEvent);
clicked.setLocation(mouseEvent.getX() - clicked.getX(), mouseEvent.getY() - clicked.getY());
setCoords(rectBounds.getX() - clicked.getX() * ratio, rectBounds.getY() + clicked.getY() * ratio, rectBounds.getWidth());
clicked.setLocation(mouseEvent.getPoint());
}
@Override
public void mouseWheelMoved(MouseWheelEvent mouseWheelEvent) {
super.mouseWheelMoved(mouseWheelEvent);
System.out.println(mouseWheelEvent.toString());
zoom(1.0 + mouseWheelEvent.getWheelRotation()/20.0, mouseWheelEvent.getPoint());
}
};
addMouseListener(ma);
addMouseMotionListener(ma);
addMouseWheelListener(ma);
addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent componentEvent) {
setTransform();
repaint();
}
});
setCoords(118.0, -40.0, 35.0);
}
public void zoom(double val, Point point) {
Point2D point2 = new Point2D.Double(point.getX(), point.getY());
point2 = rat.transform(point2, point2);
double x = point2.getX() - (point2.getX() - rectBounds.getX())/val;
double y = point2.getY() - (point2.getY() - rectBounds.getY())/val;
setCoords(x, y, rectBounds.getWidth()/val);
}
private void setTransform() {
Rectangle pos = getBounds();
System.out.println("Getbounds returned " + pos);
if(pos.getHeight() == 0 || pos.getWidth() == 0)
return;
ratio = rectBounds.width/(double)pos.getWidth();
rectBounds.height = rectBounds.width * (double)pos.getHeight()/(double)pos.getWidth();
at = new AffineTransform();
//at.translate(pos.getX(), pos.getY() + pos.getHeight());
at.translate(0, pos.getHeight());
at.scale((pos.getWidth())/rectBounds.getWidth(), -(pos.getWidth())/rectBounds.getWidth());
at.translate(-rectBounds.getMinX(), -rectBounds.getMinY());
System.out.println("Translation is: " + at.toString());
rat = null;
try {
rat = at.createInverse();
} catch(NoninvertibleTransformException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
}
@Override
protected void paintComponent(Graphics graphics) {
super.paintComponent(graphics);
Graphics2D g = (Graphics2D)graphics;
g.setTransform(at);
grids.draw(g);
}
public void setCoords(double x, double y, double width) {
if(width <= 0)
width = 35;
System.out.println(String.format("setCoords(x=%f, y=%f, width=%f", x, y, width));
rectBounds = new Rectangle2D.Double(x, y, width, width);
setTransform();
grids = new TestDrawString(rectBounds);
repaint();
}
}
public static void main(String args[]) {
JFrame frame = new JFrame("DrawStringTest");
frame.setBounds(400, 400, 1000, 1000);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ImageLayers iml = new ImageLayers();
iml.setBackground(Color.blue);
iml.setCoords(118.0, -40.0, 35.0);
JPanel jp = new JPanel();
jp.setLayout(new BorderLayout());
JPanel buttonPanel = new JPanel();
buttonPanel.add(new Button("+")); // COMMENT out this line to speed things up!
jp.add(buttonPanel, BorderLayout.SOUTH);
JSplitPane contentPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, jp, iml);
contentPane.setDividerLocation(200);
frame.add(contentPane);
frame.setVisible(true);
}
}
拖動或縮放(使用滾輪)非常慢。 VisualVM分析數據如下。每次調用TestDrawString.draw()需要大約400ms!但是,如果我不將該按鈕添加到側面板,它會顯着加速 - 每次draw()調用的時間不會超過1ms。奇怪的。
profile http://www.sr20.org/DrawString.png
「緩慢」,如:它出現在面板上之前有一點滯後? – GGrec
你正在做雙循環,這不會幫助。如果可以的話,將結果緩衝到像「BufferedImage」之類的東西並直接繪製它們。 – MadProgrammer
請修改您的問題以包含展示您描述的問題的[sscce](http://sscce.org/),並確保[profile](http://stackoverflow.com/q/2064427/230513) ;或者,使用'JTextComponent'。 – trashgod