0

Currently attempting to generate a ComboBox with a list of Strings and want those String values to have a certain opacity. The CombobBox itself should remain normal and only the data change.

I was able accomplish this with my ComboBox of icons by implementing my own custom Class.

    ///This works great when ICons are used within the JComboBox
    class MyImageIconObject extends ImageIcon
    {
        float x;
        ImageIcon ic;
        public MyImageIconObject(String iconLocation)
        {
            super(iconLocation);
            this.ic = new ImageIcon(iconLocation); 
        }
    
        @Override
        public void paintIcon(Component c, Graphics g, int x, int y)
        {
            //super.paintIcon(c, g, x, y);
            ((Graphics2D) g).setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.25f));
            ic.paintIcon(c, g, x, y);
            System.out.println("Painting 2");
        }
    }

The above code generates the following results.

enter image description here

Can't do this for Strings since it is a Final class, but even if I could there isn't a paint() type function to override.

import java.awt.AlphaComposite;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;

import javax.swing.ImageIcon;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;


public class JComboBoxWithStrings extends JFrame
{
    private JComboBox comboBox;
    JPanel topPanel;
    String[] arrayOfStrings = {"String 1", "Entry 2", "More data", "Entry 10000"};
    
    public JComboBoxWithStrings ()
    {
        
    }
    
    public static void main(String[] args)  
    {

        JComboBoxWithStrings T = new JComboBoxWithStrings();
        T.createGUI();
        T.setVisible(true);        
    }
    public void createGUI(){

        setMinimumSize(new Dimension(500,500));
        setTitle("Demo");
        setLocation(200, 200);

        topPanel = new JPanel();
        getContentPane().add(topPanel, BorderLayout.CENTER);

        comboBox = new JComboBox(arrayOfStrings);
        
        topPanel.add(comboBox);

        super.addWindowListener(new WindowAdapter() {           
            public void windowClosing(WindowEvent e) {              
                dispose();          
            }           
        }); 
    }
}

The above code generates the following :

enter image description here

What is required so that I am able to control the opacity of the Strings displayed in the ComboBox while keeping the ComboBox itself normal?

ControlAltDel
  • 33,923
  • 10
  • 53
  • 80
Unhandled Exception
  • 1,427
  • 14
  • 30
  • It's not actually that hard. You need to create a custom ListCellRenderer and use setRenderer on the JCombo with an instance: https://docs.oracle.com/javase/8/docs/api/javax/swing/JComboBox.html#getRenderer-- – ControlAltDel Sep 16 '20 at 16:04
  • Added the Renderer makes sense, but does the opacity get set similar to how the icons were set? From what I am seeing, most sample involve mimicking the behavior by manually setting background/foreground. – Unhandled Exception Sep 16 '20 at 17:02
  • @camickr has posted a solution for you – ControlAltDel Sep 16 '20 at 17:15

1 Answers1

1

control the opacity of the Strings displayed in the ComboBox while keeping the ComboBox itself normal?

Use a custom renderer that checks if the rendering is for the dropdown or the combobox:

import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.plaf.basic.*;

public class ComboBoxTransparent extends JFrame
{
    public ComboBoxTransparent()
    {
        Object[] items = { Color.red, Color.green, Color.blue };
        JComboBox comboBox = new JComboBox( items );
        comboBox.setRenderer( new TransparentRenderer() );
        getContentPane().add( comboBox, BorderLayout.NORTH );
        add( new JTextField(), BorderLayout.SOUTH);
    }

    public static void main(String[] args)
    {
        ComboBoxTransparent frame = new ComboBoxTransparent();
        frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
        frame.pack();
        frame.setLocationRelativeTo( null );
        frame.setVisible( true );
    }

    class TransparentRenderer extends BasicComboBoxRenderer
    {
        private Color transparent = new Color(0, 0, 0, 128);

        public Component getListCellRendererComponent(
            JList list, Object value, int index, boolean isSelected, boolean cellHasFocus)
        {
            super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);

            if (index == -1)
                setForeground( Color.BLACK );
            else
                setForeground( transparent );

            return this;
        }
    }
}
camickr
  • 321,443
  • 19
  • 166
  • 288
  • Thanks that helps. I excluded the IF condition so that all items get the setForeground(tranparent) call and all items become transparent except for the selected item. The one difference from your code is my Renderer implements ListCellRenderer. These are the only 2 calls in the function. JLabel renderer = (JLabel) defaultRenderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); renderer.setForeground(transparent); – Unhandled Exception Sep 16 '20 at 17:19
  • *and all items become transparent except for the selected item* - your change isn't making any sense. If you want all the text so be transparent, then you just set the foregound color of the combo box. The reason I used a custom renderer is to differentiate between the two states of your requirement. – camickr Sep 16 '20 at 17:32
  • Glad it helped. Don't forget to "accept" the answer the clicking on the checkmark (beside the answer) so people know the problem has been solved. – camickr Sep 16 '20 at 17:34
  • Ok, that makes it a lot easier without having to worry about the Renderer. I was expecting it to be more involved like with the Icons. By using the combobox.setForeground() it works as you scroll through the list, but once the list is closed the selected item is back to its solid setting again. – Unhandled Exception Sep 16 '20 at 17:35
  • Looks like to affect the Selected item I need to go back into the Renderer and use the following line of code : list.setSelectionForeground(transparent); unless there is an easier way. – Unhandled Exception Sep 16 '20 at 17:40