Skip to Main Content

Java SE (Java Platform, Standard Edition)

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

Interested in getting your voice heard by members of the Developer Marketing team at Oracle? Check out this post for AppDev or this post for AI focus group information.

list widget with different colors for each list item?

RichFOct 8 2010 — edited Oct 15 2010
I'm going to add a list widget to my Interactive Color Wheel:

* http://r0k.us/graphics/SIHwheel.html

It's an old applet, first published in 1998, and pre-dating Swing.

The list will contain the 1,567 color names for which it knows color values. I would like to have the background color on each item to be that of its named color. The color name foreground text will be white or black, chosen for readability upon its background. Basically, I am hoping to accomplish what the Name that Color page does with its HTML-form list widget:

* http://chir.ag/projects/name-that-color/

I've studied the java.awt.list document:

* http://download.oracle.com/javase/1.4.2/docs/api/java/awt/List.html

The setBackground() and setForeground() methods are implemented, but they appear to only apply to the List as a whole. As far as I can tell, there appears to be no access to list items themselves as components. I hope I'm just missing the obvious.

-- Rich
This post has been answered by pietblok on Oct 9 2010
Jump to Answer

Comments

RichF
Hmm, is the following telling me that setBackground(), although implemented for List.AccessibleAWTListChild, doesn't actually work?
247:            public final void testSetBackground() {
248:                Color color = Color.DARK_GRAY;
249:                assertFalse(list.isBackgroundSet());
250:                aComp3.setBackground(color);
251:                assertEquals(color, aComp1.getBackground());
252:                assertEquals(color, aComp2.getBackground());
253:                assertEquals(color, aComp3.getBackground());
254:                assertTrue("setBackground() is delegated to List", list
255:                        .isBackgroundSet());
256:                assertEquals(color, list.getBackground());
257:            }
above found at:

* http://www.java2s.com/Open-Source/Java-Document/Apache-Harmony-Java-SE/java-package/java/awt/AccessibleAWTListChildTest.java.htm

I have no knowledge of Java accessibility, but I was excited when I found something that gave access to "list children", such as aComp3 above. They seem to be the individual list items themselves. However, line 254 above seems to suggest something .. unfortunate. One may go through the motions of setting the background color of a child, but the setBackground() is actually delegated to the List as a whole. Am I interpreting this correctly?

The above is part of a test suite implemented using:

* import junit.framework.TestCase;

I'm trying to avoid the learning curve to use JUnit when I already suspect the answer is "no". :(

-- Rich
pietblok
Answer
What you want to do can be easyly implemented in a swing JList, with the help of a customized renderer. So I would advise to rewrite your applet in swing and then use a JList. That way you can skip studying JUnit just for forcing your awt applet to do something awt was nor designed for and concentrate on swing GUI stuff. Below an example of how you might implement your JList:
import java.awt.*;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.Comparator;

import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

public class ColorList {

    public static void main(String[] args) {
	SwingUtilities.invokeLater(new Runnable() {

	    @Override
	    public void run() {
		new ColorList().createGUI();
	    }
	});
    }

