tags:

views:

369

answers:

2

Hi all.

Problem: I have a method that creates a list from the parsed ArrayList. I manage to show the list in the GUI, without scrollbar. However, I am having problem setting it to show only the size of ArrayList. Meaning, say if the size is 6, there should only be 6 rows in the shown List. Below is the code that I am using. I tried setting the visibleRowCount as below but it does not work. I tried printing out the result and it shows that the change is made.

private void createSuggestionList(ArrayList<String> str) {
    int visibleRowCount = str.size();
    System.out.println("visibleRowCount " + visibleRowCount);
    listForSuggestion = new JList(str.toArray());
    listForSuggestion.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    listForSuggestion.setSelectedIndex(0);
    listForSuggestion.setVisibleRowCount(visibleRowCount);
    System.out.println(listForSuggestion.getVisibleRowCount());
    listScrollPane = new JScrollPane(listForSuggestion);
    MouseListener mouseListener = new MouseAdapter() {

        @Override
        public void mouseClicked(MouseEvent mouseEvent) {
            JList theList = (JList) mouseEvent.getSource();
            if (mouseEvent.getClickCount() == 2) {
                int index = theList.locationToIndex(mouseEvent.getPoint());
                if (index >= 0) {
                    Object o = theList.getModel().getElementAt(index);
                    System.out.println("Double-clicked on: " + o.toString());
                }
            }
        }
    };
    listForSuggestion.addMouseListener(mouseListener);
    textPane.add(listScrollPane);
    repaint();
}

To summarize: I want the JList to show as many rows as the size of the parsed ArrayList, without a scrollbar.

Here is the picture of the problem: alt text

Here's the link to the other 2 as the picture resolution is quite big I'm scared it will distort the view: JList 1 & JList 2

The JList 1 and 2 pictures shows it clearly. The JList displays empty rows, which I do not want it to happen.

Any ideas? Please help. Thanks. Please let me know if a picture of the problem is needed in case I did not phrase my question correctly.

--

Edit:

JScrollPane scrollPane = new JScrollPane(textPane);
scrollPane.setPreferredSize(new Dimension(200, 200));

//Create the text area for the status log and configure it.
changeLog = new JTextArea(5, 30);
changeLog.setEditable(false);
JScrollPane scrollPaneForLog = new JScrollPane(changeLog);

//Create a split pane for the change log and the text area.
JSplitPane splitPane = new JSplitPane(
        JSplitPane.VERTICAL_SPLIT,
        scrollPane, scrollPaneForLog);
splitPane.setOneTouchExpandable(true);

//Create the status area.
JPanel statusPane = new JPanel(new GridLayout(1, 1));
CaretListenerLabel caretListenerLabel =
        new CaretListenerLabel("Caret Status");
statusPane.add(caretListenerLabel);

//Add the components.
getContentPane().add(splitPane, BorderLayout.CENTER);
getContentPane().add(statusPane, BorderLayout.PAGE_END);

How the textPane is included into the container, if that helps

Another edit:

public void showSuggestionList(JScrollPane pane, Rectangle caretCoords) {
    pane.setVisible(false);
    pane.setBounds(caretCoords.x - 5, caretCoords.y + 25, 400, 250);
    pane.setVisible(true);
    repaint();
}

showSuggestionList() is being called my CaretListener, to show the JScrollPane when the caret moves.

+1  A: 

If you are dynamically (via code) filling your list, it is bad idea not to use scrollbar. It might work as you want f.e. for 20 list items, but imagine what happens once you need use more data - like 2000. Your GUI will be ruined.

Xorty
@Xorty: Well, the ArrayList is actually a collection of different parameters that is hardcoded into the program. So I can assure you that it will not be more than 10. I'll add the scrollbar if it is more than 10, but that is another part of the code.
Alex Cheng
+2  A: 

I suspect it's the layout-management of textPane that is the issue. From what I can see, the listForSuggestions should not occupy more space than it needs to display those items, if it's preferred size is respected.

So the JTextPane is a Container, that is, you can add subcomponents to it. But how are those subcomponents layed out? That is up to the layout manager currently in use. If the layout manager respects the preferred dimension of the listForSuggestios I think you should be ok. Not sure though.

From what I can see, you get the "null-layout" by just instantiating a JTextPane, which means that unless you set another layout manager explicitly, you would need to take care of placement / resizing of the subcomponents yourself.

You could try to do something like

Dimension dim = listForSuggestions.getPreferredSize();
listForSuggestions.setBounds(xPos, yPos, dim.getWidth(), dim.getHeight());

Here is a complete example

import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;

import javax.swing.*;


public class FrameTest {

