Skip to main content

TabbedPane Problem

9 replies [Last post]
danko
Offline
Joined: 2008-07-18

Hi there,
I would like to make a huge number of tabs. So I set the title of the tabs to a single number.
I would prefer that tabs should have only so much space as they need to print their title. But it seems for me that TabbedPane is not designed for that. I looked at the api doc and found out that there is the methode
public void setTabTitlePrototype(java.lang.String title)
but always I call that I get an exception.
java.lang.ClassCastException
Uncaught exception java/lang/ClassCastException.
at com.sun.lwuit.TabbedPane$TabsRenderer.getListCellRendererComponent(TabbedPane.java:457)
at com.sun.lwuit.List.calculateElementSize(List.java:975)
at com.sun.lwuit.List.getElementSize(List.java:964)
at com.sun.lwuit.List.paint(List.java:723)
at com.sun.lwuit.Component.paintInternal(Component.java:632)
at com.sun.lwuit.Container.paint(Container.java:394)
at com.sun.lwuit.TabbedPane.paint(TabbedPane.java:382)
at com.sun.lwuit.Component.paintInternal(Component.java:632)
at com.sun.lwuit.Container.paint(Container.java:394)
at com.sun.lwuit.Component.paintInternal(Component.java:632)
at com.sun.lwuit.Container.paint(Container.java:394)
at com.sun.lwuit.Form.paint(Form.java:1442)
at com.sun.lwuit.Component.paintInternal(Component.java:632)
at com.sun.lwuit.Component.paintComponent(Component.java:721)
at com.sun.lwuit.Implementation.paintDirty(Implementation.java:460)
at com.sun.lwuit.Implementation.edtLoopImpl(Implementation.java:722)
at com.sun.lwuit.Implementation.mainEDTLoop(Implementation.java:678)
at com.sun.lwuit.Implementation.run(Implementation.java:632)

My code:

import javax.microedition.midlet.*;

import com.sun.lwuit.Command;
import com.sun.lwuit.Display;
import com.sun.lwuit.Form;
import com.sun.lwuit.Label;
import com.sun.lwuit.TabbedPane;
import com.sun.lwuit.events.ActionEvent;
import com.sun.lwuit.events.ActionListener;
import com.sun.lwuit.layouts.BorderLayout;

public class LwuitTestMidlet extends MIDlet implements ActionListener
{

public void startApp()
{
Display.init(this);

Form f = new Form("LWUIT TestMidlet");
f.setLayout(new BorderLayout());
f.setScrollable(false);
TabbedPane tp = new TabbedPane();

// tp.setTabTitlePrototype("XX");
tp.addTab("1", new Label("Tab 1"));
tp.addTab("2", new Label("Tab 2"));
tp.addTab("3", new Label("Tab 3"));
tp.addTab("4", new Label("Tab 4"));
tp.addTab("5", new Label("Tab 5"));
tp.addTab("6", new Label("Tab 6"));
tp.addTab("7", new Label("Tab 7"));
tp.addTab("8", new Label("Tab 8"));
tp.addTab("9", new Label("Tab 9"));
tp.addTab("10", new Label("Tab 10"));
f.addComponent(BorderLayout.CENTER, tp);
Command exitCommand = new Command("exit");
f.addCommand(exitCommand);
f.setCommandListener(this);
f.show();
}

public void pauseApp()
{
}

public void destroyApp(boolean unconditional)
{
}

public void actionPerformed(ActionEvent ae)
{
if (ae.getCommand().getCommandName().equals("exit"))
{
notifyDestroyed();
}
}
}

If I use ten tabs the label of the last one is not readable. http://666kb.com/i/b0n5cqiqk2nty0g0d.png
That there would be enough place shows that screen http://666kb.com/i/b0n5e49mn1xvemt59.png
If I only use five tabs it works perfect http://666kb.com/i/b0n5fsq1h567kj025.png

I do not want to use the workaround with the zeros. Spaces instead does not work.

Thanks,
danko

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
danko
Offline
Joined: 2008-07-18

Hi,
I found additional
http://forums.java.net/jive/thread.jspa?messageID=287704&#287704

