目前我正在使用自定义JFrame
创建自定义JPanel
。渲染JFrame
没有闪烁,但是当我渲染自定义`JPanel时,组件闪烁。我的代码:
我的代码JFrame
:
public void paint(Graphics g) {
Dimension d = getSize();
Graphics og = g;
g = b.getGraphics();
//background
g.setColor(SConstants.ct.FRAME_BACKGROUND());
g.fillRect(SConstants.ct.FRAME_FRAME_WIDTH(), SConstants.ct.FRAME_FRAME_HEIGHT(), d.width - SConstants.ct.FRAME_FRAME_WIDTH(), d.height - SConstants.ct.FRAME_FRAME_WIDTH());
//frame
if(isFocused()){
g.setColor(SConstants.ct.FRAME_FOCUSED_FRAME());
}else{
g.setColor(SConstants.ct.FRAME_UNFOCUSED_FRAME());
}
//top
g.fillRect(0, 0, d.width, SConstants.ct.FRAME_FRAME_HEIGHT());
//left
g.fillRect(0, 0, SConstants.ct.FRAME_FRAME_WIDTH(), d.height);
//bottom
g.fillRect(0, d.height - SConstants.ct.FRAME_FRAME_WIDTH(), d.width, SConstants.ct.FRAME_FRAME_WIDTH());
//right
g.fillRect(d.width - SConstants.ct.FRAME_FRAME_WIDTH(), 0, SConstants.ct.FRAME_FRAME_WIDTH(), d.height);
//icon
if(getIconImage() != null)
g.drawImage(getIconImage(), 15, SConstants.ct.FRAME_FRAME_HEIGHT() / 2 - getIconImage().getHeight(null) / 2, null);
Graphics2D g2d = (Graphics2D) g;
g2d.setFont(SConstants.ct.FRAME_FONT());
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(Color.BLACK);
g2d.drawString(getTitle(), d.width / 2 - g2d.getFontMetrics().stringWidth(getTitle()) / 2, SConstants.ct.FRAME_FRAME_HEIGHT() / 2 - g2d.getFontMetrics().getHeight() / 2 + g2d.getFontMetrics().getAscent());
getContentPane().paint(og);
og.drawImage(b, 0, 0, null);
}
我正在设置contentPane
,如下所示:
getRootPane().setLayout(null);
SPanel cp = new SPanel();
cp.setBounds(SConstants.ct.FRAME_FRAME_WIDTH(), SConstants.ct.FRAME_FRAME_HEIGHT(), getWidth() - SConstants.ct.FRAME_FRAME_WIDTH() * 2, getHeight() - SConstants.ct.FRAME_FRAME_HEIGHT() - SConstants.ct.FRAME_FRAME_WIDTH());
setContentPane(cp);
SPanel
是这样的:
public void paint(Graphics g) {
paintComponent(g);
}
protected void paintComponent(Graphics g) {
//paintComponents(g);
for(Component c : getComponents())
c.paint(g);
}
我正在渲染一个SLabel
:
public void paint(Graphics g) {
Graphics2D g2d = (Graphics2D)g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.drawString(text, getX() + SConstants.ct.LABEL_SPACING_HORIZONTAL(), getY());
}
public Dimension getPreferredSize() {
Rectangle2D d = getGraphics().getFontMetrics(SConstants.ct.LABEL_FONT()).getStringBounds(text, getGraphics());
int w = (int)(d.getWidth() + SConstants.ct.LABEL_SPACING_HORIZONTAL() * 2);
int h = (int)(d.getHeight() + SConstants.ct.LABEL_SPACING_VERTICAL() * 2);
return new Dimension(w, h);
}
可运行的示例:https://drive.google.com/file/d/0B8czlxc22-xqOHlPdUZxV2dkMjQ/edit?usp=sharing
有人知道为什么SLabel
会闪烁吗?
答案 0 :(得分:4)
您似乎无法理解Swing的工作原理或Swing / AWT中的绘画效果......
此...
public class SMain {
public static void main(String[] args) throws Exception {
//...
while(true){
sf.repaint();
Thread.sleep((int)(1000.0 / 24.0));
}
}
}
是个坏主意... Swing使用被动渲染模型,这意味着更新会在需要时发生,因为您似乎没有对UI的状态进行更改,这只是添加对你的系统施加更大的压力。
如果调用正确,也可以阻止您的UI永久更新。
getRootPane().setLayout(null);
为什么呢?为什么? JRootPane
拥有自己的布局管理流程,可确保contentPane
提供包含框架内的所有空间减去菜单栏的空间(如果提供),您不会提供了,是的,默认实现将允许contentPane
占用所有可用空间......
setSize
可能会连续多次调用,最好只是将b
无效(将其设置为null
)并仅在需要时创建它(当paint
被称为),但这引出了为什么?
为什么不让内容窗格为您执行此操作...
pack
会自动调整contentPane
的大小,如果你真的让JRootPane
做它的工作......
paint
完成了许多重要的工作,而且你已经规避了大部分工作,这将导致你无法解决问题和结果....
例如,在尝试绘制内容窗格之前,您没有翻译Graphics
上下文,这意味着内容绘制的内容可能会覆盖什么内容你画了(即标题)。
你最好使用......
BorderLayout.NORTH
位置,其余内容包含在另一个容器中BorderLayout.CENTER
默认位置contentPane
JRootPane
以提供所需的布局JFrame
实现自己的外观代理并自行绘制边框EmptyBorder
上的contentPane
为标题提供空间...... 请注意,MouseListener
和MouseMotionListener
可能被容器层次结构中较高的组件阻止,这些组件实现其中一个或两个接口
paint
做了很多重要的工作,包括但不限于绘制组件,边框和组件(以及实现双缓冲),但是你决定绕过它们并且做你自己的事......
paintComponent
假设绘制组件的背景,而不是它的孩子。这已由paint
和paintChildren
以及paintComponents
子组件也可以独立于其父级绘制......
请注意,Component
是一个重量级(AWT)组件,它的绘画要求与轻量级(Swing)组件的要求不同,事实上,您应该避免添加重量轻的组件以减轻重量容器....
Component
已定义paint(Graphics)
...
默认情况下,重量级组件也不是双缓冲的...这意味着更新可能会导致闪烁...因此您的问题......
"但我已经双重缓冲框架" ...抱歉让你失望,但组件可以并且通常是独立于父母绘制的,因此它们可能不会被绘制为部分父母的更新...
你似乎并不了解绘画在AWT / Swing中是如何运作的。请查看Painting in AWT and Swing了解更多详情......
您似乎也不了解Swing和AWT之间的差异。虽然Swing位于AWT之上,但它有自己的框架要求,这与AWT和一些有意义的方式不同......
您似乎正在尝试实现自己的框架......为什么,我不知道,显然在Swing和AWT上最近20多年的开发还不够好或者什么......
您可以考虑查看Modifying the Look and Feel并使用UI委托API来实现您要执行的操作...
你有两个选择,你可以学习理解当前框架(Swing / AWT)如何工作并在其中工作以实现你的目标,或者在你的余生中度过追逐怪异,无法解释的问题和错误。
您还可以考虑查看JavaFX,它允许您通过CSS修改外观...