NullPointerException with JTextPane
| Author |
Message |
|
daveray
Joined: Thu Feb 02, 2012 5:41 am Posts: 2
|
 NullPointerException with JTextPane
Hi, If I have a JTextPane inside a MigLayout inside a BoxLayout, I get a NullPointerException. Am I doing something wrong, or is this a bug? Setting a preferred size (any dimension) on the panel with the MigLayout seems to be a workaround. I've reproduced this with both Mig 3.7.4 and 4.2. Here's the code: Code: import javax.swing.BoxLayout; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JTextPane; import javax.swing.SwingUtilities;
import net.miginfocom.swing.MigLayout;
public class MigTest {
public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() {
@Override public void run() { swingMain(); }}); }
private static void swingMain() { final JPanel vertical = new JPanel(); vertical.setLayout(new BoxLayout(vertical, BoxLayout.Y_AXIS));
final JPanel migPanel = new JPanel(); migPanel.setLayout(new MigLayout());
migPanel.add(new JTextPane(), "");
vertical.add(migPanel);
final JFrame frame = new JFrame(); frame.setContentPane(vertical); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack(); frame.setVisible(true); }
}
and here's the stacktrace: Code: Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException at javax.swing.BoxLayout.preferredLayoutSize(BoxLayout.java:282) at java.awt.Container.preferredSize(Container.java:1599) at java.awt.Container.getPreferredSize(Container.java:1584) at javax.swing.JComponent.getPreferredSize(JComponent.java:1636) at javax.swing.JRootPane$RootLayout.preferredLayoutSize(JRootPane.java:900) at java.awt.Container.preferredSize(Container.java:1599) at java.awt.Container.getPreferredSize(Container.java:1584) at javax.swing.JComponent.getPreferredSize(JComponent.java:1636) at java.awt.BorderLayout.preferredLayoutSize(BorderLayout.java:702) at java.awt.Container.preferredSize(Container.java:1599) at java.awt.Container.getPreferredSize(Container.java:1584) at net.miginfocom.swing.MigLayout.adjustWindowSize(Unknown Source) at net.miginfocom.swing.MigLayout.layoutContainer(Unknown Source) at net.miginfocom.swing.MigLayout.preferredLayoutSize(Unknown Source) at java.awt.Container.preferredSize(Container.java:1599) at java.awt.Container.getPreferredSize(Container.java:1584) at javax.swing.JComponent.getPreferredSize(JComponent.java:1636) at javax.swing.BoxLayout.checkRequests(BoxLayout.java:464) at javax.swing.BoxLayout.preferredLayoutSize(BoxLayout.java:281) at java.awt.Container.preferredSize(Container.java:1599) at java.awt.Container.getPreferredSize(Container.java:1584) at javax.swing.JComponent.getPreferredSize(JComponent.java:1636) at javax.swing.JRootPane$RootLayout.preferredLayoutSize(JRootPane.java:900) at java.awt.Container.preferredSize(Container.java:1599) at java.awt.Container.getPreferredSize(Container.java:1584) at javax.swing.JComponent.getPreferredSize(JComponent.java:1636) at java.awt.BorderLayout.preferredLayoutSize(BorderLayout.java:702) at java.awt.Container.preferredSize(Container.java:1599) at java.awt.Container.getPreferredSize(Container.java:1584) at java.awt.Window.pack(Window.java:706) at org.darevay.migtest.MigTest.swingMain(MigTest.java:38) at org.darevay.migtest.MigTest.access$0(MigTest.java:23) at org.darevay.migtest.MigTest$1.run(MigTest.java:19) at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209) at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:677) at java.awt.EventQueue.access$000(EventQueue.java:85) at java.awt.EventQueue$1.run(EventQueue.java:638) at java.awt.EventQueue$1.run(EventQueue.java:636) at java.security.AccessController.doPrivileged(Native Method) at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87) at java.awt.EventQueue.dispatchEvent(EventQueue.java:647) at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:296) at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:211) at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:201) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:196) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:188) at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
|
| Thu Feb 02, 2012 5:48 am |
|
 |
