简体   繁体   English

将RTF / HTML字符串绘制到自定义的swing组件中

[英]Paint RTF/HTML strings into a custom swing component

In my Swing application, users enter styled text into a JTextPane which uses an RTFEditorKit (HTML is also a possibility). 在我的Swing应用程序中,用户将样式文本输入到使用RTFEditorKit的JTextPane中(也可以使用HTML)。

I then need to render many of these styled notes at specific coordinates in a custom component. 然后,我需要在自定义组件中的特定坐标处渲染许多样式注释。

I would think the View.paint method would be helpful here, but I'm not able to create a usable View object. 我认为View.paint方法在这里会有所帮助,但是我无法创建可用的View对象。

I have the following method: 我有以下方法:

public View createView() throws IOException, BadLocationException {
 RTFEditorKit kit = new RTFEditorKit();
 final Document document = kit.createDefaultDocument();
 kit.read(new ByteArrayInputStream(text.getBytes("UTF-8")), document, 0);
 return kit.getViewFactory().create(document.getDefaultRootElement());
}

This returns a javax.swing.text.BoxView with the following attributes: 这将返回具有以下属性的javax.swing.text.BoxView:

majorAxis = 1
majorSpan = 0
minorSpan = 0
majorReqValid = false
minorReqValid = false
majorRequest = null
minorRequest = null
majorAllocValid = false
majorOffsets = {int[0]@2321}
majorSpans = {int[0]@2322}
minorAllocValid = false
minorOffsets = {int[0]@2323}
minorSpans = {int[0]@2324}
tempRect = {java.awt.Rectangle@2325}"java.awt.Rectangle[x=0,y=0,width=0,height=0]"
children = {javax.swing.text.View[1]@2326}
nchildren = 0
left = 0
right = 0
top = 0
bottom = 0
childAlloc = {java.awt.Rectangle@2327}"java.awt.Rectangle[x=0,y=0,width=0,height=0]"
parent = null
elem = {javax.swing.text.DefaultStyledDocument$SectionElement@2328}"BranchElement(section) 0,35\n"

Note that parent = null and nchildren = 0. This means there's nothing really useful there. 注意,parent = null,nchildren =0。这意味着那里没有什么真正有用的。 I can hack together something by calling JTextPane.getUI().paint , but the text pane needs to be visible, and this feels like the wrong way to do it. 我可以通过调用JTextPane.getUI().paint来一起破解某些东西,但是文本窗格必须可见,这感觉像是错误的方式。

Is there any way to get a visual representation of the RTF content without rendering the actual JTextPane? 有没有办法在不渲染实际JTextPane的情况下获得RTF内容的可视化表示?

This code sort of works, but seems less than ideal. 这段代码行得通,但似乎并不理想。 Is there a better way to do it? 有更好的方法吗? Also, what's a good way to render the text somewhere other than 0,0 on the graphics? 另外,在图形上除0,0之外的其他地方呈现文本的好方法是什么?

private static void testRtfRender() {
    String s = "{\\rtf1\\ansi\n" +
            "{\\fonttbl\\f0\\fnil Monospaced;\\f1\\fnil Lucida Grande;}\n" +
            "\n" +
            "\\f1\\fs26\\i0\\b0\\cf0 this is a \\b test\\b0\\par\n" +
            "}";

    JTextPane pane = new JTextPane();
    pane.setContentType("text/rtf");
    pane.setText(s);

    final Dimension preferredSize = pane.getUI().getPreferredSize(pane);
    int w = preferredSize.width;
    int h = preferredSize.height;

    pane.setSize(w, h);
    pane.addNotify();
    pane.validate();

    // would be nice to use this box view instead of instantiating a UI
    // however, unless you call setParent() on the view it's useless
    // What should the parent of a root element be?
    //BoxView view = (BoxView) pane.getEditorKit().getViewFactory().create(pane.getStyledDocument().getDefaultRootElement());
    //view.paint(d, new Rectangle(w, h));

    BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
    final Graphics2D d = img.createGraphics();
    d.setClip(0, 0, w, h); // throws a NullPointerException if I leave this out
    pane.getUI().paint(d, pane);
    d.dispose();
    JOptionPane.showMessageDialog(null, new JLabel(new ImageIcon(img)));
}

Check out the ScreenImage class which allows you to create a BufferedImage of any Swing component. ScreenImage类,该类使您可以创建任何Swing组件的BufferedImage。 It should also work for Swing components that are not visible, but yes you do have to do the rendering first. 它也应适用于不可见的Swing组件,但是是的,您必须先进行渲染。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM