This discussion is archived
10 Replies Latest reply: Oct 15, 2010 8:37 PM by 801338 RSS

list widget with different colors for each list item?

801338 Newbie
Currently Being Moderated
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
  • 1. Re: list widget with different colors for each list item?
    801338 Newbie
    Currently Being Moderated
    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
  • 2. Re: list widget with different colors for each list item?
    800025 Explorer
    Currently Being Moderated
    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
  • 3. Re: list widget with different colors for each list item?
    801338 Newbie
    Currently Being Moderated
    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
  • 4. Re: list widget with different colors for each list item?
    793415 Pro
    Currently Being Moderated
    RichF wrote:
    Piet, wow, that's beautiful!! :)
    Agreed.
    ..Time to learn Swing, enter the 21st century ...
    ++ ;)
  • 5. Re: list widget with different colors for each list item?
    800025 Explorer
    Currently Being Moderated
    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
  • 6. Re: list widget with different colors for each list item?
    801338 Newbie
    Currently Being Moderated
    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:

    * simpler way to sort 2-d string array?

    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
  • 7. Re: list widget with different colors for each list item?
    800025 Explorer
    Currently Being Moderated
    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
  • 8. Re: list widget with different colors for each list item?
    801338 Newbie
    Currently Being Moderated
    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
  • 9. Re: list widget with different colors for each list item?
    801338 Newbie
    Currently Being Moderated
    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.
  • 10. Re: list widget with different colors for each list item?
    801338 Newbie
    Currently Being Moderated
    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:

    * conversion from awt to Swing, colored list widget, and awt update() method

    Please respond there. Thank you.

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points