Java 使用JTextArea时,MigLayout会导致JOption窗格中出现异常。布局很好

Java 使用JTextArea时,MigLayout会导致JOption窗格中出现异常。布局很好,java,swing,joptionpane,miglayout,Java,Swing,Joptionpane,Miglayout,下面的示例程序显示一个带有两个按钮的框架。按下第二个使用MigLayout的按钮会导致异常。使用FlowLayout的第一个按钮工作正常。似乎是MigLayout中的错误 NPE的原因是一些米格内部魔法与下面的JTextArea/JEditorPane细节有关。这可能会导致嵌套容器出现问题。某些父容器有一个在BoxLayout中保持内部状态f.i.的管理器 最简单的解决方法:不要嵌套-MigLayout设计用于控制一个大面板。在添加到optionPane等预制的特殊容器中时,这不是一个选项:在这

下面的示例程序显示一个带有两个按钮的框架。按下第二个使用MigLayout的按钮会导致异常。使用FlowLayout的第一个按钮工作正常。似乎是MigLayout中的错误


NPE的原因是一些米格内部魔法与下面的JTextArea/JEditorPane细节有关。这可能会导致嵌套容器出现问题。某些父容器有一个在BoxLayout中保持内部状态f.i.的管理器

最简单的解决方法:不要嵌套-MigLayout设计用于控制一个大面板。在添加到optionPane等预制的特殊容器中时,这不是一个选项:在这里,它有助于将textArea/editorPane包装在JScrollPane中

虽然仅仅在getter PreferredLayouuutSize中向上操纵容器层次结构看起来可疑,但不完全确定这是否是一个bug

NPE发生原因的详细信息:magic的作用是强制父容器布局查询prefSize:

public Dimension preferredLayoutSize(Container parent) {
    synchronized (parent.getTreeLock()) {
        if (lastParentSize == null
                || !parent.getSize().equals(lastParentSize)) {
            for (ComponentWrapper wrapper : ccMap.keySet()) {
                Component c = (Component) wrapper.getComponent();
                if (c instanceof JTextArea
                        || c instanceof JEditorPane
                        || (c instanceof JComponent && Boolean.TRUE
                                .equals(((JComponent) c)
                                        .getClientProperty("migLayout.dynamicAspectRatio")))) {
                    layoutContainer(parent);
                    break;
                }
            }
        }

        lastParentSize = parent.getSize();
        return getSizeImpl(parent, LayoutUtil.PREF);
    }
}
进而在AdjustWindowsSize中向下重新查询顶级容器的prefSize:

private void adjustWindowSize(ContainerWrapper parent) {
    BoundSize wBounds = lc.getPackWidth();
    BoundSize hBounds = lc.getPackHeight();

    if (wBounds == null && hBounds == null)
        return;

    Window win = ((Window) SwingUtilities.getAncestorOfClass(Window.class,
            (Component) parent.getComponent()));
    if (win == null)
        return;

    Dimension prefSize = win.getPreferredSize();
    ....
}
嵌套在BoxLayout中时,会导致重新输入checkTarget:

public Dimension preferredLayoutSize(Container target) {
    Dimension size;
    synchronized(this) {
        checkContainer(target);
        // checkRequests initializes all internal book-keeping
        checkRequests();
        // here's the NPE in the second round
        size = new Dimension(xTotal.preferred, yTotal.preferred);
    }
    ...
 }

void checkRequests() {
    // config only if not yet done earlier
    if (xChildren == null || yChildren == null) {
        // The requests have been invalidated... recalculate
        // the request information.
        int n = target.getComponentCount();
        //JW: first time around the arrays of sz are initialized
        xChildren = new SizeRequirements[n];
        yChildren = new SizeRequirements[n];
        for (int i = 0; i < n; i++) {
            Component c = target.getComponent(i);
            ....
            Dimension min = c.getMinimumSize();
            Dimension typ = c.getPreferredSize();
            ....
        }
        .... 
        // JW: never reached if c.getPref re-enters, that is xTotal remains null
        if (absoluteAxis == X_AXIS) {
            xTotal = SizeRequirements.getTiledSizeRequirements(xChildren);
            yTotal = SizeRequirements.getAlignedSizeRequirements(yChildren);
        } else {
            xTotal = SizeRequirements.getAlignedSizeRequirements(xChildren);
            yTotal = SizeRequirements.getTiledSizeRequirements(yChildren);
        }

     }
 }   

