Почему Synth продолжает выдавать исключения NullPointerException при попытке применить стиль?

Всякий раз, когда я пытаюсь применить стиль к JMenu или JMenuItem (через Synth), я получаю множество исключений NullPointerException при каждом наведении курсора на JMenuItems или на само JMenu, трассировка стека не дает мне никакой полезной информации и не дает указать где-нибудь на любой из моих исходных файлов.

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

это синтетический файл LookAndFeel.xml:

<?xml version="1.0" encoding="UTF-8"?>
<synth>

    <style id="menuBarStyle">
        <state>
            <color value="GRAY" type="BACKGROUND"/>
        </state>
    </style>
    <bind style="menuBarStyle" type="region" key="MenuBar"/>

    <style id="menuStyle">
        <insets top="5" bottom="3" right="10" left="10"/>
        <state>
            <color value="RED" type="BACKGROUND"/>
        </state>
    </style>
    <bind style="menuStyle" type="region" key="Menu"/>

    <style id="menuItemStyle">
        <insets top="5" bottom="5" left="10" right="3"/>
        <state>
            <color value="GREEN" type="BACKGROUND"/>
        </state>
    </style>
    <bind style="menuItemStyle" type="region" key="MenuItem"/>

    <style id="menuItemAcceleratorStyle">
        <state>
            <color value="GRAY" type="BACKGROUND"/>
        </state>
    </style>
    <bind style="menuItemAcceleratorStyle" type="region" key="MenuItem"/>

</synth>

Вот как я загружаю файл:

 private void initUI() {
        try {
            SynthLookAndFeel laf = new SynthLookAndFeel();
            laf.load(getClass().getClassLoader().getResourceAsStream("LookAndFeel.xml"), getClass());
            UIManager.setLookAndFeel(laf);
        } catch (ParseException e) {
            e.printStackTrace();
        } catch (UnsupportedLookAndFeelException e) {
            e.printStackTrace();
        }
    }

И это трассировка стека (печатается многократно, когда происходит взаимодействие со стилизованными компонентами):

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
    at sun.font.FontDesignMetrics$MetricsKey.init(FontDesignMetrics.java:217)
    at sun.font.FontDesignMetrics.getMetrics(FontDesignMetrics.java:286)
    at sun.swing.SwingUtilities2.getFontMetrics(SwingUtilities2.java:1113)
    at javax.swing.JComponent.getFontMetrics(JComponent.java:1626)
    at sun.swing.MenuItemLayoutHelper.reset(MenuItemLayoutHelper.java:125)
    at javax.swing.plaf.synth.SynthMenuItemLayoutHelper.<init>(SynthMenuItemLayoutHelper.java:119)
    at javax.swing.plaf.synth.SynthGraphicsUtils.paint(SynthGraphicsUtils.java:501)
    at javax.swing.plaf.synth.SynthMenuItemUI.paint(SynthMenuItemUI.java:281)
    at javax.swing.plaf.synth.SynthMenuItemUI.update(SynthMenuItemUI.java:245)
    at javax.swing.JComponent.paintComponent(JComponent.java:780)
    at javax.swing.JComponent.paint(JComponent.java:1056)
    at javax.swing.JComponent.paintChildren(JComponent.java:889)
    at javax.swing.JComponent.paint(JComponent.java:1065)
    at javax.swing.JComponent.paintChildren(JComponent.java:889)
    at javax.swing.JComponent.paint(JComponent.java:1065)
    at javax.swing.JComponent.paintChildren(JComponent.java:889)
    at javax.swing.JComponent.paint(JComponent.java:1065)
    at javax.swing.JLayeredPane.paint(JLayeredPane.java:586)
    at javax.swing.JComponent.paintChildren(JComponent.java:889)
    at javax.swing.JComponent.paint(JComponent.java:1065)
    at javax.swing.JComponent.paintToOffscreen(JComponent.java:5210)
    at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(RepaintManager.java:1579)
    at javax.swing.RepaintManager$PaintManager.paint(RepaintManager.java:1502)
    at javax.swing.RepaintManager.paint(RepaintManager.java:1272)
    at javax.swing.JComponent._paintImmediately(JComponent.java:5158)
    at javax.swing.JComponent.paintImmediately(JComponent.java:4969)
    at javax.swing.RepaintManager$4.run(RepaintManager.java:831)
    at javax.swing.RepaintManager$4.run(RepaintManager.java:814)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
    at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:814)
    at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:789)
    at javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:738)
    at javax.swing.RepaintManager.access$1200(RepaintManager.java:64)
    at javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1732)
    at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:756)
    at java.awt.EventQueue.access$500(EventQueue.java:97)
    at java.awt.EventQueue$3.run(EventQueue.java:709)
    at java.awt.EventQueue$3.run(EventQueue.java:703)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:726)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)

Я подозреваю, что проблема связана с самим Synth, а не с моим кодом, я полагаю, я попытался поискать в Интернете и в документации по Java и учебные пособия по Synth, но не смог найти ничего подходящего.

PS: я вызываю этот метод перед тем, как начать отображать или создавать какие-либо компоненты свинга.

1 ответ

Решение

Обновление (и весьма вероятный ответ):

Я нашел способ решить проблему, однако вопрос остается в такте, так как у меня до сих пор нет никакого объяснения, почему проблема возникает, но у меня есть гипотеза.

Решение:

Очевидно, стиль шрифта должен быть применен ко всем элементам, чтобы файл XML не отображал ошибки, это необходимый минимум для решения проблемы, которую я обнаружил после некоторых экспериментов:

<style id="defaultElementStyle">
    <font name="Verdana" size="12"/>
</style>
<bind style="defaultElementStyle" type="region" key=".*"/>


гипотеза

Поскольку:

  • NullPointerException генерировалось всякий раз, когда происходило изменение в состоянии JMenu/JMenuItems.
  • Проблема была решена путем установки глобального свойства шрифта

Я могу с уверенностью заключить, что источником проблемы был вызов некоторой функции, которая пыталась прочитать свойство шрифта измененных состояний *(вероятно, из одного из классов в трассировке стека). Однако в упомянутом выше случае шрифт по умолчанию для состояний был неопределен в XML-файле (null), что привело к исключению NullPointerException, тогда, возможно, класс был достаточно умен, чтобы прибегнуть к некоторому шрифту по умолчанию (который отображается), и это предотвратило программа от полного сбоя и сбоя. Любые мысли по этому вопросу будут высоко оценены, так как кажется, что проблема вообще не является общей и требует дальнейшего изучения.

Другие вопросы по тегам