如何更改 Java Swing TextArea 中的突出显示颜色?此外,更改与突出显示位置对应的文本的开头

Posted

技术标签:

【中文标题】如何更改 Java Swing TextArea 中的突出显示颜色?此外,更改与突出显示位置对应的文本的开头【英文标题】:How to change highlighting color in Java Swing TextArea? And also, change the beginning of text corresponding to the highlighting location 【发布时间】:2012-05-05 14:53:23 【问题描述】:

问题 1:通过使用 defaulthighlighter,我可以使焦点线变为蓝色。 现在我想将其更改为其他颜色。有人知道如何更改此参数吗? --- 解决了

问题 2:pos 是我要突出显示的子字符串的开始索引。我使用 setCaretPosition(pos);更新显示内容。但它总是出现在窗口的底部。我想把它放在顶部。谁能告诉我如何处理它?

我用一个演示来展示我的问题:

import java.awt.Color;
import java.net.MalformedURLException;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultHighlighter;

public class Test 
    public static void main(final String[] args) throws MalformedURLException 
        SwingUtilities.invokeLater(new Runnable() 

        @Override
        public void run() 
            try 
                init();
             catch (BadLocationException e) 
                // TODO Auto-generated catch block
                e.printStackTrace();
            

        
    );


private static void init() throws BadLocationException 
    JFrame frame = new JFrame();
    final JTextArea textArea = new JTextArea();
    JScrollPane pane = new JScrollPane(textArea);
    textArea.setText("Something. Something else.\nA second line\na third line"
            + "Blabla\nBlabla\nBlabla\nBlabla\nBlabla\nBlabla\nBlabla\n"
            + "Blabla\nBlabla\nBlabla\nBlabla\nBlabla\nBlabla\nSomething. Samething else.\nA second line\na third line"
            + "Blabla\nBlabla\nBlabla\nBlabla\nBlabla\nBlabla\nBlabla\n"
            + "Blabla\nBlabla\nBlabla\nBlabla\nBlabla\nBlabla\nSomething. Sbmething else.\nA second line\na third line"
            + "Blabla\nBlabla\nBlabla\nBlabla\nBlabla\nBlabla\nBlabla\n"
            + "Blabla\nBlabla\nBlabla\nBlabla\nBlabla\nBlabla\nSomething. Scmething else.\nA second line\na third line"
            + "Blabla\nBlabla\nBlabla\nBlabla\nBlabla\nBlabla\nBlabla\n"
            + "Blabla\nBlabla\nBlabla\nBlabla\nBlabla\nBlabla\nSomething. Sdmething else.\nA second line\na third line"
            + "Blabla\nBlabla\nBlabla\nBlabla\nBlabla\nBlabla\nBlabla\n"
            + "Blabla\nBlabla\nBlabla\nBlabla\nBlabla\nBlabla\nSomething. Semething else.\nA second line\na third line"
            + "Blabla\nBlabla\nBlabla\nBlabla\nBlabla\nBlabla\nBlabla\n"
            + "Blabla\nBlabla\nBlabla\nBlabla\nBlabla\nBlabla\nSomething. Sfmething else.\nA second line\na third line"
            + "Blabla\nBlabla\nBlabla\nBlabla\nBlabla\nBlabla\nBlabla\n"
            + "Blabla\nBlabla\nBlabla\nBlabla\nBlabla\nBlabla\nSomething. Sgmething else.\nA second line\na third line"
            + "Blabla\nBlabla\nBlabla\nBlabla\nBlabla\nBlabla\nBlabla\n"
            + "Blabla\nBlabla\nBlabla\nBlabla\nBlabla\nBlabla\n");
    textArea.setSelectionColor(Color.RED);
    frame.add(pane);
    frame.setSize(300, 120);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setVisible(true);

    String turnToString2 = "Sdmething else.\nA second line\na third line"
            + "Blabla\nBlabla\nBlabla\nBlabla\nBlabla";
    int pos2 = textArea.getText().indexOf(turnToString2);
    textArea.getHighlighter().addHighlight(pos2,
            pos2 + turnToString2.length(),
            new DefaultHighlighter.DefaultHighlightPainter(Color.yellow));
    textArea.setCaretPosition(pos2);

