HighlightPainter issue with Substance UI when using Monospaced font

99封情书 提交于 2019-12-23 17:08:42

问题


I am using Highlighter.HighlightPainter interface for highlighting the lines of a text area. I used the source code from this website: Line Painter. It works just great, but when I used org.jvnet.substance.skin.SubstanceBusinessBlackSteelLookAndFeel for decorating the GUI, an issue comes up. Whenever I change the font of the text area to Monospaced, the paint() method of Highlighter.HighlightPainter isn't invoked for some reason. Here is a sample code:

import java.awt.Font;
import java.awt.Graphics;
import java.awt.Shape;
import javax.swing.BorderFactory;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.text.BadLocationException;
import javax.swing.text.Highlighter;
import javax.swing.text.JTextComponent;

public class TestFrame extends JFrame implements Highlighter.HighlightPainter
{
    private static final long serialVersionUID = 1L;

    static
    {
        try
        {
            JFrame.setDefaultLookAndFeelDecorated(true);
            JDialog.setDefaultLookAndFeelDecorated(true);
            UIManager.setLookAndFeel(new org.jvnet.substance.skin.SubstanceBusinessBlackSteelLookAndFeel()); 
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }

    public TestFrame() throws BadLocationException
    {
        super("The title");
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        JTextArea txt = new JTextArea(10, 30);
        txt.getHighlighter().addHighlight(0, 0, this);
        txt.setFont(new Font("Monospaced", Font.PLAIN, 12));
        JPanel container = (JPanel) getContentPane();
        container.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
        container.add(txt);
        pack();
        setLocationRelativeTo(null);
    }

    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                try
                {
                    new TestFrame().setVisible(true);
                }
                catch(BadLocationException e)
                {
                    e.printStackTrace();
                }
            }
        });
    }

    @Override
    public void paint(Graphics g, int p0, int p1, Shape bounds, JTextComponent c)
    {
        System.out.println("paint() is invoked!");
    }
}

If I comment this line:

txt.setFont(new Font("Monospaced", Font.PLAIN, 12));

paint() will be invoked. Is there anyway to fix this issue?


回答1:


1) @Eng.Fouad this was n_times mentioned (@camickr, @StanislavL) here for styled and highligted test use JTextComponent that supporting that

2) @Eng.Fouad you are right output from JTextArea

from code

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

public class TextPaneHighlighting {

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

    public TextPaneHighlighting() {
        JFrame frame = new JFrame();
        JTextPane textPane = new JTextPane();
        textPane.setText("one\ntwo\nthree\nfour\nfive\nsix\nseven\neight\n");
        //textPane.setFont(new Font("Monospaced", Font.PLAIN, 12)); // uncommnent
        JScrollPane scrollPane = new JScrollPane(textPane);
        frame.add(scrollPane, BorderLayout.CENTER);//  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) {
        }
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setPreferredSize(new Dimension(300, 200));
        frame.setLocationRelativeTo(null);
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                JFrame.setDefaultLookAndFeelDecorated(true);
                JDialog.setDefaultLookAndFeelDecorated(true);
                try {
                    UIManager.setLookAndFeel(new org.pushingpixels.substance.api.skin.SubstanceBusinessBlackSteelLookAndFeel());
                } catch (UnsupportedLookAndFeelException ex) {
                }
                TextPaneHighlighting tph = new TextPaneHighlighting();
            }
        });
    }
}

3) as @ trashgod correctly mentioned never to set whatever in Substance without invokeLater, never, whatever Look and Feel sensitive, right maybe in this moment Font isn't important, maybe not

4) simple JTextArea have got some issue with Font and Look and Feel, maybe there are own Highlighter concept as for Renderer (sorry I lazy read API after wake_up) and Substance, for Renderer concept you must to use SubstanceRenderer instead of XxxRenderer, then all formatting wokrs as you excepted

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

public class Fonts implements Runnable {

    private String[] fnt;
    private JFrame frm;
    private JScrollPane jsp;
    private JTextPane jta;
    private int width = 450;
    private int height = 300;
    private GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
    private StyledDocument doc;
    private MutableAttributeSet mas;
    private int cp = 0;
    private Highlighter.HighlightPainter cyanPainter = new DefaultHighlighter.DefaultHighlightPainter(Color.cyan);
    private Highlighter.HighlightPainter redPainter = new DefaultHighlighter.DefaultHighlightPainter(Color.red);
    private Highlighter.HighlightPainter whitePainter = new DefaultHighlighter.DefaultHighlightPainter(Color.white);
    private int _count = 0;
    private int _lenght = 0;

