【问题标题】:Repainting a Swing component produce an awful result重绘 Swing 组件会产生糟糕的结果
【发布时间】:2015-05-16 14:02:37
【问题描述】:

我“绘制”了一个组件来制作一种旋钮,因为我没有找到一种方法来拥有一个“圆形 JSlider”。我使用抗锯齿来获得良好的效果。当我用鼠标按下组件时,我会修改光标位置并要求组件重新绘制。然后,问题出现了:我repain的结果很糟糕!

如果我只在释放鼠标时要求重新绘制,结果似乎保持正确。但是,如果我在设置时不“连续”重新绘制组件,那么设置旋钮值会更加复杂。

导致问题的“重绘”方法位于类末尾的 run 方法中。

有人已经遇到这个问题了吗?可以使用什么样的解决方案来解决它? 这是我正在使用的代码:

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.PointerInfo;
import java.awt.RadialGradientPaint;
import java.awt.RenderingHints;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;

import javax.swing.JFrame;
import javax.swing.JPanel;


public class Knob extends JPanel implements MouseListener {
int length, originX, originY, centerX, centerY, width, height, diameter, squareLength;
int minorTick, majorTick, xTick, yTick, xCursor, yCursor;
int xMouse, yMouse, xMouseOrigin, yMouseOrigin;
float yDeltaMouse;
double angleOrigin, angleRange, angle;
double angleCursorOrigin;
double angleCursorInitial;
Color backgroundColor, knobColor;
boolean mousePressed;
Thread t;

Knob () {
    System.out.println("Knob");
    angleCursorOrigin=0.5;
    angleCursorInitial=0.5;
    knobColor =new Color(0,255,0,255);      
    minorTick=9;
    majorTick=3;

    this.addMouseListener(this);
}

public void paintComponent (Graphics g) {
    width=this.getWidth()/10*10;
    height=this.getHeight()/10*10;

    Graphics2D g2D = (Graphics2D)g;
    System.setProperty("awt.useSystemAAFontSettings", "on");
    System.setProperty("swing.aatext", "true");
    g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

    if (width>height) {
        length=height;
    } else {
        length=width;
    }
    centerX=width/2;
    centerY=height/2;

    g.setColor(Color.BLACK);
    squareLength = (int )(length*0.9);
    originX=(width-squareLength)/2;
    originY=(height-squareLength)/2;

    /*
    //-45 = (-(Math.PI)/4)
    angleOrigin= -45;
    // 270 = (3*(Math.PI)/2)
    angleRange=270;
    //g.drawRect(originX, originY, squareLength, squareLength);
    //g.fillArc(originX, originY, squareLength, squareLength, (int)angleOrigin, (int)angleRange);
    for (int i=0; i<minorTick ; i++) {
        angle=((i*angleRange/(minorTick-1))+angleOrigin)-7;
        //System.out.println(angle*360/(2*Math.PI));
        xTick= (int) (centerX+Math.cos(angle)*squareLength/2);
        yTick= (int) (centerY-Math.sin(angle)*squareLength/2);
        //g.drawLine(centerX, centerY, xTick, yTick);
        //g.fillArc(originX, originY, squareLength, squareLength, (int)angle, (int)14);
    }
    */

    angleOrigin=-(Math.PI)/4;
    angleRange=3*(Math.PI)/2;       
    g2D.setStroke(new BasicStroke(length/50+1));        
    for (int i=0; i<minorTick ; i++) {
        angle=i*angleRange/(minorTick-1)+angleOrigin;
        //System.out.println(angle*360/(2*Math.PI));
        xTick= (int) (centerX+Math.cos(angle)*squareLength/2);
        yTick= (int) (centerY-Math.sin(angle)*squareLength/2);
        //g.drawLine(centerX, centerY, xTick, yTick);
        g2D.draw (new Line2D.Float(centerX, centerY, xTick, yTick));
    }

    backgroundColor = this.getBackground();
    g.setColor(backgroundColor);
    diameter=(int)(length*0.8);
    originX=(width-diameter)/2;
    originY=(height-diameter)/2;
    g.fillOval(originX, originY, diameter, diameter);


    /*
    RadialGradientPaint gp;
    Point2D center= new Point2D.Float(width/2, height/2);
    diameter=(int)(length*0.75);
    originX=(width-diameter)/2;
    originY=(height-diameter)/2;
    float radius=diameter/2;        
    float[] dist = {0.7f, 1f};
    Color[] colors = {Color.BLUE, Color.GRAY};
    gp=new RadialGradientPaint(center, radius, dist, colors);
    g2D.setPaint(gp);       
    g2D.fillOval(originX,originY,diameter,diameter);
    */
    diameter=(int)(length*0.75);
    originX=(width-diameter)/2;
    originY=(height-diameter)/2;
    g.setColor(Color.GRAY);
    g.fillOval(originX,originY,diameter,diameter);

    diameter=(int)(length*0.6);
    originX=(width-diameter)/2;
    originY=(height-diameter)/2;
    g.setColor(knobColor);
    g.fillOval(originX,originY,diameter,diameter);

    g2D.setStroke(new BasicStroke(length/50+3));
    angle=(2*Math.PI)*(0.75-angleCursorOrigin*0.75)+angleOrigin;
    xCursor= (int) (centerX+Math.cos(angle)*length*0.35);
    yCursor= (int) (centerY-Math.sin(angle)*length*0.35);
    g.setColor(Color.GRAY);
    g2D.draw (new Line2D.Float(centerX, centerY, xCursor, yCursor));

}

@Override
public void mouseClicked(MouseEvent arg0) {
    // TODO Auto-generated method stub
    //System.out.println("Bouton : "+arg0.getButton());

}

@Override
public void mouseEntered(MouseEvent arg0) {
    // TODO Auto-generated method stub

}

@Override
public void mouseExited(MouseEvent arg0) {
    // TODO Auto-generated method stub

}

@Override
public void mousePressed(MouseEvent arg0) {
    // TODO Auto-generated method stub
    //System.out.println("Bouton : "+arg0.getButton());
    PointerInfo pointer = MouseInfo.getPointerInfo();
    Point mouseLocation = pointer.getLocation();
    xMouseOrigin = (int) mouseLocation.getX();
    yMouseOrigin = (int) mouseLocation.getY();
    if (arg0.getButton()==MouseEvent.BUTTON1) {
        mousePressed=true;
        t= new Thread(new TrackPosition());
        t.start();
    } else if (arg0.getButton()==MouseEvent.BUTTON3) {
        angleCursorOrigin=angleCursorInitial;
        repaint();
    }       
}

@Override
public void mouseReleased(MouseEvent arg0) {
    // TODO Auto-generated method stub
    mousePressed=false;
    //System.out.println("Mouse released");

    repaint();

}

class TrackPosition implements Runnable {