结果是:

我希望它位于屏幕的右上角,但在此代码中,它显示在滚动窗格的底部。谁能知道如何改变这个? 谢谢。

【问题讨论】:

看看我最新的编辑,这是你想要的吗? @nIcEcOw 您好,非常感谢您的编辑。我现在使用 Guillaume Polet 的演示代码来说明我的问题。你能运行它并看看它吗?谢谢。 我已经做了一点,尝试通过运行最新代码来测试它,我希望这可能会有所帮助:-) 【参考方案1】:

您可以实现这一点,尽管不是直接的,因为您必须保存对已添加到所述行的 Highlight 的引用,因此您必须遍历所有的 Highlights 以删除您想要的,有看看随附的程序,这可能会帮助您实现您的愿望:

最新编辑:新代码,删除了一些错误,似乎添加了与设置插入位置相关的所需功能

import java.awt.*;
import java.awt.event.*;
import java.util.Map;
import java.util.HashMap;
import javax.swing.*;
import javax.swing.text.*;

public class TextHighlight

    private JTextArea tarea;
    private JComboBox cbox;
    private JTextField lineField;
    private String[] colourNames = "RED", "ORANGE", "CYAN";

    private Highlighter.HighlightPainter redPainter;
    private Highlighter.HighlightPainter orangePainter;
    private Highlighter.HighlightPainter cyanPainter;   

    private int firstUpdateIndex;
    private int counter;

    private Map<Integer, Highlighter.Highlight> highlights = new HashMap<Integer, Highlighter.Highlight>();

    public TextHighlight()
    
        redPainter = new DefaultHighlighter.DefaultHighlightPainter(Color.RED);
        orangePainter = new DefaultHighlighter.DefaultHighlightPainter(Color.ORANGE);
        cyanPainter = new DefaultHighlighter.DefaultHighlightPainter(Color.CYAN);

        firstUpdateIndex = -1;
        counter = 0;
    

    private void createAndDisplayGUI()
    
        final JFrame frame = new JFrame("Text HIGHLIGHT");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        JPanel contentPane = new JPanel();
        contentPane.setBorder(BorderFactory.createTitledBorder(
                BorderFactory.createEmptyBorder(5, 5, 5, 5), "Highlighter JTextArea"));

        tarea = new JTextArea(10, 10);
        JScrollPane scrollPane = new JScrollPane(tarea);
        contentPane.add(scrollPane);

        JButton remHighButton = new JButton("REMOVE HIGHLIGHT");
        remHighButton.addActionListener(new ActionListener()
        
            public void actionPerformed(ActionEvent ae)
            
                String input = JOptionPane.showInputDialog(frame, "Please Enter Start Index : "
                                                        , "Highlighting Options : "
                                                        , JOptionPane.PLAIN_MESSAGE);

                if (input != null && (highlights.size() > 0))
                               
                    int startIndex = Integer.parseInt(input.trim());
                    Highlighter highlighter = tarea.getHighlighter();
                    highlighter.removeHighlight(highlights.get(startIndex));
                    tarea.setCaretPosition(startIndex);
                    tarea.requestFocusInWindow();
                    highlights.remove(startIndex);
                
            
        );

        JButton button = new JButton("HIGHLIGHT TEXT");
        button.addActionListener(new ActionListener()
        
            public void actionPerformed(ActionEvent ae)
            
                String text = null;
                text = tarea.getSelectedText();
                if (text != null && text.length() > 0)
                
                    int startIndex = tarea.getText().indexOf(text);
                    int endIndex = startIndex + text.length();
                    Highlighter highlighter = tarea.getHighlighter();

                    int selection = JOptionPane.showConfirmDialog(
                                            frame, getOptionPanel(), "Highlight Colour : "
                                                , JOptionPane.OK_CANCEL_OPTION
                                                , JOptionPane.PLAIN_MESSAGE);

                    System.out.println("TEXT : " + text);
                    System.out.println("START INDEX : " + startIndex);
                    System.out.println("END INDEX : " + endIndex);

                    if (selection == JOptionPane.OK_OPTION)
                    
                        String colour = (String) cbox.getSelectedItem();
                        try
                        
                            if (colour == colourNames[0])
                            
                                System.out.println("Colour Selected : " + colour);
                                highlighter.addHighlight(startIndex, endIndex, redPainter);
                            
                            else if (colour == colourNames[1])
                            
                                System.out.println("Colour Selected : " + colour);
                                highlighter.addHighlight(startIndex, endIndex, orangePainter);
                            
                            else if (colour == colourNames[2])
                            
                                System.out.println("Colour Selected : " + colour);
                                highlighter.addHighlight(startIndex, endIndex, cyanPainter);
                            
                            Highlighter.Highlight[] highlightIndex = highlighter.getHighlights();
                            System.out.println("Lengh of Highlights used : " + highlightIndex.length);
                            highlights.put(startIndex, highlightIndex[highlightIndex.length - 1]);
                        
                        catch(BadLocationException ble)
                        
                            ble.printStackTrace();
                        
                    
                    else if (selection == JOptionPane.CANCEL_OPTION)
                    
                        System.out.println("CANCEL BUTTON PRESSED.");
                    
                    else if (selection == JOptionPane.CLOSED_OPTION)
                    
                        System.out.println("JOPTIONPANE CLOSED DELIBERATELY.");
                                       
                
            
        );

        frame.add(remHighButton, BorderLayout.PAGE_START);
        frame.add(contentPane, BorderLayout.CENTER);
        frame.add(button, BorderLayout.PAGE_END);

        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    

    private JPanel getOptionPanel()
    
        JPanel panel = new JPanel();
        panel.setBorder(BorderFactory.createTitledBorder(
                        BorderFactory.createLineBorder(Color.DARK_GRAY, 2), "COLOUR SELECTION"));
        panel.setLayout(new GridLayout(0, 2, 5, 5));

        JLabel colourLabel = new JLabel("Select One Colour : ");
        cbox = new JComboBox(colourNames);

        panel.add(colourLabel);
        panel.add(cbox);

        return panel;
    

    public static void main(String... args)
    
        SwingUtilities.invokeLater(new Runnable()
        
            public void run()
            
                new TextHighlight().createAndDisplayGUI();
            
        );
    

