【A Bug in BasicJideTabbedPaneUI】

This is the forum for JIDE Common Layer which is open sourced at https://github.com/jidesoft/jide-oss. Please note, JIDE technical support doesn't monitor this forum as often as other forums. Please consider subscribe for technical support for JIDE Common Layer so that you can use customer only forum to get a timely response.

Moderator: JIDE Support

Forum rules
Community driven forum for open source JIDE Common Layer. JIDE technical support doesn't monitor this forum as often as other forums. If you only use JIDE Common Layer, please consider subscribing for technical support for JIDE Common Layer so that you can use customer only forum to get a timely response.

【A Bug in BasicJideTabbedPaneUI】

Postby Neptune » Fri Apr 23, 2010 10:34 pm

My application uses the JideTabbedPane and when I launch it, an uncertain exception will throw out.See it as follows:

Caused by:
java.lang.NullPointerException at java.awt.Dimension.<init>(Dimension.java:93)
at java.awt.Component.getMaximumSize(Component.java:2617)
at java.awt.Container.getMaximumSize(Container.java:1698)
at javax.swing.JComponent.getMaximumSize(JComponent.java:1671)
at javax.swing.BoxLayout.checkRequests(BoxLayout.java:465)
at javax.swing.BoxLayout.preferredLayoutSize(BoxLayout.java:281)
...
at com.jidesoft.plaf.basic.BasicJideTabbedPaneUI#TabbedPaneLayout(BasicJideTabbedPaneUI.java:5560)
at com.jidesoft.plaf.basic.BasicJideTabbedPaneUI.calculateSize(BasicJideTabbedPaneUI.java:5527)

I open your the BasicJideTabbedPaneUI and locate it to line 5560, find that

for (int i = 0; i < _tabPane.getTabCount(); i++) {
Component component = _tabPane.getComponentAt(i);
if (component != null) {
Dimension size = zeroSize;
size = minimum ? component.getMinimumSize() :
component.getPreferredSize(); =================== line 5560, the issuse is caused here===================

if (size != null) {
cHeight = Math.max(size.height, cHeight);
cWidth = Math.max(size.width, cWidth);
}
}
}

The issue will not happen every time, so it is difficult to recur, but it appears casually.I think it is may a thread safety problem and the application invokes the 'calculateSize' method before the 'component' have its preferredSize.Would you help me to kill the bug?
Neptune
 
Posts: 11
Joined: Fri Apr 23, 2010 10:09 pm

Re: 【A Bug in BasicJideTabbedPaneUI】

Postby JIDE Support » Fri Apr 23, 2010 10:39 pm

Swing is not thread safe. You need to make sure you are updating the UI always from an event dispatching thread (EDT in short). Take a look at http://weblogs.java.net/blog/alexfromsu ... swing.html for ThreadCheckingRepaintManager which will give you a way to quickly identify any potential threading violations.

Thanks,
JIDE Software Technical Support Team
JIDE Support
Site Admin
 
Posts: 37219
Joined: Sun Sep 14, 2003 10:49 am

Re: 【A Bug in BasicJideTabbedPaneUI】

Postby Neptune » Fri Apr 23, 2010 10:59 pm

Thanks for your feeding back quickly.This is my invoke code:

public static void main(String[] args)
{
DemoFrame frame = new DemoFrame();
frame.setVisible(true);
frame.setExtendedState(DemoFrame.MAXIMIZED_BOTH);
}

The DemoFrame is very simple, in it I initialize the JideTabbedPane for 10 tabs.If I use JTabbedPane instead of JideTabbedPane, No issuse happen!
I also have try this way: If i delete the lines as follows, every things are OK.I wonder why you circle the tabbedPane's child component and get their preferredSize in Layout?

if (_tabPane.isShowTabContent()) {
for (int i = 0; i < _tabPane.getTabCount(); i++) {
Component component = _tabPane.getComponentAt(i);
if (component != null) {
Dimension size = zeroSize;
size = minimum ? component.getMinimumSize() :
component.getPreferredSize();

if (size != null) {
cHeight = Math.max(size.height, cHeight);
cWidth = Math.max(size.width, cWidth);
}
}
}
// Add content border insets to minimum size
width += cWidth;
height += cHeight;
}
Neptune
 
