Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / GUI / August 2006

Tip: Looking for answers? Try searching our database.

Different height at JComboBox editor and renderer

Thread view: 
Beaned - 25 Aug 2006 18:41 GMT
I have a combo box which uses a custom ListCellRenderer which basically
displays two lines of text (the preferred name of an object and an
alternate name of the object). That works well. The problem is that the
editor for the combobox (which is editable) is being displayed with the
same height as the ListCellRenderer (ie two lines) but I would like it
to be normal and be a single text line height. I can't figure out how
to do this. Is this possible? If so could you please provide an example
of how it is done?

Thanks
IchBin - 25 Aug 2006 19:54 GMT
> I have a combo box which uses a custom ListCellRenderer which basically
> displays two lines of text (the preferred name of an object and an
[quoted text clipped - 6 lines]
>
> Thanks

Personally I would need a working snippet of your code to help out.

Signature

Thanks in Advance...
IchBin, Pocono Lake, Pa, USA              http://weconsultants.phpnet.us
'If there is one, Knowledge is the "Fountain of Youth"'
-William E. Taylor,  Regular Guy (1952-)

Beaned - 25 Aug 2006 22:16 GMT
Here is a some code to illustrate the problem. Notice that the editor
is twice as wide as it needs to be. I am at a lost on how to fix this.

import java.awt.*;

import javax.swing.*;

import javax.swing.border.*;

import java.util.*;

@SuppressWarnings("serial")
public class MultiLineListCellRenderer extends JPanel implements
        ListCellRenderer {

    private final JLabel preferredNameLabel = new JLabel();

    private JLabel[] possibleLabels;

    private Font smallFont = null;

    protected Border indentBorder;

    protected Border defaultBorder = getBorder();

    protected Font defaultFont;

    public MultiLineListCellRenderer() {

        setLayout(new BorderLayout());
        int padX = 10;
        int indent = 10;
        indentBorder = BorderFactory.createEmptyBorder(0, padX + indent, 0,
                padX);

        add(preferredNameLabel, BorderLayout.CENTER);
        defaultFont = getFont();
    }

    protected void render(Object value) {

        Resource model = (Resource) value;

        if (smallFont == null) {
            smallFont = defaultFont.deriveFont(defaultFont.getSize2D() * 0.8f);
        }

        String preferredName = model.getPreferredName();
        String[] possibleNames = model.getPossibleNames();
        if (possibleNames.length > 1) {
            if (possibleLabels == null) {
                int size = possibleNames.length - 1;
                setLayout(new GridLayout(size + 1, 1));
                possibleLabels = new JLabel[size];
                for (int i = 0; i < size; i++) {
                    possibleLabels[i] = new JLabel();
                    possibleLabels[i].setFont(smallFont);
                    possibleLabels[i].setBorder(indentBorder);
                    add(possibleLabels[i]);
                }
                validate();
            }
            int index = 0;
            for (String name : possibleNames) {
                if (!name.equals(preferredName)) {
                    possibleLabels[index].setText(name);
                    index++;
                }
            }
        }

        preferredNameLabel.setBorder(defaultBorder);
        preferredNameLabel.setFont(defaultFont);
        preferredNameLabel.setEnabled(isEnabled());
        preferredNameLabel.setComponentOrientation(getComponentOrientation());
        preferredNameLabel.setText(preferredName);
    }

    public Component getListCellRendererComponent(JList list, Object
value,
            int row, boolean isSelected, boolean cellHasFocus) {
        Color color;

        Component component = getRendererComponent(list, value, row,
                isSelected, cellHasFocus);
        Resource model = (Resource) value;
        if (isSelected) {
            preferredNameLabel.setBackground(list.getSelectionBackground());
            preferredNameLabel.setForeground(list.getSelectionForeground());
            if (possibleLabels != null) {
            for (JLabel label : possibleLabels) {
                label.setForeground(list.getSelectionForeground());
            }
        }
        } else {
            preferredNameLabel.setBackground(list.getBackground());
            color = list.getForeground();
            preferredNameLabel.setForeground(color);
            color = new Color(color.getRed(), color.getGreen(),
                    color.getBlue(), 160);
            if (possibleLabels != null) {
            for (JLabel label : possibleLabels) {
                label.setForeground(color);
            }
        }

        }

        return component;
    }

    private JComponent getRendererComponent(JComponent component, Object
value,
            int index, boolean isSelected, boolean cellHasFocus) {

        // Set this cell properties to the same as the list.
        setEnabled(component.isEnabled());
        setFont(component.getFont());
        setComponentOrientation(component.getComponentOrientation());
        setOpaque(component.isOpaque());
        setBackground(component.getBackground());
        setForeground(component.getForeground());

        Border border = null;
        if (cellHasFocus) {
            if (isSelected) {
                border = UIManager
                        .getBorder("List.focusSelectedCellHighlightBorder");
            }
            if (border == null) {
                border = UIManager.getBorder("List.focusCellHighlightBorder");
            }
        } else {
            border = new EmptyBorder(1, 1, 1, 1);
        }

        setBorder(border);
        render(value);
        return this;
    }

    public static void main(String[] args) {

        JFrame frame = new JFrame("JComboBoxExample");
        Vector vector = new Vector();
        vector.add(new Resource("Joe", "Smith"));
        vector.add(new Resource("Mary", "Jane"));
        JComboBox combobox = new JComboBox(vector);
        combobox.setEditable(true);
        combobox.setRenderer(new MultiLineListCellRenderer());
        frame.getContentPane().add(combobox);
        frame.setSize(200, 200);
        frame.pack();
        frame.setVisible(true);
    }

}

public class Resource{

    String name1, name2;

    public Resource(String name1, String name2) {

        this.name1 = name1;
        this.name2 = name2;

    }

    public String getPreferredName() {
        return name1;
    }

    public String[] getPossibleNames() {
        return new String[] {name1, name2};
    }

    public String toString() {
        return name1;
    }
}
Babu Kalakrishnan - 28 Aug 2006 12:47 GMT
> I have a combo box which uses a custom ListCellRenderer which basically
> displays two lines of text (the preferred name of an object and an
[quoted text clipped - 4 lines]
> to do this. Is this possible? If so could you please provide an example
> of how it is done?

The issue is basically - how to inform the JCombobox as to what
"normal" height is :-)

The default strategy of an editable JComboBox in finding its preferred
size is to check for the preferredSize of its renderer when rendering
each item, as well as the preferredSize of its editor component, and
choose the maximum of these along both the width and the height, (Check
out the source code of the getPreferredSize(Component) /
getMinimumSize(Component) methods in the
javax.swing.plaf.basic.BasicComboboxUI class).

If you have something better to suggest as the preferred size (or some
alternate strategy to compute it) you could either override its
getPreferredSize() method (recommended if your size needs to change
dynamically) or to compute it once and call setPreferredSize() on it
(if you don't anticipate the size to change after the component has
been created). Swing will then honour the value returned by the
getPreferredSize() method to fix the size fo the combobox.

BK
Beaned - 28 Aug 2006 16:33 GMT
> > I have a combo box which uses a custom ListCellRenderer which basically
> > displays two lines of text (the preferred name of an object and an
[quoted text clipped - 25 lines]
>
> BK

Thank for pointing me in the right direction! However looking at the
source for the javax.swing.plaf.basic.BasicComboboxUI class, wouldn't I
need to subclass this class and overrided the getDisplaySize() method
since this is where takes the maximum size of either the editor or list
renderer?
Beaned - 28 Aug 2006 17:02 GMT
> > > I have a combo box which uses a custom ListCellRenderer which basically
> > > displays two lines of text (the preferred name of an object and an
[quoted text clipped - 31 lines]
> since this is where takes the maximum size of either the editor or list
> renderer?

I tried implementing what I suggested above and it works but
unfortunately there is a catch. By subclassing BasicComboBoxUI I loose
the look and feel that I am currently using (reverts to metal look and
feel). Can I implement this change and still make it available to any
look and feel?

Thanks.
Babu Kalakrishnan - 28 Aug 2006 18:36 GMT
> > Thank for pointing me in the right direction! However looking at the
> > source for the javax.swing.plaf.basic.BasicComboboxUI class, wouldn't I
[quoted text clipped - 7 lines]
> feel). Can I implement this change and still make it available to any
> look and feel?

Unfortunately the answer is no. This (in my opinion) is one of the big
drawbacks of the swing framework - there's no single point where you
can override a certain behaviour in the UI area and allow it to
propagate to all look-n-feels.

In my opinion you'd be better off putting your custom sizing behaviour
in either a customized JComboBox subclass - (Or simply call
setPreferredSize on it). While the default behaviour of a JComponent is
to (rightly) ask the UI delegate to compute the preferred sizes, it
normally honors the  preferred sizes set by the application at the
component level.

BK
Beaned - 28 Aug 2006 19:47 GMT
> Unfortunately the answer is no. This (in my opinion) is one of the big
> drawbacks of the swing framework - there's no single point where you
[quoted text clipped - 9 lines]
>
> BK

Doing it the way you suggested works much better. Thanks for your help!


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.