Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java-Swing: Setting Selected Text Color with HTML

I'm having problems finding out how to set the Color of my JList's Selected Text using HTML.

Using Java Swing and HTML I've managed to color specific sections of each String in my JList, my example looks like this:

enter image description here

This is ideal as I can set as many different colors as I want for each entry!

However, when the text is selected, only the default Black text turns White! The html-colored text keeps its color instead of also turning white, this leads to some pretty hard-to-read text for some colors:

enter image description here

How would I be able to set the Text's Color when Selected?

I've tried using JList's setSelectionForeground(Color.WHITE) method on the JList but it did not affect the html-colored text (although it did affect the non-html-colored text)

I've also read up on Oracle's HTML-in-Swing tutorial (where I first found out about coloring with HTML) but could not find a solution.

Here is the code to my short example:

import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.UIManager;
import java.awt.Color;

public class JListSelectionColorTest extends JFrame {

    private String[] exampleText = {"Some example text without any color changes",
        "Some more example text without color changes",
        "Even more plain text!", 
        "<html>Uncolored Text! <font color=orange>Now some example Text with color!</font> more Uncolored Text!</html>", 
        "<html>Uncolored Text! <font color=green>And some more example text with color! Text, Text, Text!</font> more Uncolored Text!</html>",
        "<html>Uncolored Text! <font color=red>A string with red color, Text Text Text!</font> more Uncolored Text!</html>",
        "<html>Uncolored Text! <font color=blue>And finally a string with blue color, Text Text Text!</font> more Uncolored Text!</html>",
        "<html>Uncolored Text! <font color=purple><selection color=white>Testing if some html can turn the selection color white!</selection></font> more Uncolored Text!</html>"};

    public JListSelectionColorTest() {
        super("JList Selection Color Test");

        // Set the Look and Feel of the window to the Native System's Look and Feel
        // (When using the default Look and Feel the problem still persists!)
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (Exception e) {
            e.printStackTrace();
        }

        // Create a JList of Strings containing the exampleText String array
        JList<String> exampleJList = new JList<String>(exampleText);

        // Set the JList's text selection color to white
        exampleJList.setSelectionForeground(Color.WHITE); // This doesn't seem to affect the html-colored text's selection foreground

        // Add the JList to the JFrame
        add(exampleJList);

        pack();
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
        setVisible(true);
    }
    public static void main(String[] args) {
        new JListSelectionColorTest();
    }
}
like image 329
user3369258 Avatar asked Mar 27 '14 22:03

user3369258


1 Answers

One way, use a ListCellRenderer that uses replaceAll(...) to strip the HTML code out of your selected String. God I hate to use regex with HTML, and this won't work if your String has non-HTML angle brackets, < or > in it.

import javax.swing.DefaultListCellRenderer;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.UIManager;

import java.awt.Color;
import java.awt.Component;

public class JListSelectionColorTest extends JFrame {

   private String[] exampleText = {
         "Some example text without any color changes",
         "Some more example text without color changes",
         "Even more plain text!",
         "<html>Uncolored Text! <font color=orange>Now some example Text with color!</font> more Uncolored Text!</html>",
         "<html>Uncolored Text! <font color=green>And some more example text with color! Text, Text, Text!</font> more Uncolored Text!</html>",
         "<html>Uncolored Text! <font color=red>A string with red color, Text Text Text!</font> more Uncolored Text!</html>",
         "<html>Uncolored Text! <font color=blue>And finally a string with blue color, Text Text Text!</font> more Uncolored Text!</html>",
         "<html>Uncolored Text! <font color=purple><selection color=white>Testing if some html can turn the selection color white!</selection></font> more Uncolored Text!</html>" };

   public JListSelectionColorTest() {
      super("JList Selection Color Test");

      try {
         UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
      } catch (Exception e) {
         e.printStackTrace();
      }
      JList<String> exampleJList = new JList<String>(exampleText);

      exampleJList.setCellRenderer(new MyCellRenderer());
      exampleJList.setSelectionForeground(Color.WHITE); 
      add(exampleJList);

      pack();
      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      setLocationRelativeTo(null);
      setVisible(true);
   }

   public static void main(String[] args) {
      new JListSelectionColorTest();
   }

   private static class MyCellRenderer extends DefaultListCellRenderer {
      // create a non-greedy regex to capture anything between angle brackets.
      private String regex = "\\<.*?\\>";

      @Override
      public Component getListCellRendererComponent(JList<?> list,
            Object value, int index, boolean isSelected, boolean cellHasFocus) {
         if (value == null) {
            return super.getListCellRendererComponent(list, value, index,
                  isSelected, cellHasFocus);
         }

         // only interested in selected Strings
         if (isSelected) {
            String valueStr = value.toString(); // get the String
            valueStr = valueStr.replaceAll(regex, "");  // extract the HTML
            value = valueStr;  // put back into value Object variable
         }
         return super.getListCellRendererComponent(list, value, index,
               isSelected, cellHasFocus);
      }
   }
}

A better solution: use JSoup to strip out the HTML.
Better still, create a class that holds HTML and non-HTML Strings, have the List hold objects of this class, and swap the Strings in the renderer.

like image 65
Hovercraft Full Of Eels Avatar answered Sep 21 '22 21:09

Hovercraft Full Of Eels