输出:

开始:

强调第一行 第二

删除亮点

用不同的颜色突出显示同一行

最新编辑符合问题中的示例代码

import java.awt.*;
import java.net.MalformedURLException;

import javax.swing.*;
import javax.swing.text.*;

public class Test 
    public static void main(final String[] args) throws MalformedURLException 
        SwingUtilities.invokeLater(new Runnable() 

        @Override
        public void run() 
            try 
                init();
             catch (BadLocationException e) 
                // TODO Auto-generated catch block
                e.printStackTrace();
            

        
    );


private static void init() throws BadLocationException 
    JFrame frame = new JFrame();
    final JTextArea textArea = new JTextArea();
    JScrollPane pane = new JScrollPane(textArea);
    textArea.setText("Something. Something else.\nA second line\na third line"
            + "Blabla\nBlabla\nBlabla\nBlabla\nBlabla\nBlabla\nBlabla\n"
            + "Blabla\nBlabla\nBlabla\nBlabla\nBlabla\nBlabla\nSomething. Samething else.\nA second line\na third line"
            + "Blabla\nBlabla\nBlabla\nBlabla\nBlabla\nBlabla\nBlabla\n"
            + "Blabla\nBlabla\nBlabla\nBlabla\nBlabla\nBlabla\nSomething. Sbmething else.\nA second line\na third line"
            + "Blabla\nBlabla\nBlabla\nBlabla\nBlabla\nBlabla\nBlabla\n"
            + "Blabla\nBlabla\nBlabla\nBlabla\nBlabla\nBlabla\nSomething. Scmething else.\nA second line\na third line"
            + "Blabla\nBlabla\nBlabla\nBlabla\nBlabla\nBlabla\nBlabla\n"
            + "Blabla\nBlabla\nBlabla\nBlabla\nBlabla\nBlabla\nSomething. Sdmething else.\nA second line\na third line"
            + "Blabla\nBlabla\nBlabla\nBlabla\nBlabla\nBlabla\nBlabla\n"
            + "Blabla\nBlabla\nBlabla\nBlabla\nBlabla\nBlabla\nSomething. Semething else.\nA second line\na third line"
            + "Blabla\nBlabla\nBlabla\nBlabla\nBlabla\nBlabla\nBlabla\n"
            + "Blabla\nBlabla\nBlabla\nBlabla\nBlabla\nBlabla\nSomething. Sfmething else.\nA second line\na third line"
            + "Blabla\nBlabla\nBlabla\nBlabla\nBlabla\nBlabla\nBlabla\n"
            + "Blabla\nBlabla\nBlabla\nBlabla\nBlabla\nBlabla\nSomething. Sgmething else.\nA second line\na third line"
            + "Blabla\nBlabla\nBlabla\nBlabla\nBlabla\nBlabla\nBlabla\n"
            + "Blabla\nBlabla\nBlabla\nBlabla\nBlabla\nBlabla\n");
    textArea.setSelectionColor(Color.RED);
    frame.add(pane);
    frame.setSize(300, 120);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setVisible(true);

    String turnToString2 = "Sdmething else.\nA second line\na third line"
            + "Blabla\nBlabla\nBlabla\nBlabla\nBlabla";
    int pos2 = textArea.getText().indexOf(turnToString2);
    Rectangle startIndex = textArea.modelToView(pos2);
    textArea.getHighlighter().addHighlight(pos2,
            pos2 + turnToString2.length(),
            new DefaultHighlighter.DefaultHighlightPainter(Color.yellow));    
    int y = startIndex.y + (pane.getHeight() - 10);
    System.out.println("Pane Height : " + pane.getHeight());
    System.out.println("X : " + startIndex.x);
    System.out.println("Y : " + y);
    System.out.println("Y (pos2) : " + startIndex.y);
    textArea.setCaretPosition(textArea.viewToModel(new Point(startIndex.x, y)));
    pane.scrollRectToVisible(new Rectangle(startIndex.x, y));
    

