私は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;
}
ありがとう