JList Dynamic List Model problem

Hello All,

I have a simple custom JList with a simple custom DefaultListModel and its own cell renderer. This JList is set as the view port of a scroll pane and the scroll pane is added to a panel. Standard Stuff.

JList's model changes dynamically and when this happens I call the updateModel method. As you can see I remove all elements and add new set of items. Now I want JScrollPane to automatically resize such that even the longest item is visible. What is the best way to do this?

1) Compute the longest string in the array and use the setPrototypeCellValue() ?

- Problem is that some times the longest string is just two characters wide and the display looks retarted.

2) Should I experiment with setPreferredSize stuff to see what is logical size for various combinations of the data that could occur in the JList?

3) Should the JScrollPane listens to change in the JList 's model and then resize itself ?

- Seems very complex for such a trivial job.

publicclass SearchableListextends JList{

MyListModel _model;

public SearchableList(){

super();

init();

}

privatevoid init(){

this.setSelectionMode( ListSelectionModel.MULTIPLE_INTERVAL_SELECTION );

this.setCellRenderer(new Renderer() );

_model =new MyListModel(new String[]{});

super.setModel(_model);

}

class Rendererextends JTextFieldimplements ListCellRenderer{

protected Border noFocusBorder;

private DefaultHighlighter.DefaultHighlightPainter painter;

public Renderer(){

super();

if( noFocusBorder ==null )

noFocusBorder =new EmptyBorder(1, 1, 1, 1);

this.painter =new DefaultHighlighter.DefaultHighlightPainter(Color.GREEN);

}

public Component getListCellRendererComponent(

JList list,

Object value,

int index,

boolean isSelected,

boolean cellHasFocus ){

setComponentOrientation( list.getComponentOrientation() );

if( isSelected ){

setBackground( list.getSelectionBackground() );

setForeground( list.getSelectionForeground() );

}else{

setBackground( list.getBackground() );

setForeground( list.getForeground() );

}

String text = value.toString();

setText( text );

// For now highlight the second character of all items

// We must change the Highlighter AFTER calling setText()

Highlighter highlighter = this.getHighlighter();

highlighter.removeAllHighlights();

if( text.length() > 2 ){

//ADD code here that highlightes the user entered substring match

// try {

//highlighter.addHighlight( 1, 2, this.painter );

// } catch( BadLocationException e ) {

// e.printStackTrace();

//}

}

setEnabled( list.isEnabled() );

setFont( list.getFont() );

returnthis;

}

}

publicvoid updateModel(String[] carValues){

_model.init(carValues);

}

}

class MyListModelextends DefaultListModel{

public MyListModel(String[] args){

init(args);

}

publicvoid contentsChanged (){

super.fireContentsChanged(this, -1, -1);

}

publicvoid init(String[] args){

removeAllElements();

if (args ==null)return;

for (int i=0; i < args.length; i++){

addElement(args[i]);

}

contentsChanged();

}

}

Thanks in advance.

[6028 byte] By [alphaman24a] at [2007-10-3 3:53:15]
# 1

I am thoroughly confused after reading through 100 posts or more here related to this problem.

Since I am not getting any help for my earlier question, I will attempt to ask my question in a different form.

If the layout manager in which I am adding this component is GridBagLayout, do I have to set the size of this ScrollPane differently when compared to other layout managers?

If I want my list and scroll pane to be a definite width irrespective of JList contents or the layout manager then what properties do I need to set?

Please help.

alphaman24a at 2007-7-14 21:51:02 > top of Java-index,Desktop,Core GUI APIs...
# 2

calling pack(), after updating the list, works OK in this

import javax.swing.*;

import java.awt.*;

import java.awt.event.*;

class Testing extends JFrame

{

DefaultListModel listModel = new DefaultListModel();

JList list = new JList(listModel);

String[] items1 = {"aaa","bbb","ccc"};

String[] items2 = {"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",

"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",

"ccccccccccccccccccccccccccccccccccccccccccccccccccccccc"};

public Testing()

{

setLocation(400,300);

setDefaultCloseOperation(EXIT_ON_CLOSE);

for(int x = 0, y = items1.length; x < y; x++) listModel.addElement(items1[x]);

JScrollPane sp = new JScrollPane(list);

getContentPane().add(sp,BorderLayout.CENTER);

JButton btn = new JButton("Change List");

getContentPane().add(btn,BorderLayout.SOUTH);

pack();

btn.addActionListener(new ActionListener(){

public void actionPerformed(ActionEvent ae){

DefaultListModel listModel2 = new DefaultListModel();

for(int x = 0, y = items2.length; x < y; x++) listModel2.addElement(items2[x]);

list.setModel(listModel2);

pack();//<

}

});

}

public static void main(String[] args){new Testing().setVisible(true);}

}

Michael_Dunna at 2007-7-14 21:51:02 > top of Java-index,Desktop,Core GUI APIs...
# 3

Michael,

Thanks for replying.

>> calling pack(), after updating the list, works OK in this

In my case I dont have access to the frame at the same place where I have updated the model, so I cannot call pack(). Also I would want to have my component self sufficient rather than depend on the container.

In your example your layout manager is Border Layout. I have read in the forums here that component behavior that are inside GridBagLayout are quite different from other layout managers when it comes to resize/preferredSize. I am reading up more on this.

Any other suggestions?

alphaman24a at 2007-7-14 21:51:02 > top of Java-index,Desktop,Core GUI APIs...
# 4

I don't understand your requirement and limitations.

> I want JScrollPane to automatically resize such that even the longest item is visible.

> Problem is that some times the longest string is just two characters wide and the display looks retarted.

Well you can't have it both ways. Either you want it to be the longest or you don't.

Personally, I don't like the requirement of it fitting the longest entry. What if you have 99 entries of 10 characters of less and one entry of 100 characters. That also looks "retarded".

The whole point of using a LayoutManager is to set a preferred size for your component to something reasonable. Then you add the component to a scrollpane so that you can still scroll to see the extreme case.

> Should I experiment with setPreferredSize stuff to see what is logical

> size for various combinations of the data that could occur in the JList?

I don't see why the size has to change. The list is part of your form. So you design the list so the it fits nicely on your form. So I would say pick a one size fits all approach.

camickra at 2007-7-14 21:51:02 > top of Java-index,Desktop,Core GUI APIs...
# 5

>>Personally, I don't like the requirement of it fitting the longest entry. What if you have 99

>>entries of 10 characters of less and one entry of 100 characters. That also looks

>>retarded".

I agree. I guess what I want is the JScrollPane not to resize itself when the contents of JList are changed. Even if it resizes, I want the JScrollPane to be of a set minimum width and height.

alphaman24a at 2007-7-14 21:51:02 > top of Java-index,Desktop,Core GUI APIs...
# 6
> I want the JScrollPane to be of a set minimum width and height. Then you use setPreferredSize(..) on the scrollPane.
camickra at 2007-7-14 21:51:02 > top of Java-index,Desktop,Core GUI APIs...