这是输出:

【讨论】:

非常感谢您的示例!我确实学习了……但是,您有解决我的问题 2 的方法吗?具体来说,假设我有很多行需要 scrollPane 自动生成滚动条。如果我突出显示一行,我希望窗口中出现的第一行是突出显示的那一行。我使用:windowText.setCaretPosition(pos);其中 pos 是 Highlighting 子字符串的索引。但它没有正常工作。突出显示的行将出现在此窗口的末尾。 至少对我来说,这件事有点棘手JScrollPane 的位置,然后它永远不会自动移动:(,看着那个东西 @nlcE 牛 谢谢。我没有手动更改位置。 Acutally 我的事情是我将此 Textarea 与其他面板链接。因此,当我单击某行时,我也希望在此 TextArea 中突出显示同一行。所以我需要插入符号来使高亮线显示在顶部,而不仅仅是显示在窗口中,这还不够。 SetCaretPosition(Position) 不起作用是没有意义的。它应该将定位线带到顶部.... @AnneS :“它应该将定位线带到顶部......”,不setCaretPosition(...)只会改变插入符号的位置,而不是文本。您必须自己插入文本,方法是从指定位置选择它并在另一个位置插入(在 TOP,我猜在你的情况下) @nIcE cOw 你必须从 Highlighter[] 和内部循环中删除 highlighter.removeHighlight() +1【参考方案2】:

要设置选择背景颜色,请使用 setSelectionColor(如下图所示,但未使用)。

我不太明白你在说什么,它总是出现在窗口的底部。我想将它放在顶部,但我猜测(我可能在这里错了)您的文本区域位于滚动窗格中,并且通过突出显示文本,它会滚动到您选择的末尾,所以我建议在突出显示文本后设置插入符号的位置。

这是我理解的一个示例。如果这不是您要找的,请告诉我:

import java.awt.Color;
import java.net.MalformedURLException;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultHighlighter;

public class Test 
    public static void main(final String[] args) throws MalformedURLException 
        SwingUtilities.invokeLater(new Runnable() 

            @Override
            public void run() 
                try 
                    init();
                 catch (BadLocationException e) 
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                

            
        );
    

    private static void init() throws BadLocationException 
        JFrame frame = new JFrame();
        final JTextArea textArea = new JTextArea();
        JScrollPane pane = new JScrollPane(textArea);
        textArea.setText("Something. Something else.\nA second line\na third line"
                + "Blabla\nBlabla\nBlabla\nBlabla\nBlabla\nBlabla\nBlabla\n"
                + "Blabla\nBlabla\nBlabla\nBlabla\nBlabla\nBlabla\n");
        textArea.setSelectionColor(Color.RED);
        frame.add(pane);
        frame.setSize(300, 120);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
        String turnToString = "Something else.\nA second line\na third line"
                + "Blabla\nBlabla\nBlabla\nBlabla\nBlabla";
        final int pos = textArea.getText().indexOf(turnToString);
        textArea.getHighlighter().addHighlight(pos,
                pos + turnToString.length(),
                new DefaultHighlighter.DefaultHighlightPainter(Color.yellow));
        textArea.scrollRectToVisible(new Rectangle(0, 0, pane.getViewport().getWidth(), pane.getViewport().getHeight()));
            SwingUtilities.invokeLater(new Runnable() 
                    @Override
                    public void run() 
                        textArea.setCaretPosition(pos);
                    
            );
    

【讨论】:

@mKorbel 嘿,我们又见面了 ;-) 我实际上误解了有关突出显示和选择的问题。我不确定 OP 在寻找什么。无论如何,感谢您的帮助,我从根本上改变了我的答案。干杯。 @GuillaumePolet 感谢您的回答。通过使用 DefaultHighlightPainter(Color.yellow) 代替,可以操纵颜色。至于 caretPosition,我的问题是当 scrollPane 中显示 20 行时,突出显示的 2 行显示在底部,这应该显示在当前窗口的前两行。你知道怎么回事吗? @AnneS 使用我的代码或来自 mKorbel 的代码,并尝试说明您遇到的问题;使用该代码编辑您的问题。如果没有完整的代码,我们无法猜测问题可能是什么。我们都试图向您展示突出显示的效果,但肯定有一些差异导致您的代码无法正常工作 @GuillaumePolet 谢谢你的建议。我已经做到了。可以看看吗? @AnneS 我用一个解决方案编辑了我的帖子,使插入符号行成为滚动窗格中可见的第一行。这有点丑陋,但效果很好。我没有看到任何直接的 API 方法来找到滚动需要去的地方。另一种解决方案是访问 TextComponent 的 UI 并询问映射器插入符号位置的确切 Rectangle,然后直接滚动到该矩形。【参考方案3】:

解决 2) 使用 modelToView 获取第一个选定行的点。然后使用 Point 使用 scrollRectToVisible (注意:矩形的高度必须是您的视口高度)。

【讨论】:

我听说过很多关于 modelToView 的事,今天看来我已经直接通过它来消除我的疑问 :-) +1【参考方案4】:

我认为在使用荧光笔的情况下无法更改所有 JTextComponents 的这些方法,但可以仅更改前景

例如

import java.awt.*;
import javax.swing.*;
import javax.swing.text.DefaultHighlighter;

public class TextAreaLineHightLight 

    public static void main(String[] args) throws Exception 
        UIManager.put("TextArea.selectionBackground", Color.yellow);
        UIManager.put("TextArea.selectionForeground", Color.red);

        String string = "Lorem ipsum eum putant gubergren evertitur in, "
                + "no assueverit vituperatoribus eum. Ea cibo offendit vim, est et vivendum qualisque prodesset. "
                + "Vis doctus expetenda contentiones an, no ius mazim epicuri expetendis, "
                + "saperet salutandi forensibus ne usu. Ex fugit alterum usu. "
                + "His ignota cotidieque in, augue erroribus eam no.";
        JTextArea textArea = new JTextArea(string);
        textArea.setLineWrap(true);
        textArea.setWrapStyleWord(true);
        JScrollPane textAreaScroll = new JScrollPane(textArea);
        JFrame frame = new JFrame();
        frame.setLayout(new BorderLayout());
        frame.add(textAreaScroll, BorderLayout.CENTER);
        frame.setSize(400, 300);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
        String term = "qualisque prodesset. "
                + "Vis doctus expetenda contentiones an, no ius mazim epicuri expetendis";
        int termOffset = string.indexOf(term);
        Rectangle view = textArea.modelToView(termOffset);
        int startOffset = textArea.viewToModel(new Point(0, view.y));
        //int rowH = textArea.
        int endOffset = textArea.viewToModel(new Point(textArea.getSize().width, view.y));
        textArea.getHighlighter().addHighlight(startOffset, endOffset, new DefaultHighlighter.DefaultHighlightPainter(Color.YELLOW));
    

