java-如何使用剪辑来减少绘制时间?

我正在尝试使用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
}

这似乎仍然在未绘制弧位的右下角分位数上留下了问题,但这当然与剪辑有关.

上一篇:BootStrap Validator 版本差异问题导致的submitHandler失效问题的解决方法


下一篇:调整TYPE_CUSTOM BufferedImages的大小?