Closed. This question needs
debugging details。它当前不接受答案。
想改善这个问题吗?
Update the question,所以它是
on-topic,用于堆栈溢出。
5年前关闭。
当前,我正在使用自定义
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
闪烁吗?
您似乎不了解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永远更新。
SFrame ...
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
完成
子组件也可以独立于父组件进行绘制...
SComponent ...
请注意,
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修改外观...
我是一名优秀的程序员,十分优秀!