JFrame显示内部的内容副本......?

时间:2014-03-29 20:52:14

标签: java swing graphics jpanel paintcomponent

我有一个奇怪的问题,我可以弄清楚。

这是我的程序运行:

enter image description here

右边的时钟甚至不应该在那里,它应该只是显示时间的字符串。我创建了两个不同的对象并将它们添加到内容面板,然后将内容面板添加到JFrame。我还有一个菜单栏,我添加到JFrame,它显示在内容窗格的右侧。这是我的主要课程:

  class DigitalClock3DialsView extends DigitalClockView {
private static int caps[] = { BasicStroke.CAP_BUTT, 
    BasicStroke.CAP_SQUARE, BasicStroke.CAP_ROUND};
private static int joins[] = { BasicStroke.JOIN_MITER, 
    BasicStroke.JOIN_BEVEL, BasicStroke.JOIN_ROUND};
private static Color colors[] = {Color.gray, Color.pink, Color.lightGray};
private static BasicStroke bs1 = new BasicStroke(1.0f);

// three arms of clock
private Line2D lines[] = new Line2D[3];
private int rAmt[] = new int[lines.length];
private int speed[] = new int[lines.length];
private BasicStroke strokes[] = new BasicStroke[lines.length];
private GeneralPath path;
private Point2D[] pts;
private float size;
private Ellipse2D ellipse = new Ellipse2D.Double();
private BufferedImage bimg;

//variables to keep track if minutes or hours increased
private int oldMinute;
private int oldHour;

/**
 * init background
 */
public void init() {

    setBackground(Color.white);
}
/**
 * reset view: the shape of arms, etc
 */
public void reset(int w, int h) 
{

    oldMinute = 0;
    oldHour = 0;

    size = (w > h) ? h/6f : w/6f;
    for (int i = 0; i < lines.length; i++) {
        lines[i] = new Line2D.Float(0,0,size,0);
        strokes[i] = new BasicStroke(size/3, caps[i], joins[i]);
        rAmt[i] = 270;      // vertical
    }
    //speed of the 3 arms
    speed[0] = 6;   
    speed[1] = 6;
    speed[2] = 6;

    path = new GeneralPath();
    path.moveTo(size, -size/2);
    path.lineTo(size+size/2, 0);
    path.lineTo(size, +size/2);

    // YW: do not know how to show the regular clock view
    // with inc of 5 mins on the contour
    // can you help to fix this?

    ellipse.setFrame(w/2-size*2-4.5f,h/2-size*2-4.5f,size*4,size*4);
    double linApproxLen = 0.75 * size * 0.258819;   // sin(15 degree)
    PathIterator pi = ellipse.getPathIterator(null, linApproxLen);
    Point2D[] points = new Point2D[100];
    int num_pts = 0;
    while ( !pi.isDone() ) 
    {
        float[] pt = new float[6];
        switch ( pi.currentSegment(pt) ) {
            case FlatteningPathIterator.SEG_MOVETO:
            case FlatteningPathIterator.SEG_LINETO:
                points[num_pts] = new Point2D.Float(pt[0], pt[1]);
                num_pts++;
        }
        pi.next();
    }

    pts = new Point2D[num_pts];
    System.arraycopy(points, 0, pts, 0, num_pts);

}

private Point2D[] computePoints(double w, double h, int n)
{
    Point2D points[] = new Point2D[n];
    double angleDeltaRad = Math.PI * 2 / n;
    for (int i=0; i<n; i++)
    {
        double angleRad = i * angleDeltaRad;
        double ca = Math.cos(angleRad);
        double sa = Math.sin(angleRad);
        double x = sa * w/2;
        double y = ca * h/2;
        points[i] = new Point2D.Double(x,y);
    }
    return points;
}




public void paint(Graphics g) 
{   
    System.out.printf("seconds: %s, minutes: %d \n", second, minute);


    Dimension d = getSize();


    updateSecond(d.width, d.height);

    if(oldMinute < minute || (oldMinute==59 && minute==0))
    {
        oldMinute = minute;
        updateMinute(d.width, d.height);
    }
    if(oldHour < hour || (oldHour==12 && hour == 1) )
    {
        oldHour = hour;
        updateHour(d.width, d.height);
    }



    Graphics2D g2 = createGraphics2D(d.width, d.height);
    drawClockArms(d.width, d.height, g2);
    g2.dispose();
    g.drawImage(bimg, 0, 0, this);
}

public Graphics2D createGraphics2D(int w, int h) {
    // standard Java 2D code
    Graphics2D g2 = null;
    if (bimg == null || bimg.getWidth() != w || bimg.getHeight() != h) {
        bimg = (BufferedImage) createImage(w, h);
        reset(w, h);
    } 
    g2 = bimg.createGraphics();
    g2.setBackground(getBackground());
    g2.clearRect(0, 0, w, h);
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                        RenderingHints.VALUE_ANTIALIAS_ON);
    return g2;
}

