I’m having troubles with a class that implements JPanel that seems to kill my CPU, even when application is idle and there are no background threads or anything like it.
This class looks like this:
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;
}
}
And I use it in another class that has a JFrame, that looks like this:
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);
}
}
Now I use the both this way in a main method:
cw = new CommencingWindow();
cw.setVisible(true);
Nothing strange or complex so far, now if I go to the shell and run ‘top’, this is the output after the setVisible call:

As you can see, CPU usage is ridiculous for such a simple app and it oscilates between 90-80 for ever…I’m afraid that the GradientPanel.paintComponent is being called all the time and this is causing the behavior. Does anybody know how to fix this? A way to specify when it should be call or “refresh rate” would be nice…
Regards,
Alex
The problem comes from this line:
which triggers eventually a repaint, causing your component to repaint constantly and eating up your CPU.
To fix this, remove that line and try to invoke it from somewhere else, like the constructor of the panel for example.
Generally, you should not modify your component during paintComponent to avoid these kind of issues. You should only perform painting operations.