    public static void main(String[] args) {
        JFrame f = new JFrame("Frame Test");


        ArrayList<String> str = new ArrayList<String>();
        for (int i = 0; i < 20; i++)
            str.add("number " + i);

        JTextPane tp = new JTextPane();


        int visibleRowCount = str.size();
        System.out.println("visibleRowCount " + visibleRowCount);
        JList listForSuggestion = new JList(str.toArray());
        listForSuggestion.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        listForSuggestion.setSelectedIndex(0);
        listForSuggestion.setVisibleRowCount(5);
        System.out.println(listForSuggestion.getVisibleRowCount());
        JScrollPane listScrollPane = new JScrollPane(listForSuggestion);
        MouseListener mouseListener = new MouseAdapter() {

            @Override
            public void mouseClicked(MouseEvent mouseEvent) {
                JList theList = (JList) mouseEvent.getSource();
                if (mouseEvent.getClickCount() == 2) {
                    int index = theList.locationToIndex(mouseEvent.getPoint());
                    if (index >= 0) {
                        Object o = theList.getModel().getElementAt(index);
                        System.out.println("Double-clicked on: " + o.toString());
                    }
                }
            }
        };
        listForSuggestion.setBorder(BorderFactory.createMatteBorder(1, 1, 1, 1, Color.BLACK));
        listForSuggestion.addMouseListener(mouseListener);
        Dimension dim = listForSuggestion.getPreferredSize();
        listForSuggestion.setBounds(20, 20, (int) dim.getWidth(), (int) dim.getHeight());

        tp.add(listForSuggestion);

        f.add(tp);
        f.setSize(400, 400);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setVisible(true);

    }
}

I think the most elegant way of doing this is to roll your own layout-manager. (It's actually quite simple.) And then, instead of doing textPane.add(list), you do textPane.add(list, YourLayoutManager.POPUP_LIST). The layout-manager then remembers the fact that list was supposed to be layed out according to it's preferred size, and layes it out accordingly in its layoutContainer-method. (If you give the YourLayoutManager a reference to the JTextPane that it is attached to, you could probably even make it layout the list right beside the current caret location.)

aioobe
@aioobe: Can you please clarify? For the textPane, it is instantiation of JTextPane, if it helps.
Alex Cheng
@aioobe: I'd included the part of the code where textPane is inserted into the split pane. May I know what can I do to rectify this? Like what you'd said earlier, it seems that the splitPane uses `BorderLayout.CENTER`.
Alex Cheng
@aioobe: I am using setBounds, in showSuggestionList(). Please check the edited post. I will try your code. Thanks.
Alex Cheng
Well there you have it, (400, 250) is the width / height of the list, while it should be (400, <preferred height of list>)
aioobe
+1. You could still use `JScrollPane` with the default policy to show scrollbars only when necessary, and use `Math.min` with a constant for `height` (maybe height of containing JTextPane minus vertical position). This would make sure that the list always fits even if there are more values, but scrollBar will only be displayed when necessary.
Peter Lang
@Peter, was I your 1000th upvote? :-)
aioobe
@Alex Cheng: Your current problem is, that the vertical ScrollBar takes place too, so the items do not have enough horizontal space, and a horizontal ScrollPane is necessary too. Try to increase width of the scrollPane for testing.
Peter Lang
Yeah silly me. However it looks weird if I use (int) dim.getWidth(), (int) dim.getHeight(). aioobe's code looked just nice. I wonder why.@aioobe: The scrollbar is there... How do I go around and disable it?@Peter Lang: Minus the vertical position? I don't really get you, I'm sorry.
Alex Cheng
@aioobe: Yeah, it actually was :)
Peter Lang
@Alex Cheng: What I meant by vertical position was to make sure that the JList does not exceed the bounds of the containing JTextPane, so the maximum height would be {(height of JTextPane) - (vertical offset (y) of JList)}
Peter Lang
@Peter: pane.setBounds(caretCoords.x - 5, caretCoords.y + 25, 400, (int) dim.getHeight() + 10); This did the trick. I add 10 to the getHeight() and the scrollbar is gone!
Alex Cheng
@Alex Cheng, I can't give you much better advice than Peter Langs reply a few comments up.
aioobe
Guys, thanks for the help. But how do I get around to set the maximum height of the JList? In the setBounds is it?
Alex Cheng
`setBounds` actually *sets* the bounds, so yes, you could constrain the height in that call. If you want you could `setMaximumSize` on the `JList`, and then respect maximum / minimum / preferred size when adjusting the bounds.
aioobe
+1 Clear explanation. Nice. Thank you very much once again to you (aioobe) and Peter Lang. =D p/s starting to love SO more haha
Alex Cheng
@Alex Cheng: Good to hear. BTW: `+1` in front of a comment usually means that you upvoted the answer (I usually accept **and** upvote the best answer to my question). Since I already upvoted, it should have at least `2` points by now ;-)
Peter Lang
@Peter: I see. I +1 to the comment by aioobe on setBounds. But I'll do what you'd suggested, accept and upvote the best answer next time.
Alex Cheng