|
MiG Support
Site Admin
Joined: Mon Dec 06, 2004 4:24 pm Posts: 2485 Location: Sweden
|
 Re: NullPointerException with JTextPane
Hello,
The NPE seems to be in BoxLayout, not MigLayout.
Cheers, Mikael
|
| Fri Feb 03, 2012 3:09 pm |
|
 |
|
daveray
Joined: Thu Feb 02, 2012 5:41 am Posts: 2
|
 Re: NullPointerException with JTextPane
Thanks for replying. The NPE is indeed encountered in BoxLayout, but replace MigLayout in the example with any other layout (Box, Flow, Border, Grid, etc) and everything works as expected. This is why it seemed like a MigLayout issue to me.
|
| Thu Feb 09, 2012 9:21 pm |
|
 |
|
SemajThorgot
Joined: Wed Feb 22, 2012 5:21 pm Posts: 1
|
 Re: NullPointerException with JTextPane
The bug reported by daveray is not isolated. We are having the exact same issue, which only occurs with MigLayouts inside of BoxLayouts. Ours seems to occur with JOptionPanes, but BasicOptionPaneUI uses a BoxLayout internally. Here is the exception we're seeing: Code: java.lang.NullPointerException at javax.swing.BoxLayout.preferredLayoutSize(Unknown Source) at javax.swing.plaf.basic.BasicOptionPaneUI.getPreferredSize(Unknown Source) at javax.swing.JComponent.getPreferredSize(Unknown Source) at java.awt.BorderLayout.preferredLayoutSize(Unknown Source) at java.awt.Container.preferredSize(Unknown Source) at java.awt.Container.getPreferredSize(Unknown Source) at javax.swing.JComponent.getPreferredSize(Unknown Source) at javax.swing.JRootPane$RootLayout.preferredLayoutSize(Unknown Source) at java.awt.Container.preferredSize(Unknown Source) at java.awt.Container.getPreferredSize(Unknown Source) at javax.swing.JComponent.getPreferredSize(Unknown Source) at java.awt.BorderLayout.preferredLayoutSize(Unknown Source) at java.awt.Container.preferredSize(Unknown Source) at java.awt.Container.getPreferredSize(Unknown Source) at net.miginfocom.swing.MigLayout.adjustWindowSize(Unknown Source) at net.miginfocom.swing.MigLayout.layoutContainer(Unknown Source) at net.miginfocom.swing.MigLayout.preferredLayoutSize(Unknown Source) at java.awt.Container.preferredSize(Unknown Source) at java.awt.Container.getPreferredSize(Unknown Source) at javax.swing.JComponent.getPreferredSize(Unknown Source) at net.miginfocom.swing.SwingComponentWrapper.getLayoutHashCode(Unknown Source) at net.miginfocom.swing.MigLayout.checkCache(Unknown Source) at net.miginfocom.swing.MigLayout.getSizeImpl(Unknown Source) at net.miginfocom.swing.MigLayout.minimumLayoutSize(Unknown Source) at java.awt.Container.minimumSize(Unknown Source) at java.awt.Container.getMinimumSize(Unknown Source) at javax.swing.JComponent.getMinimumSize(Unknown Source) at java.awt.GridBagLayout.GetLayoutInfo(Unknown Source) at java.awt.GridBagLayout.getLayoutInfo(Unknown Source) at java.awt.GridBagLayout.minimumLayoutSize(Unknown Source) at java.awt.Container.minimumSize(Unknown Source) at java.awt.Container.getMinimumSize(Unknown Source) at javax.swing.JComponent.getMinimumSize(Unknown Source) at java.awt.BorderLayout.minimumLayoutSize(Unknown Source) at java.awt.Container.minimumSize(Unknown Source) at java.awt.Container.getMinimumSize(Unknown Source) at javax.swing.JComponent.getMinimumSize(Unknown Source) at java.awt.BorderLayout.minimumLayoutSize(Unknown Source) at java.awt.Container.minimumSize(Unknown Source) at java.awt.Container.getMinimumSize(Unknown Source) at javax.swing.JComponent.getMinimumSize(Unknown Source) at javax.swing.BoxLayout.checkRequests(Unknown Source) at javax.swing.BoxLayout.preferredLayoutSize(Unknown Source) at javax.swing.plaf.basic.BasicOptionPaneUI.getPreferredSize(Unknown Source) at javax.swing.JComponent.getPreferredSize(Unknown Source) at java.awt.BorderLayout.preferredLayoutSize(Unknown Source) at java.awt.Container.preferredSize(Unknown Source) at java.awt.Container.getPreferredSize(Unknown Source) at javax.swing.JComponent.getPreferredSize(Unknown Source) at javax.swing.JRootPane$RootLayout.preferredLayoutSize(Unknown Source) at java.awt.Container.preferredSize(Unknown Source) at java.awt.Container.getPreferredSize(Unknown Source) at javax.swing.JComponent.getPreferredSize(Unknown Source) at java.awt.BorderLayout.preferredLayoutSize(Unknown Source) at java.awt.Container.preferredSize(Unknown Source) at java.awt.Container.getPreferredSize(Unknown Source) at java.awt.Window.pack(Unknown Source) at javax.swing.JOptionPane.initDialog(Unknown Source) at javax.swing.JOptionPane.createDialog(Unknown Source) at javax.swing.JOptionPane.showOptionDialog(Unknown Source) at javax.swing.JOptionPane.showMessageDialog(Unknown Source) at javax.swing.JOptionPane.showMessageDialog(Unknown Source) ... When the MigLayout is replaced with other layouts, it works fine (just like for daveray). The panel that is inside the JOptionPane is too complex to post code here, but suffice it to say it is a JPanel used for custom message dialogs that uses a MigLayout. The call is a simple call to JOptionPane.showMessageDialog() that is done in the event dispatch thread. Unfortunately, the error only occurs in certain environments. In fact, another programmer has had the code work consistently fine in his IDE, but it consistently throws the exception when run separately as an executable, on the same computer. It would seem to be JRE-dependent, but he's using the same version of the JDK as the JRE he's running outside.
|
| Wed Feb 22, 2012 6:15 pm |
|
 |
