Доступ / изменение загруженных html-элементов JEditorPane + проблема HTMLEditorKit с Unicode (Java) - PullRequest
4 голосов
/ 10 июля 2011

это будет длинный вопрос, так что терпите меня:)

Мое приложение

Я занимаюсь разработкой настольного приложения на Java (с графическим интерфейсом JFrame), которое выполняет следующие действия:

  1. Сканирование (.txt) файлов.
  2. Анализирует некоторые числа из этих файлов, выполняет некоторые вычисления над ними и, наконец, сохраняет результаты в строковых переменных.
  3. Выводит эти числав специальном (табличном) формате.(Примечание: формат содержит некоторые символы Юникода (арабский).)

Задача

Первые две части прошли гладко.Однако когда я подошел к 3-й части (форматированный вывод), я не знал, как отобразить этот специальный формат, поэтому

  • Как лучше всего отобразить специальныйформатированный вывод (таблица) в Java?

Примечание: Formatter не поможет, потому что не имеет надлежащей поддержки таблиц.

Решение первое:

Я провел исследование и обнаружил, что могу использовать JEditorPane, поскольку он может отображать специальные форматы, такие как "html".Поэтому я решил создать страницу «html» в нужном (табличном) формате и затем отобразить эту страницу на [JEditorPane] [4].Я сделал это, и все шло гладко, пока я не захотел изменить значения некоторых элементов html на проанализированные номера из этих (.txt) файлов.

  • Как получить доступк элементу html (например, <td></td>) и измените его значение?

Обратите внимание, что (.html) загружается внутри JEditorPane с использованием setPage(url).

Символы Юникода отображаются правильно, но я не могу изменить некоторые значения элементов (например, я хочу изменить значение <td> 000,000,000 </td> на <td> MainController.getCurrentTotalPayment() </td>

Решение второе:

Я нашел обходной путь к этому, который включает использование HTMLDocument и HTMLEditorKit. Таким образом, я могу создать (.html) с помощью HTMLEditorKit с нуля и отобразить его на JEditorPane, используя kit.insertHTML.

, который я успешно добавилсодержимое с использованием вышеуказанного метода, и я также смог добавить проанализированные числа из файлов (.txt), потому что они хранятся в моем классе (MainController). К сожалению, арабские символы Unicode не отображались должным образом.

  • Как правильно отобразить эти символы Юникода?

Таким образом, в первом решении отсутствуетдоступ к html-элементам, а во втором отсутствует поддержка Unicode!

Мои коллеги посоветовали мне использовать код JSP в html-документе, который может иметь доступ к моему классу MainController.java.Поэтому загрузка страницы в JEditorPane с элементами html уже изменилась.Разве нет способа сделать это без помощи JSP?

Некоторые другие люди рекомендовали использовать JTidy , но нет ли способа сделать это в JDK Java?

Я открыт для всех возможных решений.Пожалуйста, помогите.

Мой код: Некоторое содержимое кода было опущено, поскольку оно не имеет отношения

MainController.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 за это понимание, если я заменяю арабский символ на соответствующий ему юникод (например, ب = \ u0628), он работает нормально, но должен быть способсделать это без необходимости замены каждого символа, верно?

1 Ответ

3 голосов
/ 12 августа 2011

Solution One

Можно редактировать HTML, загруженный в JEditorPane.Вот полный код, основанный на вашем 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();
            }
        });
    }
}

. Он загружает документ асинхронно и ожидает загрузки page .Когда страница загружена, она обращается к элементам документа для поиска элементов и вставляет текст в первый <td> во 2-й и 3-й строке таблицы.

Кстати, ваш HTML-код недействителен! Вы должны очистить его.Когда вы это сделаете, индексы элементов документа изменятся, и вам придется настроить код, который находит точки вставки.

Окно выглядит следующим образом: Solution One window screen shot

Решение второе

Я не нашел проблем с кодировкой.Символы отображаются правильно.Тем не менее мне пришлось установить кодировку файлов Java в UTF-8 в проекте Eclipse.

Solution Two with correctly displayed Arabic

Решение Три

Есть ли у васРассматривается ли использование JTable для отображения таблицы результатов в пользовательском интерфейсе?


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> над таблицей, где только у одного из них был открывающий тег <label>, было три закрывающих тега </label>.Я сделал их всех в <p>;однако, если вы предполагаете, что они являются заголовками для столбцов таблицы, вы должны были использовать строку таблицы с тремя <th> элементами.

С этой структурой HTML элемент <table> вHTML-дерево будет с индексом 4, то есть вы должны изменить строку

Element table = body.getElement(1);

на

Element table = body.getElement(4);

Индексы 0–3 теперь <p> элементов.


В качестве примечания, вместо редактирования HTML после загрузки его в JEditorPane, который загружает его в текстовую модель HTMLDocument, вы можете отредактировать ваш HTML-документ перед передачей в setPage, чтобы он уже содержалправильные данные в <td> элементах.Так как метод JEditorPane.setPage принимает только URL, тогда ваш выбор будет read, который принимает InputStream и Object, который описывает модель (в вашем случае это должен быть экземпляр HTMLDocument).StringBufferInputStream - лучший кандидат для этой задачи, но она устарела, поскольку не может правильно читать символы UTF-8.Имея это в виду, вы бы предпочли использовать String.getBytes("UTF-8") function (начиная с J2SE 6) и ByteArrayInputStream, ваш HTML-код объявляет кодировку и JEditorPane уважал бы это при чтении.

...