    private void createGUI() {
	String[][] array = getArray();
	// sort the array as you wish
	Arrays.sort(array, new Comparator<String[]>() {

	    @Override
	    public int compare(String[] o1, String[] o2) {
		return o1[1].compareTo(o2[1]);
	    }

	});
	// create the JList
	final JList list = new JList(array);
	// set some adequate renderer
	list.setCellRenderer(new DefaultListCellRenderer() {
	    private static final long serialVersionUID = 1L;

	    @Override
	    public Component getListCellRendererComponent(JList list,
		    Object value, int index, boolean isSelected,
		    boolean cellHasFocus) {
		DefaultListCellRenderer renderer = (DefaultListCellRenderer) super
			.getListCellRendererComponent(list, value, index,
				isSelected, cellHasFocus);
		renderer.setText(((String[]) value)[1]);
		int color = new BigInteger(((String[]) value)[0], 16)
			.intValue();
		renderer.setBackground(new Color(color));
		renderer.setForeground(new Color(0xFFFFFFFF ^ color));
		return renderer;
	    }
	});
	final JLabel demoLabel = new JLabel(
		"Display this text in the selected color", JLabel.CENTER);
	list.addListSelectionListener(new ListSelectionListener() {

	    @Override
	    public void valueChanged(ListSelectionEvent e) {
		String[] selected = (String[]) list.getSelectedValue();
		demoLabel.setForeground(new Color(new BigInteger(selected[0],
			16).intValue()));
	    }
	});

	JFrame frame = new JFrame("ColorList");
	frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	frame.add(new JScrollPane(list), BorderLayout.LINE_START);
	frame.add(demoLabel, BorderLayout.CENTER);
	frame.pack();
	frame.setLocationRelativeTo(null);
	frame.setVisible(true);
    }

    private String[][] getArray() {
	return new String[][] {

	{ "000000", "Black" },

	{ "000080", "Navy Blue" },

	{ "0000C8", "Dark Blue" },

	{ "0000FF", "Blue" },

	{ "000741", "Stratos" },

	{ "00FF00", "Green" },

	{ "FF0000", "Red" },

	{ "FFFFF0", "Ivory" },

	{ "FFFFFF", "White" }

	};

    }

}
Piet
Marked as Answer by RichF · Sep 27 2020
RichF
Piet, wow, that's beautiful!! :)

What is amazing as the example you took time to write is that you pulled together info from two different threads in two different forums to do so. Thank you very much!

Time to learn Swing, enter the 21st century ...

-- Rich
User_64CKJ
RichF wrote:
Piet, wow, that's beautiful!! :)
Agreed.
..Time to learn Swing, enter the 21st century ...
++ ;)
pietblok
Andrew Thompson wrote:
RichF wrote:
Piet, wow, that's beautiful!! :)
Agreed.
..Time to learn Swing, enter the 21st century ...
++ ;)
So you see, in some cases, rare I do agree, just "giving the codes" may have some educational value ;-)
Piet
RichF
Piet, converting to Swing will not only be educational, it will likely be easier than my other option. What I was considering was either extending awt.List, or perhaps rewriting it if necessary. I'm quite glad I don't have to reinvent the list...

I posted an update to the other, "simpler way to sort 2-d string array?", thread:

* 1557000

Understated person which you are, you snuck in an answer to that question as well. Did you already know how to do that, or was the Javascript code I posted there an inspiration?

One thing puzzles me in your example. Why the need for BigInteger? The hex color values are only 24-bit, which should not cause problems with 32-bit integers, right? Oh, I see. the Integer constructors do not include a form with radix, but the BigInteger constructors do. You've programmed with Java before. ;)

-- Rich
pietblok
RichF wrote:
Understated person which you are, you snuck in an answer to that question as well. Did you already know how to do that, or was the Javascript code I posted there an inspiration?
No. I usually skip all text that I don't understand. Javascript falls into that category. It's just the way I would do it.
One thing puzzles me in your example. Why the need for BigInteger? The hex color values are only 24-bit, which should not cause problems with 32-bit integers, right? Oh, I see. the Integer constructors do not include a form with radix, but the BigInteger constructors do. You've programmed with Java before. ;)
Here I was educated by kajbj, reply number 5 in this thread http://forums.sun.com/thread.jspa?threadID=5450453&tstart=90 on the old forums. I internalized that reply for the rest of my life.

Piet
RichF
I've got the original awt code pretty-much ported to Swing now. The only new feature so far is that I've added toolTips to the GUI buttons. Neat!

