首页 > 解决方案 > Java JEditorPane 内联表未按预期工作

问题描述

JEditorPane用来在我的“游戏构建器”中进行代码更正,这有助于为我的另一个游戏创建地图。
(然后内部使用HTMLEditorKit.inline CSS 并<div>用于格式化)
我希望获得像 IDE 一样的视觉效果:
[预期]我的 StackOverflow 排名太低,无法在此处发布图像
然而,实际效果是:[实际]

下面是我的代码:(

其中strl[i]是第i个子字符串,它在语法上是正确的。如果存在多个与部分输入的字符串匹配的可能函数,则在strl[i],它们都将存储在同一个字符串中,由$$)分隔

...(some code related to IDE functionalities)...
String txt = "";
for(int i = 0; i < strl.length; i++){
    String[] list; boolean cont = strl[i].contains("$$");
        if(cont) {
            list = strl[i].split("\\$\\$");
            txt += "<table style=\"display:inline;vertical-align:top;\"><tr><td>";
        }
    else list = new String[]{strl[i]};
    for(String elem : list){
        switch(elem.charAt(0)){//assigning colours by the first character in the string
            //error colour (red - orange)
            case 'e': txt += "<span style=\"color:red;background-color:yellow;font-weight:bold;\">"; break;
            //syntax component (green)
            case 'g': txt += "<span style=\"color:green;font-weight:bold;\">"; break;
            //recognized function (blue)
            case 'b': txt += "<span style=\"color:blue;font-weight:bold;\">"; break;
            //recognized function (cyan)
            case 'c': txt += "<span style=\"color:cyan;font-weight:bold;\">"; break;
        }
        txt += elem.substring(elem.indexOf("|")+1);//you may interpret this as "getting the value of substring"
        switch(elem.charAt(0)){
            case 'e': case 'g': case 'b': case 'c':
            txt += "</span>";
        }
        if(cont) txt += "<br>";
    }
    if(cont) txt += "</td></tr></table>";
}
if(tip.equals("<br><b>In this code:</b>")) tip += "<br>There is no syntax error.";
msg += txt + tip;
cmdaid.setText(msg); //cmdaid is the JEditorPane in question.
cmdaid.select(0,0);

对于输入if:{hav,生成的 html 字符串为:

<table style="display:inline;vertical-align:top;"><tr><td>
    <span style="color:blue;font-weight:bold;">have</span><br><span style="color:blue;font-weight:bold;">haved</span><br>
</td></tr></table>
<span style="color:red;background-color:yellow;font-weight:bold;">}</span><br>
<b>In this code:</b><br>The "if"-"then"-"else" structure should be in the form of: "if:{...}then:{...}else:{...}"

在 W3School 的 Tryit 编辑器中正确显示:https
://www.w3schools.com/code/tryit.asp?filename=GSTCQD0WF5WK 这表明我的代码在 HTML/CSS 中应该没问题,但它不能作为预期在JEditorPane设置中:

JEditorPane cmdaid = new JEditorPane();
cmdaid.setEditable(false);
cmdaid.setOpaque(false);
cmdaid.setFont(new Font("Times New Roman", 0, 16));
cmdaid.setEditorKit(new HTMLEditorKit());
cmdaid.setPreferredSize(new Dimension(200, 100));
JScrollPane cmdp = new JScrollPane(cmdaid, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);

由于其他格式完全没问题,我希望 JEditorPane 设置没有问题。然而,内联表无法按预期工作。

我的问题是,有什么办法可以解决这个问题,还是 JEditorPane 的内在问题?

虽然我认为当问题得到回答时,我可能已经在开发另一个游戏了 :|

不过,提前感谢您的详细解释。

标签: javahtmlcssswingjeditorpane

解决方案


根据oracle文档和问题帖子中的评论,Java支持的HTMLEditorKit仅支持HTML 3.2,这是一个相当原始的版本。不支持某些高级 CSS。

在阅读了问题帖子中的评论后,我进行了以下修改:

txt = ""; ArrayList<String> txts = new ArrayList<String>(); int l = 0;
for(int i = 0; i < strl.length; i++){
    String[] list; boolean cont = strl[i].contains("$$"); char ch = strl[i].charAt(0);
    list = new String[]{strl[i].substring(strl[i].indexOf("|")+1)};
    if(cont) list = list[0].split("\\$\\$");

    switch(ch){
        //error colour (red - orange)
        case 'e': txt += "<span style=\"color:red;background-color:yellow;font-weight:bold;\">"; break;
        //syntax component (green)
        case 'g': txt += "<span style=\"color:green;font-weight:bold;\">"; break;
        //recognized function (blue)
        case 'b': txt += "<span style=\"color:blue;font-weight:bold;\">"; break;
        //recognized function (cyan)
        case 'c': txt += "<span style=\"color:cyan;font-weight:bold;\">"; break;
    }

    int maxl = -1;
    for(String elem : list) if(elem.length() > maxl) maxl = elem.length();
    txt += pad(list[0], maxl); l += maxl;

    for(int I = 1; I < list.length; I++){
        if(I <= txts.size()) txts.set(I-1, txts.get(I-1)+fpad(pad(list[I], maxl), l-txts.get(I-1).length()));
        else txts.add(I-1, fpad(pad(list[I], maxl), l));
    }
    switch(ch){
    case 'e': case 'g': case 'b': case 'c':
        txt += "</span>";
    }
}

if(tip.equals("<br><b>In this code:</b>")) tip += "<br>There is no syntax error.";
msg += txt + "<span style=\"color:blue;font-weight:bold;\">";
for(String subt : txts) msg += "<br>" + toHTML(subt);
msg += "</span>" + tip;

cmdaid.setText("<div style=\"font-family:monospace;\">"+msg+"</div>");
cmdaid.select(0,0);

和:

String fpad(String in, int l){return String.format("%1$" + l + "s", in);}
//does front padding from string in to string with length l

String pad(String in, int l){return String.format("%1$-" + l + "s", in);}
//does right padding from string in to string with length l

String toHTML(String in){return in.replace(" ", "&nbsp;");}
//transform string to HTML form, as HTML eats multiple adjacent whitespaces

我添加了另一个数组来存储额外的字符串建议,问题得到解决(参见[NOW])。我曾经monospacing确保字符之间有规律的间距,虽然FontRenderingContext可以使用更复杂的,但我更愿意在我的应用程序中为这个(也许是次要的)组件保持简单。

[结案]


推荐阅读