java - 访问/更改 JEditorPane 的 html 加载元素 + Unicode (Java) 的 HTMLEditorKit 问题

标签 java unicode jeditorpane dom htmleditorkit

这将是一个很长的问题,请耐心等待 :)

我的申请

我正在开发一个执行以下操作的 Java(带有 JFrame GUI)桌面应用程序:

  1. 扫描 (.txt) 文件。
  2. 从中解析出一些数字 文件,执行一些计算 他们并最终存储结果 在字符串变量中。
  3. 以特殊格式输出这些数字 (表格)格式。 (注:格式 包括一些 Unicode(阿拉伯语) 字符。)

问题

前两部分进行得很顺利。然而,当我来到第三部分(格式化输出)时,我不知道如何显示这种特殊格式,

  • 在 Java 中显示特殊格式输出(表格)的最佳方式是什么?

备注:Formatter 不会有帮助,因为它没有适当的表支持。

解决方案一:

我做了研究,发现我可以使用 JEditorPane,因为它可以显示特殊格式,例如“html”。所以我决定创建一个具有所需(表格)格式的“html”页面,然后在 [JEditorPane][4] 上显示该页面。我这样做了并且进展顺利,直到我想将一些 html 元素的值更改为那些 (.txt) 文件中解析的数字。

  • 我怎样才能访问 html 元素(例如 <td></td> )并更改 它的值(value)?

请注意,(.html) 使用 setPage(url) 加载到 JEditorPane 中.

Unicode 字符显示正确,但我无法更改某些元素值(例如,我想将 <td> 000,000,000 </td> 的值更改为 <td> MainController.getCurrentTotalPayment() </td>

方案二:

我找到了一个解决方法,涉及使用 HTMLDocument 和 HTMLEditorKit,这样我就可以使用 HTMLEditorKit 从头开始​​创建 (.html) 并使用 kit.insertHTML 在 JEditorPane 上显示它。 .

我已经使用上述方法成功添加了内容,而且我还能够从 (.txt) 文件中添加已解析的数字,因为我将它们存储在我的 (MainController) 类中。不幸的是,Unicode 阿拉伯字符无法正确显示。

  • 如何显示这些 Unicode 字符正确吗?

所以第一个解决方案缺少对 html 元素的访问,第二个缺少 Unicode 支持!

我的同事建议我在可以访问我的 MainController.java 类的 html 文档中使用 JSP 代码。因此,将页面加载到 JEditorPane 中时,html 元素已经更改。如果没有 JSP 的帮助,难道没有办法做到这一点吗?

其他一些人推荐使用 JTidy但是在 Java 的 JDK 中没有办法做到这一点吗?

我愿意接受所有可能的解决方案。请帮忙。

我的代码:部分代码内容因不相关而被省略

主 Controller .java

class MainController 
{
    private static String currentTotalPayment;

    public static void main(String[] args) 
    {
        CheckBankFilesView cbfView = new CheckBankFilesView();
        cbfView.setVisible(true);
    }

    public static void setCurrentTotalPayment(String totalPayment) {
        MainController.currentTotalPayment = totalPayment;
    }

    public static String getCurrentTotalPayment() {
        return currentTotalPayment;
    }
}

MyFormattedOuputSolutionOne.java:

public class MyFormattedOuputSolutionOne extends javax.swing.JFrame {

    private void MyFormattedOuputSolutionOne() {

        jPanel1 = new javax.swing.JPanel();
        jScrollPane1 = new javax.swing.JScrollPane();
        myFormattedOuput = new javax.swing.JEditorPane();

        myFormattedOuput.setContentType("text/html");
        //myFormattedOuput.setContentType("text/html; charset=UTF-8"); //Doesn't seem to work

        myFormattedOuput.setEditable(false);

        jScrollPane1.setViewportView(myFormattedOuput);

        myFormattedOuput.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);

        try{
            myFormattedOuput.setPage(getClass().getResource("resources/emailFormat2.html"));

            //How can I edit/change html elements loaded in 'myFormattedOuput'?
        }catch(Exception e){
        }
    }
}

MyFormattedOuputSolutionTwo.java:

public class MyFormattedOuputSolutionTwo extends javax.swing.JFrame {

    private void MyFormattedOuputSolutionTwo() {

        jPanel1 = new javax.swing.JPanel();
        jScrollPane1 = new javax.swing.JScrollPane();
        myFormattedOuput = new javax.swing.JEditorPane();

        myFormattedOuput.setContentType("text/html");
        //myFormattedOuput.setContentType("text/html; charset=UTF-8"); //Doesn't seem to work

        myFormattedOuput.setEditable(false);

        jScrollPane1.setViewportView(myFormattedOuput);

        HTMLEditorKit kit = new HTMLEditorKit();

        HTMLDocument doc = new HTMLDocument();

        myFormattedOuput.setEditorKit(kit);

        myFormattedOuput.setDocument(doc);

        myFormattedOuput.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);