Posts: 11
Joined: Fri Apr 23, 2010 10:09 pm

Re: 【A Bug in BasicJideTabbedPaneUI】

Postby JIDE Support » Tue May 04, 2010 4:00 pm

Sorry for the late reponse. I tried to reproduce it however failed. May I have the test case from you if it's not complicated?

I don't think it is prohibited for layout manager to invoke component.getPreferredSize(). Something else must be wrong.

Thanks,
JIDE Software Technical Support Team
JIDE Support
Site Admin
 
Posts: 37219
Joined: Sun Sep 14, 2003 10:49 am

Re: 【A Bug in BasicJideTabbedPaneUI】

Postby Neptune » Wed May 05, 2010 6:07 am

Thanks for your reply.Now the issues appears again today.



The exception is as follows:

Exception in thread "main" java.lang.NullPointerException
at java.awt.Dimension.<init>(Dimension.java:93)
at java.awt.Component.getMaximumSize(Component.java:2617)
at java.awt.Container.getMaximumSize(Container.java:1698)
at javax.swing.JComponent.getMaximumSize(JComponent.java:1671)
at javax.swing.BoxLayout.checkRequests(BoxLayout.java:465)
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 java.awt.BorderLayout.preferredLayoutSize(BorderLayout.java:712)
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 com.jidesoft.plaf.basic.BasicJideTabbedPaneUI$TabbedPaneLayout.calculateSize(BasicJideTabbedPaneUI.java:5562)
at com.jidesoft.plaf.basic.BasicJideTabbedPaneUI$TabbedPaneLayout.preferredLayoutSize(BasicJideTabbedPaneUI.java:5529)
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 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 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 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 javax.swing.JComponent.getPreferredSize(JComponent.java:1636)
at com.jidesoft.swing.JideBoxLayout.getPreferredSizeOf(Unknown Source)
at com.jidesoft.swing.JideBoxLayout.calculateComponentSizes(Unknown Source)
at com.jidesoft.swing.JideSplitPaneLayout.calculateComponentSizes(Unknown Source)
at com.jidesoft.swing.JideBoxLayout.layoutContainer(Unknown Source)
at java.awt.Container.layout(Container.java:1421)
at java.awt.Container.doLayout(Container.java:1410)
at com.jidesoft.swing.JideSplitPane.doLayout(Unknown Source)
at java.awt.Container.validateTree(Container.java:1507)
at java.awt.Container.validateTree(Container.java:1513)
at java.awt.Container.validateTree(Container.java:1513)
at java.awt.Container.validateTree(Container.java:1513)
at java.awt.Container.validateTree(Container.java:1513)
at java.awt.Container.validateTree(Container.java:1513)
at java.awt.Container.validateTree(Container.java:1513)
at java.awt.Container.validate(Container.java:1480)
at java.awt.Window.show(Window.java:861)
at java.awt.Component.show(Component.java:1563)
at java.awt.Component.setVisible(Component.java:1515)
at java.awt.Window.setVisible(Window.java:842)
at com.nepxion.demo.DemoFrame.main(DemoFrame.java:43)
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 java.awt.BorderLayout.preferredLayoutSize(BorderLayout.java:712)
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 com.jidesoft.plaf.basic.BasicJideTabbedPaneUI$TabbedPaneLayout.calculateSize(BasicJideTabbedPaneUI.java:5562)
at com.jidesoft.plaf.basic.BasicJideTabbedPaneUI$TabbedPaneLayout.preferredLayoutSize(BasicJideTabbedPaneUI.java:5529)
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 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 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 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 javax.swing.JComponent.getPreferredSize(JComponent.java:1636)
at com.jidesoft.swing.JideBoxLayout.getPreferredSizeOf(Unknown Source)
at com.jidesoft.swing.JideBoxLayout.calculateComponentSizes(Unknown Source)
at com.jidesoft.swing.JideSplitPaneLayout.calculateComponentSizes(Unknown Source)
at com.jidesoft.swing.JideBoxLayout.layoutContainer(Unknown Source)
at java.awt.Container.layout(Container.java:1421)
at java.awt.Container.doLayout(Container.java:1410)
at com.jidesoft.swing.JideSplitPane.doLayout(Unknown Source)
at java.awt.Container.validateTree(Container.java:1507)
at java.awt.Container.validateTree(Container.java:1513)
at java.awt.Container.validateTree(Container.java:1513)
at java.awt.Container.validateTree(Container.java:1513)
at java.awt.Container.validateTree(Container.java:1513)
at java.awt.Container.validateTree(Container.java:1513)
at java.awt.Container.validateTree(Container.java:1513)
at java.awt.Container.validate(Container.java:1480)
at java.awt.Window.dispatchEventImpl(Window.java:2476)
at java.awt.Component.dispatchEvent(Component.java:4460)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)





