我在使用一个实现 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 一直被调用,这导致了这种行为。有人知道如何解决这个问题吗?一种指定何时应该调用或“刷新率”的方法会很好......
问候,亚历克斯