Steve McLeod
Steve McLeod

Reputation: 52448

How can I customise the appearance of a JComboBox?

I'd like to make a drop-down list that looks like this:

alt text

JComboBox provides the functionality I need, so I shouldn't need to write a custom component. But I can't find a way to customise the entire appearance of a JComboBox to achieve this. Any suggestions?

Update: I don't want all JComboBoxes to look like this. I only want to create one with this custom appearance. So as far as I can tell, creating a custom L&F is not the solution.

Upvotes: 3

Views: 7386

Answers (2)

John Gardner
John Gardner

Reputation: 25116

If you don't want to create an entire look and feel, the simplest answer is to subclass jcombobox and override the paintComponent method and draw whatever you want.

fill the background with your gray color, then draw your text and arrow in your lighter color.

if you go this route, you may also need to override the updateUI method so that if the VM tries to update your look and feel your combo box doesn't go back to the wrong colors.

Upvotes: 2

omax
omax

Reputation: 539

JComboBox UI is composed from textfield, list and arrows. To customize them you can use some ready L&F or implement your most easily with Synth L&F.

Initialize L&F:

SynthLookAndFeel lookAndFeel = new SynthLookAndFeel();

try {
    lookAndFeel.load(YourClassAlongWithSynthXml.class.getResourceAsStream("synth.xml"), YourClassAlongWithSynthXml.class);
} catch (ParseException e) {
    e.printStackTrace();
}

UIManager.setLookAndFeel(lookAndFeel);

Where synth.xml contains something like this:

<style id="textfield">
    <insets top="4" left="6" bottom="4" right="6" />

    <state>
        <font name="Verdana" size="12" />

        <!--
        <color type="BACKGROUND" value="#D2DFF2" />
        -->
        <color type="TEXT_FOREGROUND" value="#003c2d" />
    </state>

    <imagePainter method="textFieldBorder" path="images/textfield.png" sourceInsets="4 6 4 6" paintCenter="false" />
</style>

<bind style="textfield" type="region" key="TextField" />

<style id="arrowStyle">
    <imagePainter method="arrowButtonForeground" path="images/arrow-up.png" sourceInsets="0 0 0 0" stretch="false" direction="north" />
    <imagePainter method="arrowButtonForeground" path="images/arrow-down.png" sourceInsets="0 0 0 0" stretch="false" direction="south" />
    <imagePainter method="arrowButtonForeground" path="images/arrow-left.png" sourceInsets="0 0 0 0" stretch="false" direction="west" />
    <imagePainter method="arrowButtonForeground" path="images/arrow-right.png" sourceInsets="0 0 0 0" stretch="false" direction="east" />
</style>

<bind key="ArrowButton" type="region" style="arrowStyle" />

<style id="comboArrowStyle">
    <imagePainter method="arrowButtonForeground" path="images/combobox-arrow.png" sourceInsets="0 0 0 0" stretch="false" direction="south" />
</style>

With Synth L&F you will need to fully define how your UI components look like you can't just.

But if you just need to simply modify colors reusing your default L&F, you can use the following snippets to initialize UI of combo box:

final Color COLOR_BUTTON_BACKGROUND = Color.decode("#d3dedb");

UIManager.put("ComboBox.buttonBackground", COLOR_BUTTON_BACKGROUND);
UIManager.put("ComboBox.buttonShadow", COLOR_BUTTON_BACKGROUND);
UIManager.put("ComboBox.buttonDarkShadow", COLOR_BUTTON_BACKGROUND);
UIManager.put("ComboBox.buttonHighlight", COLOR_BUTTON_BACKGROUND);

Upvotes: 9

Related Questions