Discussions
Categories
- 385.5K All Categories
- 4.9K Data
- 2.5K Big Data Appliance
- 2.4K Data Science
- 453.4K Databases
- 223.2K General Database Discussions
- 3.8K Java and JavaScript in the Database
- 47 Multilingual Engine
- 606 MySQL Community Space
- 486 NoSQL Database
- 7.9K Oracle Database Express Edition (XE)
- 3.2K ORDS, SODA & JSON in the Database
- 585 SQLcl
- 4K SQL Developer Data Modeler
- 188K SQL & PL/SQL
- 21.5K SQL Developer
- 46 Data Integration
- 46 GoldenGate
- 298.4K Development
- 4 Application Development
- 20 Developer Projects
- 166 Programming Languages
- 295K Development Tools
- 150 DevOps
- 3.1K QA/Testing
- 646.7K Java
- 37 Java Learning Subscription
- 37.1K Database Connectivity
- 201 Java Community Process
- 108 Java 25
- 22.2K Java APIs
- 138.3K Java Development Tools
- 165.4K Java EE (Java Enterprise Edition)
- 22 Java Essentials
- 176 Java 8 Questions
- 86K Java Programming
- 82 Java Puzzle Ball
- 65.1K New To Java
- 1.7K Training / Learning / Certification
- 13.8K Java HotSpot Virtual Machine
- 94.3K Java SE
- 13.8K Java Security
- 208 Java User Groups
- 25 JavaScript - Nashorn
- Programs
- 667 LiveLabs
- 41 Workshops
- 10.3K Software
- 6.7K Berkeley DB Family
- 3.6K JHeadstart
- 6K Other Languages
- 2.3K Chinese
- 207 Deutsche Oracle Community
- 1.1K Español
- 1.9K Japanese
- 474 Portuguese
list widget with different colors for each list item?

RichF
Member Posts: 214
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
* 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
Tagged:
Best 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
Answers
-
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 -
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 -
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 -
RichF wrote:Agreed.
Piet, wow, that's beautiful!!..Time to learn Swing, enter the 21st century ...++ -
Andrew Thompson wrote:So you see, in some cases, rare I do agree, just "giving the codes" may have some educational value ;-)RichF wrote:Agreed.
Piet, wow, that's beautiful!!..Time to learn Swing, enter the 21st century ...++
Piet -
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 -
RichF wrote: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.
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.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 -
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 -
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. -
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.
This discussion has been closed.