1

我在使用一个实现 JPanel 的类时遇到了问题,它似乎会杀死我的 CPU,即使应用程序处于空闲状态并且没有后台线程或类似的东西也是如此。

这个类看起来像这样:

public class GradientPanel extends JPanel {

/**
 * Serial ID
 */
private static final long serialVersionUID = 1L;

/**
 * Starting color for the gradient
 */
private Color startColor;

/**
 * Ending color for the gradient
 */
private Color endColor;

/**
 * Border Color
 */
private Color borderColor;


@Override
/**
 * This is the method that actually paints the Panel 
 * 
 * @param   g   The graphics object used to do the rendering
 * 
 */
protected void paintComponent( Graphics g ) {

    //check that the opacitiy is not set to true first
    if ( !isOpaque( ) ) {

        super.paintComponent( g );  
        return;
    }

    Graphics2D g2d = (Graphics2D) g;

    //to get height and width of the component  
    int w = getWidth();     
    int h = getHeight();

    /*generating gradient pattern from two colors*/
    GradientPaint gp = new GradientPaint( 0, 0, startColor, 0, h, endColor );
    g2d.setPaint( gp ); //set gradient color to graphics2D object
    g2d.fillRect( 0, 0, w, h ); //filling color
    setOpaque( false );
    //Generating Titleborder
    TitledBorder title;
    title= BorderFactory.createTitledBorder(new LineBorder(borderColor, 1, true), null, javax.swing.border.TitledBorder.LEFT, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("Arial", 0, 16), Color.BLACK);
    super.setBorder(title);  //appling border to JPanel
    super.paintComponent( g );
    setOpaque( true );
}

/**
 * Getters and setters 
 */
public Color getStartColor() {
    return startColor;
}


public void setStartColor(Color startColor) {
    this.startColor = startColor;
}


public Color getEndColor() {
    return endColor;
}


public void setEndColor(Color endColor) {
    this.endColor = endColor;
}

public Color getBorderColor() {
    return borderColor;
}


public void setBorderColor(Color borderColor) {
    this.borderColor = borderColor;
}

}

我在另一个具有 JFrame 的类中使用它,如下所示:

public class CommencingWindow extends JFrame {

/**
 * The serial ID
 */
private static final long serialVersionUID = 1L;


/**
 * Content Panel
 */
private GradientPanel contentPane;


/**
 * Window specific attributes
 */
private GraphicsConfiguration translucencyCapableGC;

/**
 * Flag to indicate if frame supports shaping
 */
private boolean isShapingSupported;

/**
 * Flag used to indicate if frame supports opacity
 */
private boolean isOpacityControlSupported;

/**
 * Used to display an infinite progress bar
 */
private JLabel progress;


/**
 * Constructor
 * @throws MalformedURLException 
 * 
 */
public CommencingWindow(){

    //change default Java icon for a nicer one
    java.net.URL url = ClassLoader.getSystemResource("res/images/smarcos.png");
    Toolkit kit = Toolkit.getDefaultToolkit();
    Image img = kit.createImage(url);
    this.setIconImage(img);
    this.setUndecorated(true);
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.setTitle("SMarcos Coach");
    kit = this.getToolkit();
    isShapingSupported = AWTUtilitiesWrapper.isTranslucencySupported(AWTUtilitiesWrapper.PERPIXEL_TRANSPARENT);
    isOpacityControlSupported = AWTUtilitiesWrapper.isTranslucencySupported(AWTUtilitiesWrapper.TRANSLUCENT);
    AWTUtilitiesWrapper.isTranslucencySupported(AWTUtilitiesWrapper.PERPIXEL_TRANSLUCENT);
    GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
    //get translucency properties of the current screen device
    translucencyCapableGC = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
    if (!AWTUtilitiesWrapper.isTranslucencyCapable(translucencyCapableGC)) {
        translucencyCapableGC = null;

        GraphicsEnvironment env =
                GraphicsEnvironment.getLocalGraphicsEnvironment();
        GraphicsDevice[] devices = env.getScreenDevices();

        for (int i = 0; i < devices.length && translucencyCapableGC == null; i++) {
            GraphicsConfiguration[] configs = devices[i].getConfigurations();
            for (int j = 0; j < configs.length && translucencyCapableGC == null; j++) {
                if (AWTUtilitiesWrapper.isTranslucencyCapable(configs[j])) {
                    translucencyCapableGC = configs[j];
                }
            }
        }
        if (translucencyCapableGC == null) {
        }
    }

    // Determine what the default GraphicsDevice can support.
    GraphicsDevice[] gs = ge.getScreenDevices();
    Insets in = kit.getScreenInsets(gs[0].getDefaultConfiguration());
    Dimension d = kit.getScreenSize();
    //Get max screen width and height
    int max_width = (d.width - in.left - in.right);
    int max_height = (d.height - in.top - in.bottom);
    //calculate frame width and height
    int frameWidth = Math.min(max_width, 300);
    int frameHeight = Math.min(max_height, 100);
    //center frame relative to the screen
    int frameX = (int) (max_width - frameWidth) / 2;
    int frameY = (int) (max_height - frameHeight ) / 2;
    this.setSize(frameWidth, frameHeight);//whatever size you want but smaller the insets
    this.setLocation(frameX, frameY);

    //apply rounded corners to frame, if possible
    if (isShapingSupported) {
        Shape  shape = new RoundRectangle2D.Float(0, 0, frameWidth, frameHeight, 30, 30);
        AWTUtilitiesWrapper.setWindowShape(this, shape);
    }
    //apply some transparency, if possible
    if (isOpacityControlSupported) {
        AWTUtilitiesWrapper.setWindowOpacity(this, 1.0f);
    }

    //add the content panel to the frame
    contentPane = new GradientPanel();
    contentPane.setStartColor(new Color(170, 191, 236));
    contentPane.setEndColor(new Color(52, 101, 206));
    contentPane.setBorderColor(new Color(170, 191, 236));
    contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
    setContentPane(contentPane);
    contentPane.setLayout(null);

    //Smarcos Label
    JLabel lblSmarcos = new JLabel();
    String lblSmarcosText = "<html><font align=\"center\" size=\"5\" color=\"D1D1D1\">SMARCOS COACH</font></html>";
    lblSmarcos.setText(lblSmarcosText);
    lblSmarcos.setBounds(67, 14, 257, 30);
    contentPane.add(lblSmarcos);

    //Add a label to ask for the verifier
    JLabel lblVerifier = new JLabel();
    String lblVerifierText = "<html><font align=\"center\" size=\"3\" color=\"D1D1D1\">Trying to connect to DirectLife Oauth service...</font></html>";
    lblVerifier.setText(lblVerifierText);
    lblVerifier.setBounds(60, 45, 240, 30);
    contentPane.add(lblVerifier);


}

}

现在我在一个主要方法中使用这两种方式:

        cw = new CommencingWindow();
    cw.setVisible(true);

到目前为止没有什么奇怪或复杂的,现在如果我进入 shell 并运行“top”,这是 setVisible 调用后的输出:

在此处输入图像描述

正如你所看到的,对于这样一个简单的应用程序来说,CPU 使用率是荒谬的,它永远在 90-80 之间波动......我担心 GradientPanel.paintComponent 一直被调用,这导致了这种行为。有人知道如何解决这个问题吗?一种指定何时应该调用或“刷新率”的方法会很好......

问候,亚历克斯

4

1 回答 1

10

问题来自这一行:

 super.setBorder(title);  //appling border to JPanel

这最终会触发重绘,导致您的组件不断重绘并占用您的 CPU。

要解决此问题,请删除该行并尝试从其他地方调用它,例如面板的构造函数。

通常,您不应在paintComponent 期间修改组件以避免此类问题。您应该只执行绘画操作。

于 2012-05-30T07:19:47.507 回答