Java-Swing:使用HTML设置选定文本的颜色

5
我遇到了一个问题,不知道如何使用HTML设置JList选定文本的颜色。
我使用Java Swing和HTML,已经成功地为JList中每个字符串的特定部分设置了颜色,我的示例如下所示:
这样很理想,因为我可以为每个条目设置任意数量的不同颜色!
然而,当选择文本时,只有默认的黑色文本变成白色!html着色的文本保持其颜色,而不是也变成白色,这导致某些颜色的文本非常难读:
我该如何在选定时设置文本的颜色?
我尝试在JList上使用setSelectionForeground(Color.WHITE)方法,但它没有影响到html着色的文本(虽然它确实影响了非html着色的文本)。
我还阅读了Oracle的HTML-in-Swing教程(我最初发现了HTML着色),但找不到解决方案。
以下是我简短示例的代码:
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();
    }
}
1个回答

5

一种方法是使用ListCellRenderer,该渲染器使用replaceAll(...)从所选字符串中剥离出HTML代码。上帝啊,我讨厌在HTML中使用正则表达式,如果您的字符串中有非HTML的角括号<>,这种方法将无法工作。

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);
      }
   }
}

更好的解决方案:使用JSoup来去除HTML。
更好的方法是创建一个类来保存HTML和非HTML字符串,让列表(List)保存该类的对象,并在渲染器中交换字符串。

太好了!谢谢,这个完美地运作了!记住要小心非HTML的< >符号! - user3369258
@user3369258:毫无疑问,这是一个临时应急的方法,在某些情况下肯定会失败。感谢您发布了一个简洁易懂的可编译示例程序。现在是时候开始回答问题了,不是吗? ;) 您可能有很多有价值的贡献。 - Hovercraft Full Of Eels
哈哈,谢谢,我会看看是否能回答任何问题,我只是觉得这里的每个人都比我更有资格 :) - user3369258

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接