> i have a simple problem. Let's say that in some app, i have a loop wich
> add a lot of elements to a JList. I CANNOT change the loop, but i can
> change how each element is added.
Are you not going to tell us why?
> What i would like is that i can scroll the JList with the mouse,
> select/unselect, etc... WHILE the elements are added:
> public class Refresh extends JFrame {
There is no need to extend JFrame.
> private JPanel jContentPane = null;
> [...]
> this.setContentPane(getJContentPane());
What's with the J's? They just make it more difficult to read.
> }
>
> private JPanel getJContentPane() {
> if (jContentPane == null) {
And what's with this lazy initialisation that is always done?
Perhaps if these methods were called by a base class constructor it
would matter, but then you've just clobbered them with the
initialisation assignments.
> jContentPane = new JPanel();
If you are going to set a JPanel as the content pane, you should
setOpaque(true) on it. It doesn't make any difference on most platforms,
but on some it does. "Works for me" doesn't work.
> jButton = new JButton();
> jButton.setText("Add");
[quoted text clipped - 6 lines]
> }
> });
Okay, so you are are creating and adding 1,000,000 entries to the list
in one go from within the Event Dispatch Thread.
If these entries have a high creation cost then the obvious thing to do
is either do it in batches, or create in another thread and transfer
across. Better still create the entries lazily, which you seem quite
keen on (IIRC, you need set a fixed with and height on the JList, or
they will all be created to determine individual heights). But if you
can't do that for some reason, I guess you can't. On a 1 GHz processor
we have around 100 cycles per entry. That should be just about doable
for a trivial object.
> private void add1(int i) {
> ((DefaultListModel)getJList().getModel()).addElement(new Integer(i));
> }
Each time you add an entry, the model fires an event. That isn't going
to be efficient. So perhaps create an entirely new model with a bulk
add. That or remove the listeners for the duration.
Note, a very long list, without fixed cell width and height, validating
layout will be extremely slow.
> * The JList freezes too, and a java.lang.OutOfMemoryError is throwed;
> */
> private void add2(int i) {
> SwingUtilities.invokeLater(new RunAdd(i));
> }
An anonymous inner class would have worked better here.
What you are doing here is queueing up a million events. That isn't
going to be nice.
You could add the entries to a plain List. invokeLater on a task that
adds a traunch of the outstanding entries. If not all entries are added
in one go, then the task should invokeLater itself again. This is
similar to the way SwingWorker operates.
There is a way to clear the event queue without returning from an event.
The ActionListener above should invokeLater, because the event hasn't
finished firing and there may be other listeners yet execute (for
instance from the PL&F). The technique is a complete hack and I don't
recommend it, but anyway:
Modal dialog boxes run a nested copy of the event loop without returning
from the event that caused the dialog box to be shown. This can be
hacked for our purposes. The Foxtrot library should help, if you must do
this.
> public static void main(String[] args) {
You need the standard boilerplate here:
EventQueue.invokeLater(new Runnable() { public void run() {
> new Refresh().setVisible(true);
}});
> }
> }
Tom Hawtin