See below how I tried to solve the problem. I am not very happy with that because if I change in my midlet by using the the number keys very fast it get stuck.
It seems for me that it is impossible to get the selected empty Container. tp.getComponentAt(0) returns a list which includes buttons but I do not have access in any way to the Hashtable tabsTable to link the buttons to the containers.

Thanks,
danko

import javax.microedition.midlet.*;

import com.sun.lwuit.Command;
import com.sun.lwuit.Container;
import com.sun.lwuit.Display;
import com.sun.lwuit.Form;
import com.sun.lwuit.Label;
import com.sun.lwuit.TabbedPane;
import com.sun.lwuit.events.ActionEvent;
import com.sun.lwuit.events.ActionListener;
import com.sun.lwuit.events.SelectionListener;
import com.sun.lwuit.layouts.BorderLayout;

public class LwuitTestMidlet extends MIDlet implements ActionListener
{

private boolean selectionChangedIgnored = false;

public void startApp()
{
Display.init(this);

Form f = new Form("LWUIT TestMidlet");
f.setLayout(new BorderLayout());
f.setScrollable(false);
final TabbedPane tp = new TabbedPane();

tp.addTab("1", new Container());
tp.addTab("2", new Container());
tp.addTab("3", new Container());
tp.addTab("4", new Container());
tp.addTab("5", new Container());
tp.addTabsListener(new SelectionListener()
{

public void selectionChanged(int o, int n)
{
if (!selectionChangedIgnored)
{
selectionChangedIgnored = true;
tp.removeTabAt(o);
tp.insertTab(Integer.toString(o + 1), null, new Container(), o);
tp.removeTabAt(n);
tp.insertTab(Integer.toString(n + 1), null, new Label("Tab " + Integer.toString(n + 1)), n);
tp.setSelectedIndex(n);
selectionChangedIgnored = false;
}
}
});

f.addComponent(BorderLayout.CENTER, tp);
Command exitCommand = new Command("exit");
f.addCommand(exitCommand);
f.setCommandListener(this);
f.show();
}

public void pauseApp()
{
}

public void destroyApp(boolean unconditional)
{
}

public void actionPerformed(ActionEvent ae)
{
if (ae.getCommand().getCommandName().equals("exit"))
{
notifyDestroyed();
}
}
}

Shai Almog

Hi,
> Hi,
> I found additional
> http://forums.java.net/jive/thread.jspa?messageID=287704&#287704
>
> See below how I tried to solve the problem. I am not very happy
> with that because if I change in my midlet by using the the number
> keys very fast it get stuck.

Its a surprise for me that you can switch the tab using the numeric
keypad, I implemented it for list and it didn't occur to me it would
(obviously) affect the tabbed pane ;-)
I just tried playing along fast with the LWUIT demos tabbed pane and
couldn't reproduce something like that, its possible a deadlock
occurs...
If you can reproduce this using a debugger (an actual freeze) just
click "pause" in the debugger and select the "thread view" and
"callstack" view. Look for the stack trace of the EDT and MIDP
threads and if if one of them has a contended monitor (this is
highlighted in NetBeans debugger).

> It seems for me that it is impossible to get the selected empty
> Container. tp.getComponentAt(0) returns a list which includes
> buttons but I do not have access in any way to the Hashtable
> tabsTable to link the buttons to the containers.

Yes this seems like an issue, I will try to add a "getTabComponentAt
(int index)" method. In the meantime the container you are looking
for is the first child of element 1 e.g.:

tabPane.addTab("1", myContainer);

((Container)tabPane.getComponentAt(1)).getComponentAt(0) == myContainer

Shai Almog
http://lwuit.blogspot.com/

[att1.html]

danko
Offline
Joined: 2008-07-18

Hi,

> Its a surprise for me that you can switch the tab
> using the numeric
> keypad, I implemented it for list and it didn't occur
> to me it would
> (obviously) affect the tabbed pane ;-)
> I just tried playing along fast with the LWUIT demos
> tabbed pane and
> couldn't reproduce something like that, its possible
> a deadlock
> occurs...
> If you can reproduce this using a debugger (an actual
> freeze) just
> click "pause" in the debugger and select the "thread
> view" and
> "callstack" view. Look for the stack trace of the EDT
> and MIDP
> threads and if if one of them has a contended monitor
> (this is
> highlighted in NetBeans debugger).