Let you know how I use it:



public static void main(String[] args)
{
DemoCaptionSplashWindow splashWindow = new DemoCaptionSplashWindow();
splashWindow.setVisible(true);

DemoFrame frame = new DemoFrame();
frame.setExtendedState(DemoFrame.MAXIMIZED_BOTH);
frame.setVisible(true);



splashWindow.setVisible(false);
}



DemoCaptionSplashWindow is a splash for my application.It is based on Thread.

DemoFrame extends the JFrame, and there are more JideTabbedPane on it contentPane.When initializating,there are about 30 JideTabbedPanes will be added to DemoFrame and every JideTabbedPane has about 5-10 components.

I have set -Xms128m -Xmx512m parameter on the run/debug settings on the Eclipse IDE.



I have no ideas on the causes!
Neptune
 
Posts: 11
Joined: Fri Apr 23, 2010 10:09 pm

Re: 【A Bug in BasicJideTabbedPaneUI】

Postby Neptune » Wed May 05, 2010 6:29 am

The issues will not appear everytime.I have just orverride the method as belows:

public void addTab(String title, Icon icon, Component component, String toolTipText, boolean isClosable)
{
super.addTab(title, icon, component, toolTipText);
setTabClosableAt(indexOfComponent(component), isClosable);
}

I always invork this method "addTab". The line "setTabClosableAt(indexOfComponent(component), isClosable);" is the cause for my exeception?

BTW:It on JDK1.6.0

If I replace JideTabbedPane with JTabbedPane, it seems that it is OK!!

I have checked your code:
if (_tabPane.isShowTabContent()) {
for (int i = 0; i < _tabPane.getTabCount(); i++) {
Component component = _tabPane.getComponentAt(i);
if (component != null) {
Dimension size = zeroSize;
size = minimum ? component.getMinimumSize() :
component.getPreferredSize(); /////////////////////////// in this line

if (size != null) {
cHeight = Math.max(size.height, cHeight);
cWidth = Math.max(size.width, cWidth);
}
}
}
// Add content border insets to minimum size
width += cWidth;
height += cHeight;
}
Neptune
 
Posts: 11
Joined: Fri Apr 23, 2010 10:09 pm

Re: 【A Bug in BasicJideTabbedPaneUI】

Postby JIDE Support » Wed May 05, 2010 7:14 am

Yes. I do think the invocation of setTabClosableAt() does the trick. Please check if the following code could help.
Code: Select all
        final JideTabbedPane tabbedPane = new JideTabbedPane(JideTabbedPane.TOP) {
            private void superUpdateUI() {
                super.updateUI();
            }
           
            @Override
            public void updateUI() {
                SwingUtilities.invokeLater(new Runnable() {
                    public void run() {
                        superUpdateUI();
                    }
                });
            }
        };

Thanks,
JIDE Software Technical Support Team
JIDE Support
Site Admin
 
Posts: 37219
Joined: Sun Sep 14, 2003 10:49 am

Re: 【A Bug in BasicJideTabbedPaneUI】

Postby Neptune » Wed May 05, 2010 7:26 am

Many thanks!I think it will maybe help me!Let me test it.
Neptune
 
Posts: 11
Joined: Fri Apr 23, 2010 10:09 pm

Re: 【A Bug in BasicJideTabbedPaneUI】

Postby Neptune » Wed May 05, 2010 7:59 am

I have tested for many times, It works so nice.You have provided a completely way to resolve my issue.Perfectly!Thanks again.
Neptune
 
Posts: 11
Joined: Fri Apr 23, 2010 10:09 pm

Re: 【A Bug in BasicJideTabbedPaneUI】