    public Fonts() {
        jta = new JTextPane();
        doc = jta.getStyledDocument();
        jsp = new JScrollPane(jta);
        jsp.setPreferredSize(new Dimension(height, width));
        frm = new JFrame("awesome");
        frm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frm.setLayout(new BorderLayout());
        frm.add(jsp, BorderLayout.CENTER);
        frm.setLocation(100, 100);
        frm.pack();
        frm.setVisible(true);
        jta.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
        fnt = ge.getAvailableFontFamilyNames();
        mas = jta.getInputAttributes();
        new Thread(this).start();
    }

    @Override
    public void run() {
        for (int i = 0; i < fnt.length; i++) {
            StyleConstants.setBold(mas, false);
            StyleConstants.setItalic(mas, false);
            StyleConstants.setFontFamily(mas, fnt[i]);
            StyleConstants.setFontSize(mas, 16);
            dis(fnt[i]);
            try {
                Thread.sleep(75);
            } catch (Exception e) {
                e.printStackTrace();
            }
            StyleConstants.setBold(mas, true);
            dis(fnt[i] + " Bold");
            try {
                Thread.sleep(75);
            } catch (Exception e) {
                e.printStackTrace();
            }
            StyleConstants.setItalic(mas, true);
            dis(fnt[i] + " Bold & Italic");
            try {
                Thread.sleep(75);
            } catch (Exception e) {
                e.printStackTrace();
            }
            StyleConstants.setBold(mas, false);
            dis(fnt[i] + " Italic");
            try {
                Thread.sleep(75);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        jta.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
    }

    public void dis(String s) {
        _count++;
        _lenght = jta.getText().length();
        try {
            doc.insertString(cp, s, mas);
            doc.insertString(cp, "\n", mas);
        } catch (Exception bla_bla_bla_bla) {
            bla_bla_bla_bla.printStackTrace();
        }
        if (_count % 2 == 0) {
            try {
                jta.getHighlighter().addHighlight(1, _lenght - 1, cyanPainter);
            } catch (BadLocationException bla_bla_bla_bla) {
            }
        } else if (_count % 3 == 0) {
            try {
                jta.getHighlighter().addHighlight(1, _lenght - 1, redPainter);
            } catch (BadLocationException bla_bla_bla_bla) {
            }
        } else {
            try {
                jta.getHighlighter().addHighlight(1, _lenght - 1, whitePainter);
            } catch (BadLocationException bla_bla_bla_bla) {
            }
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                JFrame.setDefaultLookAndFeelDecorated(true);
                JDialog.setDefaultLookAndFeelDecorated(true);
                try {
                    UIManager.setLookAndFeel(new org.pushingpixels.substance.api.skin.SubstanceBusinessBlackSteelLookAndFeel());
                } catch (UnsupportedLookAndFeelException ex) {
                }
                Fonts fs = new Fonts();
            }
        });
    }
}



回答2:


Well, there is one solution for this, create the text area and set a font for it just before calling UIManager.setLookAndFeel().




回答3:


Just for reference, here's a quick test of LinePainter:

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.Highlighter;
import javax.swing.text.JTextComponent;

/**
 * @see http://stackoverflow.com/q/10544046/230513
 * @see http://tips4java.wordpress.com/2008/10/29/line-painter/
 */
public class LinePainterTest extends JPanel {

    public LinePainterTest() {
        JTextPane textPane = new JTextPane();
        textPane.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 24));
        try {
            textPane.getDocument().insertString(0, "One\nTwo\nThree", null);
        } catch (BadLocationException ex) {
            ex.printStackTrace(System.err);
        }
        LinePainter painter = new LinePainter(textPane);
        this.add(textPane);
    }

    private void display() {
        JFrame f = new JFrame("LinePainterTest");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(this);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    public static void main(String[] args) throws Exception {
        UIManager.setLookAndFeel(
            "com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
        JFrame.setDefaultLookAndFeelDecorated(true);
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new LinePainterTest().display();
            }
        });
    }
}


来源:https://stackoverflow.com/questions/10544046/highlightpainter-issue-with-substance-ui-when-using-monospaced-font

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!