Of course I can reproduce it using a debugger.
The first three times I played around with the debugger the thread view works fine. Now the netbean debugger always throws an exception.

java.lang.IllegalThreadStateException
at com.sun.tools.jdi.JDWPException.toJDIException(JDWPException.java:45)
at com.sun.tools.jdi.ThreadReferenceImpl.suspendCount(ThreadReferenceImpl.java:145)
at org.netbeans.modules.debugger.jpda.models.JPDAThreadImpl.(JPDAThreadImpl.java:105)
at org.netbeans.modules.debugger.jpda.models.ObjectTranslation.createTranslation(ObjectTranslation.java:102)
at org.netbeans.modules.debugger.jpda.models.ObjectTranslation.translate(ObjectTranslation.java:172)
at org.netbeans.modules.debugger.jpda.JPDADebuggerImpl.getThread(JPDADebuggerImpl.java:1290)
at org.netbeans.modules.debugger.jpda.models.JPDAThreadGroupImpl.getThreads(JPDAThreadGroupImpl.java:89)
at org.netbeans.modules.debugger.jpda.models.ThreadsTreeModel.computeChildren(ThreadsTreeModel.java:155)
at org.netbeans.modules.debugger.jpda.models.ThreadsTreeModel.getChildren(ThreadsTreeModel.java:110)
at org.netbeans.spi.viewmodel.Models$DelegatingTreeModel.getChildren(Models.java:1148)
at org.netbeans.modules.debugger.jpda.ui.models.MonitorModel.getChildren(MonitorModel.java:130)
at org.netbeans.spi.viewmodel.Models$CompoundTreeModel.getChildren(Models.java:628)
at org.netbeans.spi.viewmodel.Models$CompoundModel.getChildren(Models.java:2819)
at org.netbeans.modules.viewmodel.TreeModelNode$TreeModelChildren.evaluateLazily(TreeModelNode.java:701)
at org.netbeans.modules.viewmodel.TreeModelNode$LazyEvaluator.run(TreeModelNode.java:1124)
at org.openide.util.RequestProcessor$Task.run(RequestProcessor.java:561)
[catch] at org.openide.util.RequestProcessor$Processor.run(RequestProcessor.java:986)

I could only save the following:

java.lang.Object.wait(Object.java:356)
com.sun.midp.midlet.Scheduler.schedule(Scheduler.java:336)
com.sun.midp.main.Main.runLocalClass(Main.java:466)
com.sun.midp.main.Main.main(Main.java:121)

com.sun.midp.lcdui.DefaultEventHandler$VMEventHandler.run(DefaultEventHandler.java:553)

A short description what my midlet does:
In background is a open recordstore and recordenumartion. I only display a few information using labels of each record in a tab. Size of one record is about 100byte.
Maybe it helps you.

>
> > It seems for me that it is impossible to get the
> selected empty
> > Container. tp.getComponentAt(0) returns a list
> which includes
> > buttons but I do not have access in any way to the
> Hashtable
> > tabsTable to link the buttons to the containers.
>
> Yes this seems like an issue, I will try to add a
> "getTabComponentAt
> (int index)" method. In the meantime the container
> you are looking
> for is the first child of element 1 e.g.:
>
> tabPane.addTab("1", myContainer);
>
> ((Container)tabPane.getComponentAt(1)).getComponentAt(
> 0) == myContainer

Thanks,
danko

Shai Almog

>
> java.lang.IllegalThreadStateException

This exception is related to NetBeans/simulator, I would suggest
restarting both (also making sure all the simulator processes are dead).

> I could only save the following:
>
> java.lang.Object.wait(Object.java:356)
> com.sun.midp.midlet.Scheduler.schedule(Scheduler.java:336)
> com.sun.midp.main.Main.runLocalClass(Main.java:466)
> com.sun.midp.main.Main.main(Main.java:121)

This is related to the VM implementation and doesn't provide much
information.