Postby JIDE Support » Wed May 05, 2010 8:10 am

Thanks for letting us know that. Will include the code in 2.9.1 and 2.8.7.

Thanks,
JIDE Software Technical Support Team
JIDE Support
Site Admin
 
Posts: 37219
Joined: Sun Sep 14, 2003 10:49 am

Re: 【A Bug in BasicJideTabbedPaneUI】

Postby Walter Laan » Thu May 06, 2010 8:14 am

But it's that just adding a hack for the missing invokeLater in the main?

A Swing program should be started as follows (and yes the Jide demo's don't do it either :P):
Code: Select all
public static void main(String[] args) {
  SwingUtilities.invokeLater(new Runnable() {
    public void run() {
      createAndShowGUI();
    }
  });
}


More info in the tutorial (link)
Walter Laan
 
Posts: 383
Joined: Mon May 01, 2006 12:13 am

Re: 【A Bug in BasicJideTabbedPaneUI】

Postby Neptune » Sat May 08, 2010 8:38 am

The issue is already existed.It will drive me mad. :(
I have implemented this as you have told me:
Code: Select all
public void updateUI()
{
  SwingUtilities.invokeLater(new Runnable()
  {
    public void run()
    {
      MyTabbedPane.super.updateUI();
    }
  }
  );
}


Should I override the paint method?
Code: Select all
public void repaint()
{
  SwingUtilities.invokeLater(new Runnable()
  {
    public void run()
    {
      MyTabbedPane.super.repaint();
    }
  }
  );
}
Neptune
 
Posts: 11
Joined: Fri Apr 23, 2010 10:09 pm

Re: 【A Bug in BasicJideTabbedPaneUI】

Postby JIDE Support » Sat May 08, 2010 8:48 am

Sorry, do not override updateUI or repaint to call invokeLater. Do what Walter said and see if it helps.
JIDE Software Technical Support Team
JIDE Support
Site Admin
 
Posts: 37219
Joined: Sun Sep 14, 2003 10:49 am

Re: 【A Bug in BasicJideTabbedPaneUI】

Postby Neptune » Sat May 08, 2010 9:14 am

Thanks!What Walter says will impact my another feature -- the splash on application starting.

Code: Select all
public static void main(String[] args)
{
  MySplashWindow splashWindow = new MySplashWindow();
  splashWindow.setVisible(true);
      
  DemoFrame frame = new DemoFrame();
  frame.setExtendedState(DemoFrame.MAXIMIZED_BOTH);
  frame.setVisible(true);         
      
  splashWindow.setVisible(false);
}


if I I change thest to:
Code: Select all
public static void main(String[] args)
{
  MySplashWindow splashWindow = new MySplashWindow();
  splashWindow.setVisible(true);

  SwingUtility.invokelater(new Runnable()
  {
    public void run()
    {
      DemoFrame frame = new DemoFrame();
      frame.setExtendedState(DemoFrame.MAXIMIZED_BOTH);
      frame.setVisible(true);   
    }
  }
  );      
            
  splashWindow.setVisible(false);
}


The MySplashWindow will show some animation effect based on Thread, If I add invokelater, MySplashWindow will be blocked and not worked.

I wonder whether the two line will work fine together or not?

addTab(title, icon, component, toolTipText);
setTabClosableAt(indexOfComponent(component), isClosable);
Neptune
 
Posts: 11
Joined: Fri Apr 23, 2010 10:09 pm

Re: 【A Bug in BasicJideTabbedPaneUI】

Postby Neptune » Sat May 08, 2010 9:31 am

The cause is just by

Code: Select all
public void addTab(String title, Icon icon, Component component, String toolTipText, boolean isClosable)
{
  super.addTab(title, icon, component, toolTipText);
  if (isClosable)
  {   
    setTabClosableAt(indexOfComponent(component), isClosable);
  }
}


I think addTab and setTabClosableAt can not be invoked here together, for it will cause the no-safty-thread issuse.Can you tell another method to avoid this cause?
In the feature I provide the user to decide the tab can be closable then he add tab.
Neptune
 
Posts: 11
Joined: Fri Apr 23, 2010 10:09 pm

Re: 【A Bug in BasicJideTabbedPaneUI】

Postby JIDE Support » Sat May 08, 2010 8:10 pm

I probably need to have a test case in order to give you more productive suggestion as I can't reproduce it myself. I used JideTabbedPaneDemo.java and change where I create JideTabbedPane from

Code: Select all
        final JideTabbedPane tabbedPane = new JideTabbedPane(JideTabbedPane.TOP);

to

Code: Select all
        final JideTabbedPane tabbedPane = new JideTabbedPane(JideTabbedPane.TOP) {
            public void addTab(String title, Icon icon, Component component, String toolTipText, boolean isClosable) {
                super.addTab(title, icon, component, toolTipText);
                if (isClosable) {
                    setTabClosableAt(indexOfComponent(component), isClosable);
                }
            }
        };


But it works just fine.

Thanks,
JIDE Software Technical Support Team
JIDE Support
Site Admin
 
Posts: 37219
Joined: Sun Sep 14, 2003 10:49 am

Re: 【A Bug in BasicJideTabbedPaneUI】

Postby Neptune » Sat May 08, 2010 8:12 pm

I think this is a bug indeed.I have delete "setTabClosableAt(indexOfComponent(component), isClosable);", the exception is already existed.

I have studie your JideTabbedPanedemo of "Demo of JIDE Products - 2.9.1" and found these line as follows:

Code: Select all
for (int i = 0; i < titles.length; i++) {
  JScrollPane scrollPane = new JScrollPane(new JTextArea());
  scrollPane.setPreferredSize(new Dimension(530, 530));// why setPreferredSize here?
  tabbedPane.addTab(titles[i], icons[i], scrollPane);
  tabbedPane.setMnemonicAt(i, mnemonics[i]);
}


I copy your code to mine, if I delete "scrollPane.setPreferredSize(new Dimension(530, 530));", and make the titles length = 300(the tabbedPane has 300 tabs), the exception will throws out!
So the cause is that do setPreferredSize for the component before it is add to the tabbedPane.Why should I setPreferredSize, that is not a friendly method for user!
Neptune
 
Posts: 11
Joined: Fri Apr 23, 2010 10:09 pm

Re: 【A Bug in BasicJideTabbedPaneUI】

Postby JIDE Support » Sat May 08, 2010 8:55 pm

Here is my new code but still not exception for me.

Code: Select all
        for (int i = 0; i < 300; i++) {
            JScrollPane scrollPane = new JScrollPane(new JTextArea());
//            scrollPane.setPreferredSize(new Dimension(530, 530));
            tabbedPane.addTab(titles[i % titles.length], icons[i % titles.length], scrollPane);
            tabbedPane.setMnemonicAt(i, mnemonics[i % titles.length]);
        }


BTW, I set the preferred size simply because I want the tabbed pane comes up nicely. In real app, you don't have to do it as the content of each tab should come up with a preferred size.

Thanks,
JIDE Software Technical Support Team
JIDE Support
Site Admin
 
Posts: 37219
Joined: Sun Sep 14, 2003 10:49 am

Re: 【A Bug in BasicJideTabbedPaneUI】

Postby JIDE Support » Fri May 21, 2010 10:42 am

Anyway, please give 2.9.2 a try and see if that release could solve your issue.

Thanks,
JIDE Software Technical Support Team
JIDE Support
Site Admin
 
Posts: 37219
Joined: Sun Sep 14, 2003 10:49 am

Re: 【A Bug in BasicJideTabbedPaneUI】

Postby Neptune » Fri May 21, 2010 11:03 am

Finally I know I have made a stupid mistake.

Code: Select all
public static void main(String[] args)
{
  new SplashWindow().setVisible(true); // this is a Thread instance, so it will cause the no-safety-thread error.
  new DemoFrame().setVisible(true);
}


If I do what like these lines as follows:
1. delete
Code: Select all
new SplashWindow().setVisible(true);


2.do SwingUtilities.invokerLater
Code: Select all
SwingUtilities.invokerLater()
{
  public void run()
  {
    new DemoFrame().setVisible(true);
  }
}


All are ok!Thanks!
Neptune
 
Posts: 11
Joined: Fri Apr 23, 2010 10:09 pm


Return to JIDE Common Layer Open Source Project Discussion (Community Driven)

Who is online

Users browsing this forum: No registered users and 3 guests