Почему этот JLabel постоянно перекрашивается? - PullRequest
1 голос
/ 08 мая 2010

У меня есть элемент, который постоянно перекрашивается, когда он существует, в результате чего процессор начинает всплывать, когда он находится в любом из моих окон. Он напрямую наследуется от JLabel и, в отличие от других JLabels на экране, имеет красный фон и рамку. Я понятия не имею, почему это будет достаточно отличаться, чтобы постоянно перекрашивать. CallCack выглядит так:

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);

Очевидно, что он делает больше, но этот конкретный блок существует только для тех меток, которые вызывают всплеск / непрерывную перерисовку.

Есть идеи, почему он будет перекрашивать этот конкретный ярлык?

Ответы [ 3 ]

4 голосов
/ 08 мая 2010

Много кода отсутствует, но я сделаю обоснованное предположение.

«Уникальная» часть класса, вероятно, находится в разделе кода, отвечающем за отображение метки. Если это так, то вызов всех этих методов setXXX (), вероятно, сделает объект грязным, что означает, что его нужно перекрасить, что снова введет этот блок кода, который затем будет использовать открытые интерфейсы, обновляющие виджет, который затем сделает объект грязным, что приведет к повторению цикла.

В конечном итоге такая вещь потребляет все запасные циклы, заставляя ЦП работать на максимуме для метки, которая, очевидно, мало что делает.

Попробуйте установить соответствующие значения в месте, которое находится за пределами цикла рендеринга. Большинство этих элементов выглядят так, как будто они могут быть установлены в конструкторе.

--- Редактировать после подтверждения, что это setBorder (...) ---

Установка новой границы, вероятно, вызовет пересчет ограничивающей рамки виджета, поскольку граница может быть больше или меньше предыдущей границы. Это и новая граница могут содержать другое представление экрана (поднятое, опущенное и т. Д.), Отличное от старого.

Ни один из этих предметов не нужно устанавливать в разделе рендеринга, но я готов поспорить, что с другими предметами делается пелимическая проверка, чтобы увидеть, является ли новый предмет equals(...) старым предметом. Если это так, то (в качестве оптимизации) грязные биты не установлены, и запрос на обновление не передается механизму рендеринга.

При наличии границы такая проверка должна охватывать несколько элементов, в том числе те, которые скомпилированы байт-кодом (собственно инструкции рисования). Поскольку проверять равенство при рассмотрении границ больше не является простой оптимизацией, скорее всего, они вообще не пытаются проверять равенство, а просто отмечают виджет для перекрашивания.

2 голосов
/ 08 мая 2010

См. Код в JComponent.setBorder ().Он сравнивает старую и новую границу, используя простое сравнение, которое всегда возвращает false, поскольку это два разных объекта.Если условие выполнено, компонент будет перекрашен.Отсюда и бесконечный цикл.

Как правило - не вызывайте какие-либо сеттеры для компонента в его методах рисования.Как вы видели, установка границы приведет к бесконечному циклу перекраски.Это может произойти с любым другим параметром, и если не в этой версии VM, возможно, в следующей.Правильный способ сделать это - изменить свойства компонента (представления) при изменении модели и позволить Swing выяснить, когда она будет перекрашена, или вызвать repaint () самостоятельно.

0 голосов
/ 08 мая 2010

Это граница.Создание границы во время каждого цикла рисования как-то заставляет его непрерывно перекрашиваться.Если я просто создаю границу один раз как закрытый объект с областью действия класса и устанавливаю его в цикле рисования, он устанавливает границу правильно и не перерисовывает непрерывно.Если кто-нибудь знает, почему это будет иметь значение, я также был бы признателен за эту информацию.Не стесняйтесь комментировать это, и я приму свой ответ, когда смогу, или добавлю новый ответ с тоннами многословия, и я приму ваш.

...