|
uckelman
Joined: Tue Dec 30, 2008 6:26 pm Posts: 20
|
 Re: NullPointerException with JTextPane
We're seeing something similar: Code: java.lang.reflect.InvocationTargetException: null at java.awt.EventQueue.invokeAndWait(Unknown Source) ~[na:1.6.0_26] at javax.swing.SwingUtilities.invokeAndWait(Unknown Source) ~[na:1.6.0_26] at VASSAL.tools.DialogUtils$1.run(DialogUtils.java:69) ~[Vengine.jar:na] at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) [na:1.6.0_26] at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source) [na:1.6.0_26] at java.util.concurrent.FutureTask.run(Unknown Source) [na:1.6.0_26] at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source) [na:1.6.0_26] at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) [na:1.6.0_26] at java.lang.Thread.run(Unknown Source) [na:1.6.0_26] java.lang.NullPointerException: null at javax.swing.BoxLayout.preferredLayoutSize(Unknown Source) ~[na:1.6.0_26] at javax.swing.plaf.basic.BasicOptionPaneUI.getPreferredSize(Unknown Source) ~[na:1.6.0_26] at javax.swing.JComponent.getPreferredSize(Unknown Source) ~[na:1.6.0_26] at java.awt.BorderLayout.preferredLayoutSize(Unknown Source) ~[na:1.6.0_26] at java.awt.Container.preferredSize(Unknown Source) ~[na:1.6.0_26] at java.awt.Container.getPreferredSize(Unknown Source) ~[na:1.6.0_26] at javax.swing.JComponent.getPreferredSize(Unknown Source) ~[na:1.6.0_26] at javax.swing.JRootPane$RootLayout.preferredLayoutSize(Unknown Source) ~[na:1.6.0_26] at java.awt.Container.preferredSize(Unknown Source) ~[na:1.6.0_26] at java.awt.Container.getPreferredSize(Unknown Source) ~[na:1.6.0_26] at javax.swing.JComponent.getPreferredSize(Unknown Source) ~[na:1.6.0_26] at java.awt.BorderLayout.preferredLayoutSize(Unknown Source) ~[na:1.6.0_26] at java.awt.Container.preferredSize(Unknown Source) ~[na:1.6.0_26] at java.awt.Container.getPreferredSize(Unknown Source) ~[na:1.6.0_26] at net.miginfocom.swing.MigLayout.adjustWindowSize(Unknown Source) ~[miglayout-4.0-swing.jar:4.0] at net.miginfocom.swing.MigLayout.layoutContainer(Unknown Source) ~[miglayout-4.0-swing.jar:4.0] at net.miginfocom.swing.MigLayout.preferredLayoutSize(Unknown Source) ~[miglayout-4.0-swing.jar:4.0] at java.awt.Container.preferredSize(Unknown Source) ~[na:1.6.0_26] at java.awt.Container.getPreferredSize(Unknown Source) ~[na:1.6.0_26] at javax.swing.JComponent.getPreferredSize(Unknown Source) ~[na:1.6.0_26] at java.awt.GridBagLayout.GetLayoutInfo(Unknown Source) ~[na:1.6.0_26] at java.awt.GridBagLayout.getLayoutInfo(Unknown Source) ~[na:1.6.0_26] at java.awt.GridBagLayout.preferredLayoutSize(Unknown Source) ~[na:1.6.0_26] at java.awt.Container.preferredSize(Unknown Source) ~[na:1.6.0_26] at java.awt.Container.getPreferredSize(Unknown Source) ~[na:1.6.0_26] at javax.swing.JComponent.getPreferredSize(Unknown Source) ~[na:1.6.0_26] at java.awt.BorderLayout.preferredLayoutSize(Unknown Source) ~[na:1.6.0_26] at java.awt.Container.preferredSize(Unknown Source) ~[na:1.6.0_26] at java.awt.Container.getPreferredSize(Unknown Source) ~[na:1.6.0_26] at javax.swing.JComponent.getPreferredSize(Unknown Source) ~[na:1.6.0_26] at java.awt.BorderLayout.preferredLayoutSize(Unknown Source) ~[na:1.6.0_26] at java.awt.Container.preferredSize(Unknown Source) ~[na:1.6.0_26] at java.awt.Container.getPreferredSize(Unknown Source) ~[na:1.6.0_26] at javax.swing.JComponent.getPreferredSize(Unknown Source) ~[na:1.6.0_26] at javax.swing.BoxLayout.checkRequests(Unknown Source) ~[na:1.6.0_26] at javax.swing.BoxLayout.preferredLayoutSize(Unknown Source) ~[na:1.6.0_26] at javax.swing.plaf.basic.BasicOptionPaneUI.getPreferredSize(Unknown Source) ~[na:1.6.0_26] at javax.swing.JComponent.getPreferredSize(Unknown Source) ~[na:1.6.0_26] at java.awt.BorderLayout.preferredLayoutSize(Unknown Source) ~[na:1.6.0_26] at java.awt.Container.preferredSize(Unknown Source) ~[na:1.6.0_26] at java.awt.Container.getPreferredSize(Unknown Source) ~[na:1.6.0_26] at javax.swing.JComponent.getPreferredSize(Unknown Source) ~[na:1.6.0_26] at javax.swing.JRootPane$RootLayout.preferredLayoutSize(Unknown Source) ~[na:1.6.0_26] at java.awt.Container.preferredSize(Unknown Source) ~[na:1.6.0_26] at java.awt.Container.getPreferredSize(Unknown Source) ~[na:1.6.0_26] at javax.swing.JComponent.getPreferredSize(Unknown Source) ~[na:1.6.0_26] at java.awt.BorderLayout.preferredLayoutSize(Unknown Source) ~[na:1.6.0_26] at java.awt.Container.preferredSize(Unknown Source) ~[na:1.6.0_26] at java.awt.Container.getPreferredSize(Unknown Source) ~[na:1.6.0_26] at java.awt.Window.pack(Unknown Source) ~[na:1.6.0_26] at javax.swing.JOptionPane.initDialog(Unknown Source) ~[na:1.6.0_26] at javax.swing.JOptionPane.createDialog(Unknown Source) ~[na:1.6.0_26] at javax.swing.JOptionPane.createDialog(Unknown Source) ~[na:1.6.0_26] at VASSAL.tools.swing.DetailsDialog.showDialog(DetailsDialog.java:96) ~[Vengine.jar:na] at VASSAL.tools.ProblemDialog$3.run(ProblemDialog.java:245) ~[Vengine.jar:na] at java.awt.event.InvocationEvent.dispatch(Unknown Source) ~[na:1.6.0_26] at java.awt.EventQueue.dispatchEventImpl(Unknown Source) ~[na:1.6.0_26] at java.awt.EventQueue.access$000(Unknown Source) ~[na:1.6.0_26] at java.awt.EventQueue$1.run(Unknown Source) ~[na:1.6.0_26] at java.awt.EventQueue$1.run(Unknown Source) ~[na:1.6.0_26] at java.security.AccessController.doPrivileged(Native Method) ~[na:1.6.0_26] at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source) ~[na:1.6.0_26] at java.awt.EventQueue.dispatchEvent(Unknown Source) ~[na:1.6.0_26] at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source) ~[na:1.6.0_26] at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source) ~[na:1.6.0_26] at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source) ~[na:1.6.0_26] at java.awt.EventDispatchThread.pumpEvents(Unknown Source) ~[na:1.6.0_26] at java.awt.EventDispatchThread.pumpEvents(Unknown Source) ~[na:1.6.0_26] at java.awt.EventDispatchThread.run(Unknown Source) ~[na:1.6.0_26]
Unfortunately, all we have is stack traces from user bug reports. It's apparenlty not a threading problem, as the exception which is the root cause is happening on the EDT. We're setting "hidemode 3" on the MigLayout, and there is JScrollPane set to be invisible in it (among other things). I can provide the code in and around the two lines of my code in the stack trace if that would help any.
|
| Sun May 20, 2012 7:55 am |
|
 |