I say "pretty-much" because I haven't found an equivalent way to do the awt update() method. Under awt, I had overridden update() to handle the situation of a partial canvas update, such as only needing to update the wheel but not everything else. Since Swing never calls update() I'm patching it in by hand:
    // was named paint() in awt version
    public void paintComponent(Graphics g)
    {
        Rectangle ulc;

	if (font == null)  defineFont(g);

	// handle partial repaints of specific items
	if (partialOnly(g))  return;

        if (r != null)
	    r = null;	/*  re-init to handle resizing of frame  */
	r = getBounds();

	// for clean double-buffering
	super.paintComponent(g);

        maxI = calcMaxI(intensity);

        g.setColor(background);
        g.fillRect(0, 0, r.width, r.height);
        ...
    }

    /**
    ***   There is no automatic update() with Swing.  Therefor we need
    *** to patch our own into paint to avoid complete redraws.
    **/
    public boolean partialOnly(Graphics g)
    {
	boolean	imDone = true;

        if (wedgeOnly)
        {
	    putDotOnWheel(g);
            paintWedge(g);
	    drawSnake(g);
	    drawSatSnake(g);
	    updateLumaBars(g);
            wedgeOnly = false;
        }
          else if (wheelOnly)
          { // update the wedge's intensity dot and label
            putDotNearWedge(g);
	    labelWedge(g);
	    miscLabels(g);
	    drawSnake(g);
	    drawSatSnake(g);
            // update the GUI items having to do with intensity
            updateGUIintensity(g);
	    updateLumaBars(g);

            paintWheel(g);
	    putDotOnWheel(g);
            wheelOnly = false;
          }
          ... // etc
          else
            imDone = false;	// allow full paint()

	return(imDone);
    }
There are two problems; perhaps both relate to double-buffering. The first is that the canvas goes wonky-white when the user clicks on the wheel. What is supposed to happen is simply the user sees another dot on the wheel for his new selected color. Forcing a complete redraw via any of the GUI buttons at the bottom sets things right. The canvas behaves itself from then on, at least until minimized or resized, at which point one needs to click a GUI button again. I'll be disabling resizing, but minimizing will still be allowed.

The second problem is that for some strange reason, the last selected GUI button and possibly it's tooltip will be replicated at the top of the painting canvas. Why this happens, I don't know -- they are two separate JPanels. Since a full paintComponent() refills the entire canvas, this effect was not visible until I started doing the partialOnly() stuff.

You can see what the heck I'm talking about by downloading:

* http://r0k.us/rock/Junk/SIHwheel.jar

Type "java -jar SIHwheel.jar" to run it.

What am I doing wrong?

Heh, I hadn't run it as an applet until I checked on the html page in the Junk folder:

* http://r0k.us/rock/Junk/SIHwheel.html

It appears to function great as an applet, without either problem mentioned above.

For anyone really interested, the full source is there as well:

* http://r0k.us/rock/Junk/SIHwheel.java
* http://r0k.us/rock/Junk/ntc.java

(File ntc.java is only necessary if you plan on running it from your own build.)

-- Rich
RichF
I have more or less fixed the first and most significant problem ("wonky-white"). I kludged-in two full paints:
    public boolean partialOnly(Graphics g)
    {
	boolean	imDone = true;
	if (resized > 0)
	{   // should enter on 1 or 2
	    imDone = false;
	    resized += 1;	// clock thru two forced-full paints
	    if (resized > 2)  resized = 0;
	}
        ...
    }
It is not elegant, but forcing the two full paints appears to do whatever magic the double-buffers need. I'm still looking for a non-kludgy solution, which I suspect will fix the second problem as well.
RichF
I decided to continue this thread in the Swing forum. My issues are Swing now (yay!), and the other forum is a lot more popular. See "conversion from awt to Swing, colored list widget, and awt update() method" at:

* 1685138

Please respond there. Thank you.
1 - 10
Locked Post
New comments cannot be posted to this locked post.

Post Details

Locked on Nov 12 2010
Added on Oct 8 2010
10 comments
4,453 views