与 JTextPane 的结果相同

import java.awt.*;
import javax.swing.*;
import javax.swing.text.*;

public class TextPaneHighlighting extends JFrame 

    private static final long serialVersionUID = 1L;
    private Highlighter.HighlightPainter cyanPainter;
    private Highlighter.HighlightPainter redPainter;

    public TextPaneHighlighting() 
        UIManager.put("TextPane.selectionBackground", Color.yellow);
        UIManager.put("TextPane.selectionForeground", Color.red);
        JTextPane textPane = new JTextPane();
        textPane.setText("one\ntwo\nthree\nfour\nfive\nsix\nseven\neight\n");
        JScrollPane scrollPane = new JScrollPane(textPane);
        getContentPane().add(scrollPane);//  Highlight some text
        cyanPainter = new DefaultHighlighter.DefaultHighlightPainter(Color.cyan);
        redPainter = new DefaultHighlighter.DefaultHighlightPainter(Color.red);
        try 
            textPane.getHighlighter().addHighlight(0, 3, DefaultHighlighter.DefaultPainter);
            textPane.getHighlighter().addHighlight(8, 14, cyanPainter);
            textPane.getHighlighter().addHighlight(19, 24, redPainter);
         catch (BadLocationException ble) 
        
    

    public static void main(String[] args) 
        TextPaneHighlighting frame = new TextPaneHighlighting();
        frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
        frame.setSize(300, 200);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    

【讨论】:

既然 setSelectionColor 和 setSelectedTextColor 可用,为什么不使用它们来更改颜色? 谢谢!基本上,你和 Guillaume 有相同的解决方案 - DefaultHighlightPainter(Color.XXX)。

以上是关于如何更改 Java Swing TextArea 中的突出显示颜色?此外,更改与突出显示位置对应的文本的开头的主要内容,如果未能解决你的问题,请参考以下文章

Java Swing - 在带有线条边框的 TextArea 上设置边距

当我在键盘上输入特定字母时,我想更新 TextArea(swing) 上的特定图像。如何?

TextArea Swing 和 JavaFX 选择范围的区别

如何在 java swing 运行时更改语言

Java Swing - 如何更改 JPanel 的 TitledBorder 上的字体大小?

java的JTextArea 和 TextArea 到底有啥根本的区别。