NPE的原因是一些米格内部魔法与下面的JTextArea/JEditorPane细节有关。这可能会导致嵌套容器出现问题。某些父容器有一个在BoxLayout中保持内部状态f.i.的管理器

最简单的解决方法:不要嵌套-MigLayout设计用于控制一个大面板。在添加到optionPane等预制的特殊容器中时,这不是一个选项:在这里,它有助于将textArea/editorPane包装在JScrollPane中

虽然仅仅在getter PreferredLayouuutSize中向上操纵容器层次结构看起来可疑,但不完全确定这是否是一个bug

NPE发生原因的详细信息:magic的作用是强制父容器布局查询prefSize:

public Dimension preferredLayoutSize(Container parent) {
    synchronized (parent.getTreeLock()) {
        if (lastParentSize == null
                || !parent.getSize().equals(lastParentSize)) {
            for (ComponentWrapper wrapper : ccMap.keySet()) {
                Component c = (Component) wrapper.getComponent();
                if (c instanceof JTextArea
                        || c instanceof JEditorPane
                        || (c instanceof JComponent && Boolean.TRUE
                                .equals(((JComponent) c)
                                        .getClientProperty("migLayout.dynamicAspectRatio")))) {
                    layoutContainer(parent);
                    break;
                }
            }
        }

        lastParentSize = parent.getSize();
        return getSizeImpl(parent, LayoutUtil.PREF);
    }
}
进而在AdjustWindowsSize中向下重新查询顶级容器的prefSize:

private void adjustWindowSize(ContainerWrapper parent) {
    BoundSize wBounds = lc.getPackWidth();
    BoundSize hBounds = lc.getPackHeight();

    if (wBounds == null && hBounds == null)
        return;

    Window win = ((Window) SwingUtilities.getAncestorOfClass(Window.class,
            (Component) parent.getComponent()));
    if (win == null)
        return;

    Dimension prefSize = win.getPreferredSize();
    ....
}
嵌套在BoxLayout中时,会导致重新输入checkTarget:

public Dimension preferredLayoutSize(Container target) {
    Dimension size;
    synchronized(this) {
        checkContainer(target);
        // checkRequests initializes all internal book-keeping
        checkRequests();
        // here's the NPE in the second round
        size = new Dimension(xTotal.preferred, yTotal.preferred);
    }
    ...
 }

void checkRequests() {
    // config only if not yet done earlier
    if (xChildren == null || yChildren == null) {
        // The requests have been invalidated... recalculate
        // the request information.
        int n = target.getComponentCount();
        //JW: first time around the arrays of sz are initialized
        xChildren = new SizeRequirements[n];
        yChildren = new SizeRequirements[n];
        for (int i = 0; i < n; i++) {
            Component c = target.getComponent(i);
            ....
            Dimension min = c.getMinimumSize();
            Dimension typ = c.getPreferredSize();
            ....
        }
        .... 
        // JW: never reached if c.getPref re-enters, that is xTotal remains null
        if (absoluteAxis == X_AXIS) {
            xTotal = SizeRequirements.getTiledSizeRequirements(xChildren);
            yTotal = SizeRequirements.getAlignedSizeRequirements(yChildren);
        } else {
            xTotal = SizeRequirements.getAlignedSizeRequirements(xChildren);
            yTotal = SizeRequirements.getTiledSizeRequirements(yChildren);
        }

     }
 }   

MigLayout 5.0对此进行了补偿。如果你想测试它,它在谷歌代码的后备箱里

干杯,
Mikael

MigLayout 5.0对此有补偿。如果你想测试它,它在谷歌代码的后备箱里

干杯,
Mikael

@MikaelGrev:您计划何时发布MigLayout 5.0?找不到任何计划或联系信息。@MikaelGrev:您计划何时发布MigLayout 5.0?找不到任何计划或联系信息。