2010-05-07 2 views
1

У меня есть элемент, который, как представляется, постоянно перерисовывается, когда он существует, что приводит к тому, что CPU будет всплескиваться всякий раз, когда он находится в любом из моих окон. Он непосредственно наследуется от JLabel, и в отличие от других JLabels на экране он имеет красный фон и границу. У меня нет идеи, почему это будет достаточно для того, чтобы постоянно перекрашивать. CallStack выглядит следующим образом:Почему эта 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); 

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

Любые идеи, почему он будет перекрасить этот ярлык?

ответ

4

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

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

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

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

--- Edit после подтверждения того, что это setBorder (...) ---

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

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

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

+0

Отличные идеи, но для задействования логики требуется, чтобы они были установлены в контуре рендеринга, к сожалению. Есть все виды логики, которые заставляют вещи выглядеть/вести себя по-другому. Вы определенно находились на правильном пути, хотя создание этой границы в цикле рендеринга кажется проблемой (см. Мой ответ). Не понимаю почему. – Morinar

+1

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

+0

Я уверен, что вы правы, но этот код работает в течение 10-ти лет, и я не собираюсь бросать ключ в вещи. Спасибо за информацию о границе. – Morinar

0

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

2

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

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

+0

Прохладный, чтобы увидеть Гуру Свинг, приходящий сюда. Добро пожаловать и THX за помощь! –