Signature
Unemployed English Java programmer
http://jroller.com/page/tackline/
Anonymous user - 30 Dec 2005 13:56 GMT
Thomas Hawtin a écrit :
> > i have a simple problem. Let's say that in some app, i have a loop wich
> > add a lot of elements to a JList. I CANNOT change the loop, but i can
> > change how each element is added.
>
> Are you not going to tell us why?
Because i'm working on JTable and sometimes, the same error happens for
all the cells in a column for example. If the error happens in the
renderering (TableCellRenderer) then you have some kind of loop that
you can't control.
> > What i would like is that i can scroll the JList with the mouse,
> > select/unselect, etc... WHILE the elements are added:
>
> > public class Refresh extends JFrame {
>
> There is no need to extend JFrame.
For this problem and all the ones conerning the build of the frame,
blame Eclipse Visual Editor.
> If you are going to set a JPanel as the content pane, you should
> setOpaque(true) on it. It doesn't make any difference on most platforms,
> but on some it does. "Works for me" doesn't work.
good to know
> Okay, so you are are creating and adding 1,000,000 entries to the list
> in one go from within the Event Dispatch Thread.
yep
> If these entries have a high creation cost then the obvious thing to do
> is either do it in batches, or create in another thread and transfer
[quoted text clipped - 4 lines]
> we have around 100 cycles per entry. That should be just about doable
> for a trivial object.
i can't make it lazily because a don't know when the "loop is done". I
have no control on the loop.
> > private void add1(int i) {
> > ((DefaultListModel)getJList().getModel()).addElement(new Integer(i));
[quoted text clipped - 3 lines]
> to be efficient. So perhaps create an entirely new model with a bulk
> add. That or remove the listeners for the duration.
good idea, i fill up a regular List, and in paintComponent(), i do:
if (regularList is not empty) {
regularList.insert(JList.this.getAll())
JList.this.setModel(new List(regularList));
// should call repaint
} else {
super.paintComponenet(g);
}
> Note, a very long list, without fixed cell width and height, validating
> layout will be extremely slow.
good to know too!
> > * The JList freezes too, and a java.lang.OutOfMemoryError is throwed;
> > */
[quoted text clipped - 3 lines]
>
> An anonymous inner class would have worked better here.
i don't know how add a parameter to the constructor in anonymous inner
class
> What you are doing here is queueing up a million events. That isn't
> going to be nice.
it should
> You could add the entries to a plain List. invokeLater on a task that
> adds a traunch of the outstanding entries. If not all entries are added
> in one go, then the task should invokeLater itself again. This is
> similar to the way SwingWorker operates.
i don't understand SwingWorker, i've already tried to but...
> [hack]
> > public static void main(String[] args) {
>
[quoted text clipped - 5 lines]
> > }
> > }
i've never managed to understand why it is needed, so i never write
it...
> Unemployed English Java programmer
hopes you get a job
> http://jroller.com/page/tackline/
seems interesting, you're in my bookmarks ;)
Rhino - 30 Dec 2005 15:28 GMT
Do you REALLY plan to make your user have to scroll through a JList with a
MILLION entries in it? That seems like a very poor design to me. Couldn't
you break the entries into categories so that the user can "drill down" to
it in stages?
For instance, if I wanted my user to choose from a million town or city
names from all over the world, I would NOT simply present a million names of
towns and cities: I'd let them choose the continent, then the country, then
the state or province, and then the town; that would keep each list, except
possibly the last one, reasonably brief.
Can you do something like this in your user interface? Otherwise, I think
your user is going to be VERY unhappy with your GUI design. Your job might
get a little harder if you have to present multiple lists in the appropriate
sequence but each list should be a lot more manageable than having to deal
with a million-element list.
Rhino
Thomas Hawtin - 30 Dec 2005 16:13 GMT
> Do you REALLY plan to make your user have to scroll through a JList with a
> MILLION entries in it? That seems like a very poor design to me. Couldn't
> you break the entries into categories so that the user can "drill down" to
> it in stages?
A million entries a pixel each wouldn't require any scrolling on a
decent screen. I suspect that the figure of a million was just being
extreme, and in fact there would be fewer, heavier entries.
> For instance, if I wanted my user to choose from a million town or city
> names from all over the world, I would NOT simply present a million names of
> towns and cities: I'd let them choose the continent, then the country, then
> the state or province, and then the town; that would keep each list, except
> possibly the last one, reasonably brief.
These days, I'd let the user type it and simultaneously search, in a
modern google style. Even for a long name it's easy. I can type
"harbertonford" without thinking. There can't be that many
Harbertonfords in the world. In fact, there probably aren't many places
starting with "harb".
> Can you do something like this in your user interface? Otherwise, I think
> your user is going to be VERY unhappy with your GUI design. Your job might
> get a little harder if you have to present multiple lists in the appropriate
> sequence but each list should be a lot more manageable than having to deal
> with a million-element list.
If the user can incrementally search, then it shouldn't really be a
problem (although the scroll bar might be a little inappropriate).
However, my guess is that a million is an exaggeration.
Tom Hawtin

Signature
Unemployed English Java programmer
http://jroller.com/page/tackline/
Thomas Hawtin - 30 Dec 2005 15:35 GMT
> Thomas Hawtin a écrit :
>
[quoted text clipped - 8 lines]
> renderering (TableCellRenderer) then you have some kind of loop that
> you can't control.
So the body of the loop sometime throws an exception, in which case no
more entries should be added? That doesn't stop you doing the loop
differently. Perhaps in sections. Perhaps in a different thread (but not
directly accessing Swing components).
> For this problem and all the ones conerning the build of the frame,
> blame Eclipse Visual Editor.
I blame using a GUI builder.
> good idea, i fill up a regular List, and in paintComponent(), i do:
Not necessarily paintComponent. The effect will be much the same,
although it might flash if you do do it from the paint.
>>An anonymous inner class would have worked better here.
>
> i don't know how add a parameter to the constructor in anonymous inner
> class
Make a local variable final in the enclosing method. You can the access
it from within the anonymous inner class.
>>You need the standard boilerplate here:
>>
>> EventQueue.invokeLater(new Runnable() { public void run() {
> i've never managed to understand why it is needed, so i never write
> it...
Take it on trust...
The main thread is different from the AWT Event Dispatch Thread (EDT).
If you don't transfer across to the EDT then you have a multithreaded
Swing program! You'll be okay most of the time. Most of the time.
Tom Hawtin

Signature
Unemployed English Java programmer
http://jroller.com/page/tackline/