|
MiG Support
Site Admin
Joined: Mon Dec 06, 2004 4:24 pm Posts: 2485 Location: Sweden
|
 Re: NullPointerException with JTextPane
Ok, I will revisit this for the next release.
Cheers, Mikae
|
| Sun May 20, 2012 10:47 pm |
|
 |
|
uckelman
Joined: Tue Dec 30, 2008 6:26 pm Posts: 20
|
 Re: NullPointerException with JTextPane
MiG Support wrote: Ok, I will revisit this for the next release.
Cheers, Mikae Any progress on this problem? It's now our second-most reported open bug.
|
| Mon Jul 30, 2012 10:08 pm |
|
 |
|
MiG Support
Site Admin
Joined: Mon Dec 06, 2004 4:24 pm Posts: 2485 Location: Sweden
|
 Re: NullPointerException with JTextPane
I have now looked at it again. Unfortunately there's not much we can do. The code is perfectly legal and there is no threading issue from our part. The bug must be in Swing or a threading issue on your part.
Since we can't reproduce the problem it's impossible for us to debug. You do have the source code for MigLayout though and it should be fairly simple to try modifications on the code and see what works.
Cheers, Mikael
|
| Tue Jul 31, 2012 11:57 am |
|
 |
|
uckelman
Joined: Tue Dec 30, 2008 6:26 pm Posts: 20
|
 Re: NullPointerException with JTextPane
