java - 为什么这个 JLabel 不断重绘?

标签 java swing paint

我有一个项目,当它存在时似乎会不断重新绘制,导致 CPU 每当它出现在我的任何窗口中时都会出现峰值。它直接继承自 JLabel,与屏幕上的其他 JLabel 不同,它具有红色背景和边框。我不知道为什么它会不同到足以不断重绘。调用堆栈如下所示:

Thread [AWT-EventQueue-1] (Suspended (breakpoint at line 260 in sItem)) 
    sItem.paint(Graphics) line: 260 
    sItem(JComponent).paintToOffscreen(Graphics, int, int, int, int, int, int) line: 5124   
    RepaintManager$PaintManager.paintDoubleBuffered(JComponent, Image, Graphics, int, int, int, int) line: 1475 
    RepaintManager$PaintManager.paint(JComponent, JComponent, Graphics, int, int, int, int) line: 1406  
    RepaintManager.paint(JComponent, JComponent, Graphics, int, int, int, int) line: 1220   
    sItem(JComponent)._paintImmediately(int, int, int, int) line: 5072  
    sItem(JComponent).paintImmediately(int, int, int, int) line: 4882   
    RepaintManager.paintDirtyRegions(Map<Component,Rectangle>) line: 803    
    RepaintManager.paintDirtyRegions() line: 714    
    RepaintManager.seqPaintDirtyRegions() line: 694 [local variables unavailable]   
    SystemEventQueueUtilities$ComponentWorkRequest.run() line: 128  
    InvocationEvent.dispatch() line: 209    
    summitEventQueue(EventQueue).dispatchEvent(AWTEvent) line: 597  
    summitEventQueue(SummitHackableEventQueue).dispatchEvent(AWTEvent) line: 26 
    summitEventQueue.dispatchEvent(AWTEvent) line: 62   
    EventDispatchThread.pumpOneEventForFilters(int) line: 269   
    EventDispatchThread.pumpEventsForFilter(int, Conditional, EventFilter) line: 184    
    EventDispatchThread.pumpEventsForHierarchy(int, Conditional, Component) line: 174   
    EventDispatchThread.pumpEvents(int, Conditional) line: 169  
    EventDispatchThread.pumpEvents(Conditional) line: 161   
    EventDispatchThread.run() line: 122 [local variables unavailable]   

它基本上只是不断地一遍又一遍地点击它,就像我可以按继续一样快。这个特定标签的“唯一”代码大致如下所示:

bgColor = OurColors.clrWindowTextAlert;
textColor = Color.white;
setBackground(bgColor);
setOpaque(true);
setSize(150, getHeight());
Border border_warning = BorderFactory.createCompoundBorder(
        BorderFactory.createMatteBorder(1, 1, 1, 1, OurColors.clrXBoxBorder),
        Global.border_left_margin);
setBorder(border_warning);

它显然做得更多,但该特定 block 仅存在于导致尖峰/连续重绘的这些标签。

知道为什么它会继续重绘这个特定标签吗?

最佳答案

缺少很多代码,但我会进行有根据的猜测。

该类的“唯一”部分可能在负责呈现标签的代码部分中。如果这是真的,那么调用所有这些 setXXX() 方法可能会使对象变脏,这意味着它需要重新绘制,这将再次进入此代码块,然后将使用公共(public)接口(interface)更新小部件,然后将使对象变脏,导致循环重复。

最终这样的事情会耗尽所有空闲周期,导致 CPU 为显然没有做太多事情的标签而达到最大值。

尝试在渲染循环之外的地方设置适当的值。大多数这些项目看起来都可以在构造函数中设置。

--- 确认是setBorder(...) 后编辑---

设置新边框可能会触发重新计算小部件的边界框,因为边框可能比以前的边框更​​大或更小。该边框和新边框可能包含与旧边框不同的屏幕呈现方式(升高、降低等)。

这些项目都不需要在渲染部分设置,但我敢打赌,对于其他项目,会进行初步检查以查看新项目是否 equals(...) 旧项目。如果是这样,那么(作为优化)不设置脏位并且不向渲染引擎发出刷新请求。

有了边框,这样的检查必须涵盖几个元素,包括一些编译字节码(实际绘图指令)。由于在考虑边界时检查相等性不再是简单的优化,他们很可能根本不尝试检查相等性而只是标记要重新绘制的小部件。

关于java - 为什么这个 JLabel 不断重绘?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2791392/

相关文章:

java - 执行按钮单击操作时更新标签文本 (Java)

java - Java repaint() 是如何工作的?

java - 同一级别的 If 语句如何同时在 Android/Java 程序中执行?

Android:如何只为图像的特定部分填充颜色?

java - 尝试获取授权 token 时出现未知的 GoogleAuthException

初始化数组对象时出现java.lang.ArrayIndexOutOfBoundsException

java - Java/Swing 有什么好的 "cube grid"组件吗?

java - 在我的 jar 中将要访问的 .dll 放在哪里

java - 如何添加当前在 java 套接字服务器上运行的程序列表?

Java Swing 多线程管理与观察者模式