>
> com.sun.midp.lcdui.DefaultEventHandler$VMEventHandler.run
> (DefaultEventHandler.java:553)
>
> A short description what my midlet does:
> In background is a open recordstore and recordenumartion. I only
> display a few information using labels of each record in a tab.
> Size of one record is about 100byte.
> Maybe it helps you.

Since you have separate threads it is very possible you have a
deadlock at some point.
I suggest you put printouts in the threads and start working on
commenting out code until you can find the problem.
MIDP synchronizes some things internally (such as RMS access) which
could itself be the source of a deadlock even if you never use
synchronization.

Thanks.

Shai Almog
http://lwuit.blogspot.com/

[att1.html]

danko
Offline
Joined: 2008-07-18

Hi,

> > java.lang.IllegalThreadStateException
>
> This exception is related to NetBeans/simulator, I
> would suggest
> restarting both (also making sure all the simulator
> processes are dead).
I closed NetBeans and simulator without an effect but I did not look up for running processes.
Debugging my testmidlet helped. Maybe that killed the processes.

> This is related to the VM implementation and doesn't
> provide much
> information.
I thought as much.

> Since you have separate threads it is very possible
> you have a
> deadlock at some point.
> I suggest you put printouts in the threads and start
> working on
> commenting out code until you can find the problem.
> MIDP synchronizes some things internally (such as RMS
> access) which
> could itself be the source of a deadlock even if you
> never use
> synchronization.
I used synchronization before I posted the problem without any effect. Maybe on the wrong position. I will ask a friend. He has more experience than me.

I change my algorithm to select the required record. Now I reset always the enumeration and go forward to the record. Previously I selected the records by going forward or backward. That solved that problem but I think not the issue that there is a deadlock. The forward/backward algorithm should work perfect because if I press the keys a bit slower I cannot detect any problems. I only need three tabs and three keystrokes to reproduce the bug.

Thanks a lot,
danko

Shai Almog

> I used synchronization before I posted the problem without any
> effect. Maybe on the wrong position. I will ask a friend. He has
> more experience than me.

Synchronization will make a deadlock worse in some cases. Generally
the best approach to debugging it is replacing code with dummy code
and trying to pinpoint the issue.

>
> I change my algorithm to select the required record. Now I reset
> always the enumeration and go forward to the record. Previously I
> selected the records by going forward or backward. That solved that
> problem but I think not the issue that there is a deadlock. The
> forward/backward algorithm should work perfect because if I press
> the keys a bit slower I cannot detect any problems. I only need
> three tabs and three keystrokes to reproduce the bug.

If you can reproduce something and send it to me I can take a look.

Shai Almog
http://lwuit.blogspot.com/

[att1.html]

danko
Offline
Joined: 2008-07-18

Hi,

I found the reason. I designed the algorithm that selectionChanged be called exclusively if there is a change. Using left/right key was not a problem because at the end/begin of the tab row there is not a second call. Using number keys selectionChanged be called as often as the key pressed.
The whole time I printed out the old and new selected index but I did not notice that there stood e.g.: "old 0 new 0" in my amount of printouts. :(

Maybe it would help other idiots If you change the behavior of calling selectionChanged.

Thanks a lot,
danko

Shai Almog

Hi,
thanks. There is indeed a bug in the current version of this method I
will try to fix it for the next drop.

Regardless, I don't think the tabbed pane will be very suitable for a
*very* large number of tabs e.g. 50 or more...

Even for this amount I would make sure to lazily instantiate tabs
remove all components when leaving a tab.

Thanks,
Shai.
> http://forums.java.net/jive/thread.jspa?messageID=289040
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@lwuit.dev.java.net
> For additional commands, e-mail: users-help@lwuit.dev.java.net
>

Shai Almog
http://lwuit.blogspot.com/

[att1.html]

danko
Offline
Joined: 2008-07-18

Hi,

> Regardless, I don't think the tabbed pane will be
> very suitable for a
> *very* large number of tabs e.g. 50 or more...
I think the maximum will be about 15 tabs. ;)

>
> Even for this amount I would make sure to lazily
> instantiate tabs
> remove all components when leaving a tab.
Thanks for that hint.

danko