MiG Support wrote: I have now looked at it again. Unfortunately there's not much we can do. The code is perfectly legal and there is no threading issue from our part. The bug must be in Swing or a threading issue on your part.
Since we can't reproduce the problem it's impossible for us to debug. You do have the source code for MigLayout though and it should be fairly simple to try modifications on the code and see what works.
Cheers, Mikael I can reproduce the problem every time with the test case posted at the top of this topic. There's no threading problem in that test case. Every method call is run on the EDT with the exception of SwingUtilities.invokeLater(). I'm looking at the source for JDK 1.7: Attachment:
File comment: BoxLayout.java
BoxLayout.java [20.64 KiB]
Downloaded 74 times
The NPE occurs on line 301 in BoxLayout.preferredLayoutSize(): Code: size = new Dimension(xTotal.preferred, yTotal.preferred); I've verified in a debugger that both xTotal and yTotal are null here, while xChildren and yChildren are nonnull. All of xTotal, yTotal, xChildren, and yChildren are private to BoxLayout, nulled in invalidateLayout(), and none of them are assigned initial values. The only other place where xTotal, yTotal, xChildren, and yChildren are assigned to is in checkRequests(), and if checkRequests is entered while xChildren or yChildren is null, I see no way (other than an exception happening in the middle of checkRequests() which we don't see because it is swallowed by the EDT) for any of xTotal, yTotal, xChildren, or yChildren to be null when checkRequests() returns. That is, so far as I can see, based on the code in front of me, the only time that xTotal and yTotal can be null while xChildren and yChildren are nonnull is while lines 475-496 are executing, or if there is an exception we don't see that happens while those lines are executing. This is very strange. The test case is so simple that either this is a Swing bug or a MigLayout bug. If it is a Swing bug, then we can't rely on it ever being fixed, so shouldn't MigLayout contain a workaround for it?
|
| Tue Jul 31, 2012 2:42 pm |
|
 |
