I’ve got an item that appears to continuously repaint when it exists, causing the CPU to spike whenever it is in any of my windows. It directly inherits from a JLabel, and unlike the other JLabels on the screen, it has a red background and a border. I have NO idea why it would be different enough to continuously repaint. The callstack looks like this:
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]
It basically just continually hits that over and over again as fast as I can press continue. The code that is “unique” to this particular label looks approximately like this:
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);
It obviously does more, but that particular block only exists for these labels that are causing the spike/continuous repaint.
Any ideas why it would keep repainting this particular label?
Lots of the code is missing, but I’ll take an educated guess.
The “unique” part of the class is probably within a section of the code responsible for rendering the Label. If this is true, then calling all these setXXX() methods probably render the object dirty, which means it needs to be repainted, which will enter this block of code again, which will then use the public interfaces updating the widget, which will then render the object dirty, causing the cycle to repeat.
Eventually such a thing will consume all spare cycles causing the CPU to max for a label that’s obviously not doing much.
Try setting the appropriate values in a place which is outside the render loop. Most of these items look like they could be set in a constructor.
— Edit after confirmation that it’s the setBorder(…) —
Setting a new border likely triggers a recalculation of the bounding box of the widget, as a border might be larger or smaller than the previous border. That and the new border might contain a different screen presentation (raised, lowered, etc) that the old one.
None of these items need to be set in the rendering section, but I’ll bet that with the other items, a peliminary check is made to see if the new item
equals(...)the old item. If so, then (as an optimization) the dirty bits aren’t set and the request to refresh isn’t made to the rendering engine.With a border, such a check would have to cover several elements, including some which are compiled bytecode (the actual drawing instructions). Since it’s no longer a simple optimization to check equality when considering borders, odds are they don’t attempt to check for equality at all and just flag the widget for repainting.