        try{
            // Tried to set the charset in <head> but it doesn't work!
            //kit.insertHTML(doc, 1, "<meta http-equiv = \"Content-Type\" content = \"text/html; charset=UTF-8\">", 0, 0, HTML.Tag.META);

            kit.insertHTML(doc, doc.getLength(), "<label> السلام عليكم ورحمة الله وبركاته ,,, </label>", 0, 0, null); //Encoding problem
            kit.insertHTML(doc, doc.getLength(), "<br/>", 0, 0, null); // works fine
            kit.insertHTML(doc, doc.getLength(), MainController.getCurrentTotalPayment(), 0, 0, null); // works fine

            //How can I solve the Unicode problem above?
        }catch(Exception e){
        }
    }
}

htmlFormatTable.html:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">

<html>

    <head>

        <meta http-equiv = "Content-Type" content = "text/html; charset=UTF-8">

    </head>

    <body>

        <label> السلام عليكم ورحمة الله وبركاته ,,, </label>
        <br/>
        <label>  الأخوة الكرام نفيدكم بتفاصيل المدفوعات لشهر  </label> XX/143X </label>  هـ كما هو موضح ادناه  </label>
        <br/>
        <table align="right"  border="1" width="600" cellpadding="5" cellspacing="0">
            <tr char="utf-8" bgcolor="cccccc" align="center">
                <td colspan="3">   <label> تفاصيل مدفوعات بنك الرياض </label>  <img src="..\images\riyadh.gif" width="65" height="15"/> </td>
            </tr>
            <tr align="center">
                <td></td>
                <td id="cell1">0,000,000.00</td>
                <td align="right"> معاشات </td>
            </tr>
            <tr align="center">
                <td></td>
                <td id="cell2">0,000,000.00</td>
                <td align="right"> أخطار </td>
            </tr>
            <tr align="center">
                <td bgcolor="cccccc"> المجموع </td>
                <td bgcolor="cccccc">   0,000,000.00 <label> ريال سعودي </label> </td>
                <td></td>
            </tr>
        </table>
        <br/>
        <label> شاكرين لكم حسن تعاونكم ...... </label>
        <br/>
        <label> فريق العمليات بقسم الحاسب الآلي </label>

    </body>

</html>

感谢您阅读我冗长的多个问题线程,等不及您的回答了。

更新:

感谢@Howard 的洞察力,如果我用相应的 unicode 替换阿拉伯字符(例如 Ø =\u0628)它工作正常但必须有一种方法可以做到这一点而不需要替换每个字符,对吗?

最佳答案

解决方案一

可以编辑加载到 JEditorPane 中的 HTML。这是基于您的 MyFormattedOuputSolutionOne.java 的完整代码:

import java.awt.ComponentOrientation;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import javax.swing.JEditorPane;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.Element;
import javax.swing.text.SimpleAttributeSet;

public class MyFormattedOuputSolutionOne extends javax.swing.JFrame {

    private MyFormattedOuputSolutionOne() {
        super("MyFormattedOuputSolutionOne");
        setDefaultCloseOperation(DISPOSE_ON_CLOSE);

        JScrollPane jScrollPane1 = new javax.swing.JScrollPane();
        final JEditorPane myFormattedOuput = new javax.swing.JEditorPane();

        getContentPane().add(jScrollPane1);

        myFormattedOuput.setContentType("text/html");
        //myFormattedOuput.setContentType("text/html; charset=UTF-8"); //Doesn't seem to work

        myFormattedOuput.setEditable(false);

        jScrollPane1.setViewportView(myFormattedOuput);

        myFormattedOuput.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);

        try{
            myFormattedOuput.setPage(getClass().getResource("htmlFormatTable.html"));
            myFormattedOuput.addPropertyChangeListener(new PropertyChangeListener() {

                @Override
                public void propertyChange(PropertyChangeEvent evt) {
                    if ("page".equals(evt.getPropertyName())) {
                        Document doc = myFormattedOuput.getDocument();
                        Element html = doc.getRootElements()[0];
                        Element body = html.getElement(1);
                        Element table = body.getElement(1);
                        try {
                            Element tr2 = table.getElement(1);
                            Element tr2td1 = tr2.getElement(0);
                            doc.insertString(tr2td1.getStartOffset(), "1: 123,456",
                                             SimpleAttributeSet.EMPTY);

                            Element tr3 = table.getElement(2);
                            Element tr3td1 = tr3.getElement(0);
                            doc.insertString(tr3td1.getStartOffset(), "2: 765.123",
                                             SimpleAttributeSet.EMPTY);
                        } catch (BadLocationException e) {
                            e.printStackTrace();
                        }
                        myFormattedOuput.removePropertyChangeListener(this);
                    }
                }

            });

            //How can I edit/change html elements loaded in 'myFormattedOuput'?

        } catch(Exception e){
            e.printStackTrace();
        }

