我正在尝试使用clip来减少cpu负载.
但是该剪辑在屏幕上留下了一些我似乎无法摆脱的垃圾.同样,打开和关闭裁剪似乎对cpu负载没有影响.
在任一情况下.大部分时间似乎都花在了重新绘制管理器和绘制缓冲的图像上.
import static java.lang.Math.*;
import static java.awt.Color.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.awt.image.*;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import javax.swing.*;
class Piece {
protected Piece(int piece,int pieces,int radius) {
this.piece=piece;
this.start=piece*2*PI/pieces;
this.end=(piece+1)*2*PI/pieces;
points=new ArrayList<Point>((int)ceil(4*PI*radius*radius/pieces));
}
public double start() {
return start;
}
public double end() {
return end;
}
public int piece() {
return piece;
}
public static double angleToPiece(int piece,int pieces) {
return piece*2*PI/pieces;
}
public String toString() {
return piece+" "+start+" "+end+" "+start*180/PI;
}
protected final double start;
protected final double end;
final int piece;
public final ArrayList<Point> points;
}
class P extends Piece {
P(int piece,int pieces,int radius) {
super(piece,pieces,radius);
shape=new Arc2D.Double(0,0,2*radius,2*radius,toDegrees(start),toDegrees(end-start),Arc2D.PIE);
shapeAndPrevious=new Arc2D.Double(0-extra,0-extra,2*radius+extra,2*radius+extra,toDegrees(start-2*PI/pieces)-extrad,toDegrees(2*(end-start))+2*extrad,Arc2D.PIE);
}
final Shape shape,shapeAndPrevious;
static final int extra=0;
static final int extrad=0;
}
class Y extends JPanel {
Y(int radius,int nPieces,long period) {
this.radius=radius;
this.nPieces=nPieces;
this.period=period;
d=new Dimension(2*radius,2*radius);
lhsOrigin=new Point(radius,radius);
// setOpaque(false);
}
private void init() {
pieces=new P[nPieces];
for(int i=0;i<nPieces;i++)
pieces[i]=new P(i,nPieces,radius);
while(gc==null)
Thread.yield(); // wait for gui to be constructed
bi=gc.createCompatibleImage(d.width,d.height);
stpe.scheduleAtFixedRate(new Runnable() {
@Override public void run() {
dtrt();
}
},0,1,TimeUnit.MILLISECONDS);
}
private int dt() {
return (int)(System.currentTimeMillis()-t0);
}
private long dtNanos() {
return System.nanoTime()-t0Nanos;
}
private double dtMillis() {
return dtNanos()/1000000.;
}
private void paintRadialLine(Graphics2D g) {
g.setColor(green);
if(line2d!=null)
if(paintRadialLine)
g.draw(line2d);
}
private void paintPieceShape(Graphics g,int index) {
g.setColor(red);
if(paintPieceShape) {
((Graphics2D)g).draw(pieces[index].shape);
g.setColor(yellow);
//((Graphics2D)g).fill(pieces[index].shape);
}
}
@Override public void paintComponent(Graphics g) {
// super.paintComponent(g);
Shape s=g.getClip();
if(clip!=null) {
AlphaComposite ac=AlphaComposite.getInstance(AlphaComposite.SRC_OVER,.75f);
((Graphics2D)g).setComposite(ac);
((Graphics2D)g).clip(clip);
}
paintBufferedImage(g);
Color old=g.getColor();
paintPieceShape(g,piece);
paintRadialLine(((Graphics2D)g));
g.setColor(old);
g.setColor(Color.white);
g.drawLine(radius,0,radius,2*radius);
g.drawLine(0,radius,2*radius,radius);
if(clip!=null)
((Graphics2D)g).setClip(s);
}
private void paintBufferedImage(Graphics g) {
if(bi!=null)
g.drawImage(bi,0,0,null);
}
@Override public Dimension getPreferredSize() {
return new Dimension(d);
}
private void dtrt() {
piece=(int)(dtNanos()%period*nPieces/period);
if(!(0<=piece&&piece<nPieces)) {
System.out.println("!(0<=piece&&piece<nPieces)");
throw new RuntimeException("!(0<=piece&&piece<nPieces)");
}
long dtNanos=dtNanos();
if(piece!=previous) {
if(dtNanos()<=period)
log.info("piece="+piece);
log.fine("piece "+piece+" "+dtMillis()+" "+round(dtMillis())+" "+(dt()-dtMillis())+" "+dtNanos()%(period/nPieces)+" "+period/nPieces);
if(useClip)
clip=piece==0?null:pieces[piece].shapeAndPrevious;
// repaint();
previous=piece;
}
double angle=2*PI*((dtNanos()%period)/(double)period);
Point2D.Double pd=new Point2D.Double((double)radius*cos(angle),radius*sin(angle));
int x=(int)rint(pd.x);
int y=(int)rint(pd.y);
Point p=new Point(x+radius,radius-y);
line2d=new Line2D.Double(lhsOrigin,p);
if(false&&useClip&&round(dtNanos()%(period/nPieces))!=0)
clip=angle==0?null:line2d;
if(paintImmediately)
paintImmediately(0,0,2*radius,2*radius);
else repaint();
}
private void createAndShowGUI() {
System.out.println("start constructing gui");
setSize(d);
setPreferredSize(d);
Frame f=new Frame("X");
f.setUndecorated(true);
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
f.add("Center",this);
gc=getGraphicsConfiguration();
f.pack();
if(System.getProperty("user.name").equals("ray")) {
Rectangle rectangle=f.getBounds();
rectangle.x+=-700;
rectangle.y+=1080;
f.setBounds(rectangle);
}
f.setVisible(true);
System.out.println("end constructing gui");
}
public static void main(String[] args) throws InvocationTargetException,InterruptedException {
RepaintManager rm;
Y x0;
if(false)
x0=new Y(512,400,2000*1000000l); // real app
else x0=new Y(512,16,10000*1000000l); // easier to see
final Y x=x0;
x.log=Logger.getLogger("");
SwingUtilities.invokeLater(new Runnable() {
public void run() {
x.createAndShowGUI();
}
});
x.init();
}
private GraphicsConfiguration gc;
private BufferedImage bi;
private P[] pieces;
private int previous,piece,n;
private final long t0=System.currentTimeMillis(),t0Nanos=System.nanoTime();
private final int radius,nPieces;
private final long period;
private final Dimension d;
private final Point lhsOrigin;
private Shape clip;
private boolean useClip=true;
private boolean paintRadialLine=true;
private boolean paintPieceShape=true;
private boolean paintImmediately=false;
private final ScheduledThreadPoolExecutor stpe=new ScheduledThreadPoolExecutor(2);
private Line2D line2d;
private Logger log;
}
谢谢
解决方法:
问题似乎是P.shapeAndPrevious,它扩展得不够远.增加它的大小似乎会使多余的东西消失.
class P extends Piece
{
P(int piece, int pieces, int radius)
{
super(piece, pieces, radius);
shape = new Arc2D.Double(0, 0, 2 * radius, 2 * radius,
toDegrees(start), toDegrees(end - start), Arc2D.PIE);
shapeAndPrevious = new Arc2D.Double(0 - extra,
0 - extra,
2 * radius + extra,
2 * radius + extra,
toDegrees((start - 2 * PI / pieces)) - extrad,
toDegrees((2 * (end - start))) + 2 * extrad,
Arc2D.PIE);
}
...
至
class P extends Piece
{
P(int piece, int pieces, int radius)
{
super(piece, pieces, radius);
shape = new Arc2D.Double(0, 0, 2 * radius, 2 * radius,
toDegrees(start), toDegrees(end - start), Arc2D.PIE);
shapeAndPrevious = new Arc2D.Double(0 - extra,
0 - extra,
2 * radius + extra + 10, // add some extra
2 * radius + extra + 10, // add some extra
toDegrees((start - 2 * PI / pieces) - 1) - extrad, // add some extra
toDegrees((2 * (end - start)) + 1) + 2 * extrad, // add some extra
Arc2D.PIE);
}
更新
实际上,您似乎已经意识到了这个问题,因为那里有变量可以执行我的硬编码.所以整个P班变成
class P extends Piece
{
P(int piece, int pieces, int radius)
{
super(piece, pieces, radius);
shape = new Arc2D.Double(0, 0, 2 * radius, 2 * radius,
toDegrees(start), toDegrees(end - start), Arc2D.PIE);
shapeAndPrevious = new Arc2D.Double(0 - extra,
0 - extra,
2 * radius + extra,
2 * radius + extra,
toDegrees((start - 2 * PI / pieces)) - extrad,
toDegrees((2 * (end - start))) + 2 * extrad,
Arc2D.PIE);
}
final Shape shape, shapeAndPrevious;
static final int extra = 15; // add some extra
static final int extrad = 25; // add some extra
}
这似乎仍然在未绘制弧位的右下角分位数上留下了问题,但这当然与剪辑有关.