private void drawClockArms(int w, int h, Graphics2D g2) {

    ellipse.setFrame(w/2-size,h/2-size,size*2,size*2);
    g2.setColor(Color.black);
    g2.draw(ellipse);

    for (int i = 0; i < lines.length; i++) {
        AffineTransform at = AffineTransform.getTranslateInstance(w/2,h/2);
        at.rotate(Math.toRadians(rAmt[i]));
        g2.setStroke(strokes[i]);
        g2.setColor(colors[i]);
        g2.draw(at.createTransformedShape(lines[i]));
        g2.draw(at.createTransformedShape(path));
    }

    g2.setStroke(bs1);
    g2.setColor(Color.black);
    for (int i = 0; i < pts.length; i++) {
        ellipse.setFrame(pts[i].getX(), pts[i].getY(), 9, 9);
        g2.draw(ellipse);
    }
}

/**
 * step forward on the display: move arm forward
 */
  public void step(int w, int h) {
        for (int i = 0; i < lines.length; i++) 
        {
            rAmt[i] += speed[i];
            System.out.println(rAmt[i]);
            if (rAmt[i] == 360) {
                rAmt[i] = 0;
            } 
        }
    }   

public void updateSecond(int w, int h) {
        rAmt[0] += speed[0];
        if (rAmt[0] == 360) {
            rAmt[0] = 0;
        } 
}   
public void updateMinute(int w, int h) {
        rAmt[1] += speed[1];
        if (rAmt[1] == 360) {
            rAmt[1] = 0;
        } 
}   
public void updateHour(int w, int h) {
        rAmt[2] += speed[2];
        if (rAmt[2] == 360) {
            rAmt[2] = 0;
        } 
}   

}

这是扩展JPanel的父类:

/** 
 * Digital Clock view base classes
 */
abstract class DigitalClockView extends JPanel 
{
protected int second = 0;
protected int minute = 0;
protected int hour = 0;


public void draw() 
{
    this.repaint();
}


public void updateTime(int second, int minute, int hour)
{
    this.second = second;
    this.minute = minute;
    this.hour = hour;
}

public abstract void paint(Graphics g);
}

当我使用菜单栏时,我的菜单按钮显示在右侧。这几乎就像它只是克隆左侧的视图并再次显示在右侧。这是为什么?

1 个答案:

答案 0 :(得分:2)

  

super.repaint()

不要这样做,因为在绘画方法中调用重绘可能会带来危险。在super.paint(g)覆盖内调用paint(Graphics g)方法。

或者更好的是,不要覆盖paint,而是覆盖您的JPanel的paintComponent(Graphics g)方法并致电super.paintComponent(g)。对于图形,您必须调用与重写方法相同的超级方法,并且您不会这样做。


一次又一次,你应该避免使用null布局,因为这会使非常不灵活的GUI,虽然它们在一个平台上看起来很好但在大多数其他平台或屏幕分辨率上看起来很糟糕且很难更新并保持。