        pack();
        setSize(700, 400);
        setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new MyFormattedOuputSolutionOne();
            }
        });
    }
}

它异步加载文档并等待加载页面。加载页面时,它会访问文档的元素以搜索元素,并将文本插入到表格第 2 行和第 3 行的第一个 <td>

顺便说一句,您的 HTML 无效!您应该清理它。当您这样做时,文档元素的索引将发生变化,您将不得不调整找到插入点的代码。

窗口看起来是这样的: Solution One window screen shot

方案二

我没有发现编码问题。字符显示正确。但是我不得不在Eclipse项目中将Java文件的编码设置为UTF-8。

Solution Two with correctly displayed Arabic

方案三

您是否考虑过使用 JTable 在 UI 中显示结果表?


HTML 可能看起来像这样:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">

<html>
    <head>
        <meta http-equiv = "Content-Type" content = "text/html; charset=UTF-8">
    </head>
    <body>
        <p> السلام عليكم ورحمة الله وبركاته ,,, </p>

        <p>  الأخوة الكرام نفيدكم بتفاصيل المدفوعات لشهر  </p>
        <p>XX/143X </p>
        <p>  هـ كما هو موضح ادناه  </p>

        <table align="right"  border="1" width="600" cellpadding="5" cellspacing="0">
            <tr bgcolor="cccccc" align="center">
                <td colspan="3">تفاصيل مدفوعات بنك الرياض <img src="..\images\riyadh.gif" width="65" height="15"/></td>
            </tr>
            <tr align="center">
                <td></td>
                <td id="cell1">0,000,000.00</td>
                <td align="right">معاشات</td>
            </tr>
            <tr align="center">
                <td></td>
                <td id="cell2">0,000,000.00</td>
                <td align="right">أخطار</td>
            </tr>
            <tr align="center">
                <td bgcolor="cccccc">المجموع</td>
                <td bgcolor="cccccc">0,000,000.00 ريال سعودي</td>
                <td></td>
            </tr>
        </table>
        <p> شاكرين لكم حسن تعاونكم ...... </p>
        <p> فريق العمليات بقسم الحاسب الآلي </p>
    </body>
</html>

因为我一个字都不懂,所以我无法提出更好的格式。首先, <label> 元素只允许在 <form> 中使用。您在表格上方有一系列三个 <label> s,其中只有一个有开始 <label> 标签,有三个结束 </label> 标签。我把它们都变成了 <p> ;但是,如果您想让它们成为表列的标题,则您应该使用包含三个 <th> 元素的表行。

使用这种 HTML 结构,HTML 树中的 <table> 元素将位于索引 4,即您应该更改行

Element table = body.getElement(1);

Element table = body.getElement(4);

索引 0–3 现在是 <p> 元素。


作为旁注,不是在将 HTML 加载到 JEditorPane 之后编辑 HTMLDocument ,它将它加载到 setPage 的文本模型中,您可以在传递到 <td> 之前编辑您的 HTML 文档,以便它已经在 JEditorPane.setPage 元素中包含正确的数据。由于 URL 方法只接受 read ,那么您的选择是 InputStream 接受 Object 和描述模型的 HTMLDocument (在您的情况下应该是 StringBufferInputStream 的实例)。 String.getBytes("UTF-8") 是此任务的最佳候选者,但已被弃用,因为它无法正确读取 UTF-8 字符。考虑到这一点,您宁愿使用 ByteArrayInputStream 函数(自 J2SE 6 起),而 JEditorPane 是您的 HTML 声明的编码,而 ojit_code 在读取时会遵守它。

关于java - 访问/更改 JEditorPane 的 html 加载元素 + Unicode (Java) 的 HTMLEditorKit 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6641457/

相关文章:

Java jScrollPane 不显示滚动条

java - Socket.io 不适用于 Android 9(API 级别 28)

java - 带有 gridview 的 recyclerview 用不同的索引号重复项目两次

java - BeanCreationException NoSuchBeanDefinitionException 使用 Spring roo

python - 从文件中去除 UTF-8 字符范围的脚本

java - 如何从 JEditorPane 获取正确的 Unicode 字符串(无 &#enties;)?

java - 应该尝试...catch 进入循环内部还是外部?

python - 写入 CSV 文件时出现 Unicode 问题

cocoa - 将 NSString 转换为 AXUIElementPostKeyboardEvent 的 keyCode+修饰符

java - 在 Swing 应用程序中显示 HTML 表单并与之交互