|
uckelman
Joined: Tue Dec 30, 2008 6:26 pm Posts: 20
|
 Re: NullPointerException with JTextPane
I think I see what the problem is now. Here's the stack trace I get with the test case: Code: Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException at javax.swing.BoxLayout.preferredLayoutSize(BoxLayout.java:301) at java.awt.Container.preferredSize(Container.java:1788) at java.awt.Container.getPreferredSize(Container.java:1773) at javax.swing.JComponent.getPreferredSize(JComponent.java:1653) at javax.swing.JRootPane$RootLayout.preferredLayoutSize(JRootPane.java:917) at java.awt.Container.preferredSize(Container.java:1788) at java.awt.Container.getPreferredSize(Container.java:1773) at javax.swing.JComponent.getPreferredSize(JComponent.java:1653) at java.awt.BorderLayout.preferredLayoutSize(BorderLayout.java:719) at java.awt.Container.preferredSize(Container.java:1788) at java.awt.Container.getPreferredSize(Container.java:1773) at net.miginfocom.swing.MigLayout.adjustWindowSize(Unknown Source) at net.miginfocom.swing.MigLayout.layoutContainer(Unknown Source) at net.miginfocom.swing.MigLayout.preferredLayoutSize(Unknown Source) at java.awt.Container.preferredSize(Container.java:1788) at java.awt.Container.getPreferredSize(Container.java:1773) at javax.swing.JComponent.getPreferredSize(JComponent.java:1653) at javax.swing.BoxLayout.checkRequests(BoxLayout.java:483) at javax.swing.BoxLayout.preferredLayoutSize(BoxLayout.java:300) at java.awt.Container.preferredSize(Container.java:1788) at java.awt.Container.getPreferredSize(Container.java:1773) at javax.swing.JComponent.getPreferredSize(JComponent.java:1653) at javax.swing.JRootPane$RootLayout.preferredLayoutSize(JRootPane.java:917) at java.awt.Container.preferredSize(Container.java:1788) at java.awt.Container.getPreferredSize(Container.java:1773) at javax.swing.JComponent.getPreferredSize(JComponent.java:1653) at java.awt.BorderLayout.preferredLayoutSize(BorderLayout.java:719) at java.awt.Container.preferredSize(Container.java:1788) at java.awt.Container.getPreferredSize(Container.java:1773) at java.awt.Window.pack(Window.java:809) at Test.swingMain(Test.java:34) at Test.access$000(Test.java:9) at Test$1.run(Test.java:14) at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:251) at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:701) at java.awt.EventQueue.access$000(EventQueue.java:102) at java.awt.EventQueue$3.run(EventQueue.java:662) at java.awt.EventQueue$3.run(EventQueue.java:660) at java.security.AccessController.doPrivileged(Native Method) at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76) at java.awt.EventQueue.dispatchEvent(EventQueue.java:671) at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:244) at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:163) at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:151) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:147) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:139) at java.awt.EventDispatchThread.run(EventDispatchThread.java:97)
I said above that the only way other than a swallowed exception for xTotal and yTotal to be null while xChildren and yChildren are nonnull is for lines 475-496 of checkRequests() to be running. This is exactly what's happening. This frame Code: at javax.swing.BoxLayout.checkRequests(BoxLayout.java:483)
is below this frame Code: at javax.swing.BoxLayout.preferredLayoutSize(BoxLayout.java:301)
in the stack trace. Line 483 is one of the places where xChildren and yChildren are set, but xTotal and yTotal are not. Line 483 is Code: Dimension typ = c.getPreferredSize();
which ultimately causes preferredLayoutSize() to be called from within checkRequests()---but this time the body of checkRequests() is skipped because neither xChildren nor yChildren are null. So, that's the bug. BoxLayout.preferredLayoutSize() is ultimately calling itself. I can't tell if this is a bug in Swing that Swing lets this happen, or if it's a bug in MigLayout that MigLayout tells Swing to do it. Mikael, now that you have more information, can I get your thoughts on the problem once again?
|
| Tue Jul 31, 2012 3:06 pm |
|
 |
|
uckelman
Joined: Tue Dec 30, 2008 6:26 pm Posts: 20
|
 Re: NullPointerException with JTextPane
Has anyone looked further at what needs to be changed in MigLayout to fix this bug? I don't understand the internals of MigLayout well enough to be able to submit a patch, but the previous post shows precisely the code path along which the bug happens.
Mikael, please have another look at what I've said above. I cannot see any way this could be a threading problem in the test case, and I've had reports of this bug across various version of Java. It might be a Swing bug, but in that case, shouldn't MigLayout have a workaround for that?
|
| Mon Sep 17, 2012 5:40 pm |
|
 |
|
uckelman
Joined: Tue Dec 30, 2008 6:26 pm Posts: 20
|
 Re: NullPointerException with JTextPane
In net.miginfocom.swing.MigLayout at line 617, we have this: Code: if (c instanceof JTextArea || c instanceof JEditorPane || (c instanceof JComponent && Boolean.TRUE.equals(((JComponent)c).getClientProperty("migLayout.dynamicAspectRatio")))) { layoutContainer(parent); break; }
In my test case, the MigLayout is set on a JPanel which contains a JTextPane. In the case where I see a NullPointerException, the stack trace passes through line 618, and in that case, c is the JTextPane and parent is the JPanel. What's going wrong when layoutContainer is called on the JPanel is this: layoutContainer calls adjustWindowSize at 556. adjustWindowSize at 575 gets the Window which is the ancestor of the JPanel, and then at 579 getPreferredSize() is called on that Window. But higher up in the stack trace, we also have getPreferredSize() being called on that Window----we reached this point while trying to calculate the Window's preferred size. What is the purpose of calling layoutContainer(parent) at 618 for parents of JTextAreas, JEditorPanes, or components set to have a dynamic aspect ratio? How is this intended to work?
|
| Tue Oct 30, 2012 11:59 pm |
|
 |