    @Override
    public void run() {
        // TODO Auto-generated method stub
        while (mousePressed==true) {
            PointerInfo pointer = MouseInfo.getPointerInfo();
            Point mouseLocation = pointer.getLocation();
            yMouse = (int) mouseLocation.getY();
            yDeltaMouse=(float)(yMouse-yMouseOrigin)/100;
            angleCursorOrigin=angleCursorOrigin+yDeltaMouse;
            yMouseOrigin=yMouse;
            if (angleCursorOrigin >=1) {
                angleCursorOrigin=1;
            } else if (angleCursorOrigin <= 0) {
                angleCursorOrigin=0;
            }
            //This repaint is a problem if I "uncomment" it
            //repaint();
        }

    }

}

/**
 * @param args
 */
public static void main(String[] args) {
    // TODO Auto-generated method stub
    JFrame frame = new JFrame();
    frame.setSize(300,90);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setContentPane(new Knob());
    frame.setVisible(true);

}

}

【问题讨论】:

  • 让我们从您没有调用 super.paintComponent 的事实开始,然后再谈一下您的“跟踪线程”已经过时且不需要的事实。您可以改用 MouseMotionListener

标签: java swing components repaint antialiasing


【解决方案1】:

让我们从在您的paintComponent 方法中执行自定义绘画之前不调用super.paintComponent 的事实开始。

Painting in AWT and SwingPerforming Custom Painting了解更多详情

然后转移到这个事实,即您的“鼠标跟踪线程”是多余的,实际上并不是必需的。相反,您应该使用MouseMotionListener,有关详细信息,请参阅How to Write a Mouse Listener

这将使您无需在本地和屏幕上下文之间进行转换。

【讨论】:

    猜你喜欢
    • 2014-06-30
    • 2013-11-14
    • 2012-08-23
    • 2016-11-02
    • 2017-06-25
    • 2022-07-13
    • 1970-01-01
    • 2022-12-20
    • 2011-11-26
    相关资源
    最近更新 更多