|
uckelman
Joined: Tue Dec 30, 2008 6:26 pm Posts: 20
|
 Re: NullPointerException with JTextPane
Mikael, would you please comment on what you intended the code from net.miginfocom.swing.MigLayout which I quoted in the previous post to do? While I have the code for MigLayout, the code does not contain your intent. What are lines 614-622 for? If I comment them out, my test case no longer causes a NullPointerException, but surely you wrote those lines for some reason. What was it?
|
| Sat Dec 08, 2012 2:22 am |
|
 |
|
MiG Support
Site Admin
Joined: Mon Dec 06, 2004 4:24 pm Posts: 2485 Location: Sweden
|
 Re: NullPointerException with JTextPane
That code does a re-layout for the known components that has a with-height dependency. Swing doesn't have a notion this kind of relationship so we have to make a best effort. JavaFX has solved this.
Cheers, Mikael
|
| Sat Dec 08, 2012 12:07 pm |
|
 |
|
uckelman
Joined: Tue Dec 30, 2008 6:26 pm Posts: 20
|
 Re: NullPointerException with JTextPane
MiG Support wrote: That code does a re-layout for the known components that has a with-height dependency. Swing doesn't have a notion this kind of relationship so we have to make a best effort. JavaFX has solved this.
Cheers, Mikael Thanks. I think I have a patch for you now. Re-laying out works when some parent of the panel using MigLayout and containing the JTextPane has any of the following layouts: BorderLayout, CardLayout, FlowLayout, GridLayout, GridBagLayout, GroupLayout, SpringLayout. This is because for none of these layouts is there any way for preferredLayoutSize() to be called recursively on the same layout object. (I also tested ScrollPaneLayout and ViewportLayout via switching the outer JPanel to a JScrollPane, which was fine.) Re-layout fails with BoxLayout and OverlayLayout. The reason is as follows: Suppose we have panel A with a BoxLayout which contains panel B with a MigLayout, and panel B contains a JTextPane. Now we pack() the window containing A, which causes preferred sizes for the children of that window to be calculated. getPreferredSize() is called on A, which then causes preferredLayoutSize() to be called on A's BoxLayout for the first time. A's BoxLayout then calls getPreferredSize() for A's child B, and B's getPreferredSize() calls preferredLayoutSize() on its layout, which is a MigLayout. Everything is as expected to this point. MigLayout, seeing that one of B's children is a JTextPane, now restarts layout all the way at the top of the component tree. This means that getPreferredSize() is called on A again, which then causes preferredLayoutSize() to be called on A's BoxLayout---but the first call to preferredLayoutSize() on that same BoxLayout has not yet completed---that frame is above us in the stack trace. The reason that calling BoxLayout.preferredLayoutSize() recursively is a problem is that BoxLayout.preferredLayoutSize() sets several private member variables for the BoxLayout, and at the point from which BoxLayout.preferredLayoutSize() is called recursively, only some of those variables have been set. This means that the BoxLayout is in an inconsistent state when the second call to preferredLayoutSize() happens, because the first call has not been allowed to finish. (The same analysis applies to OverlayLayout.) I've attached two patches. The first patch checks whether there is a BoxLayout or OverlayLayout between the MigLayout's parent and the Window it all lives in, and if so, bails out before calling getPreferredSize() on the Window. This is perhaps a bit crude, but it does avoid the recursion problem and seems to give me proper layouts in the cases I've tried. The second patch calls invalidateLayout() on the two problem layouts and their containers instead of giving up. I tried this on a lark, and honestly I'm a bit surprised that it appears to work---but since it does, this might be a better solution than the first patch, as it lets the preferred size calculation go through from top to bottom.
|
| Sat Dec 08, 2012 7:54 pm |
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot post attachments in this forum
|
|