我有一个使用JXLayer和pbjar-Framework具有可缩放UI的Java swing项目。 JTextComponents出现问题,该问题已通过TransformUI.java中的以下方法修复:

/**
 * {@link JTextComponent} and its descendants have some caret position
 * problems when used inside a transformed {@link JXLayer}. When you plan to
 * use {@link JTextComponent}(s) inside the hierarchy of a transformed
 * {@link JXLayer}, call this method in an early stage, before instantiating
 * any {@link JTextComponent} .
 * <p>
 * It executes the following method:
 *
 * <pre>
 * System.setProperty(&quot;i18n&quot;, Boolean.TRUE.toString());
 * </pre>
 *
 * As a result, a {@link GlyphPainter} will be selected that uses floating
 * point instead of fixed point calculations.
 * </p>
 */
public static void prepareForJTextComponent() {
  System.setProperty("i18n", Boolean.TRUE.toString());
}


所有JAR均使用有效证书签名,并且jnlp看起来像

<?xml version="1.0" encoding="utf-8"?>
<jnlp spec="7.0+" codebase="https://__HOST_IP____HOST_HTTPS_PORT__/test"
  href="client/1024.jnlp">
  <information>
    <offline-allowed />
  </information>
  <security>
    <all-permissions />
  </security>
  <resources>
    <j2se version="1.8+" java-vm-args="-Xmx512M" />
    <jar href="client.jar" />
    ... more JARs
  </resources>
  <application-desc main-class="de.test.Frame">
    <argument>__HOST_IP__</argument>
  </application-desc>
</jnlp>


client.jar MANIFEST.MF包含以下内容

...
Permissions: all-permissions
Codebase: *
Trusted-Only: false
Trusted-Library: false
...


因为javaws只接受安全属性,所以我在主类中调用了

static
{
  TransformUI.prepareForJTextComponent();
}


问题是,如果我在每个浏览器中使用Java webstart,则JTextComponent的修复程序将无法正常工作。

对于Java Webstart,我测试了4种情况:


爪哇
javaws [url]
javaws [本地文件]
浏览器


使用oracle java 8u141、32或64位,Windows 7 64bit,Linux debian 7 64位,firefox进行测试
爪哇

如果我将客户端称为Java应用程序,则修复效果很好

javaws [url]

此调用在linux和Windows中均能正常运行。
但是在旧版本的jnlp文件中,我们使用扩展名来包含3rd-party JAR,在Windows中,此调用只能运行一次,直到删除缓存的文件为止

javaws [本地文件]

不起作用

浏览器

不起作用

有什么建议为什么系统属性不起作用?

最佳答案

在javax.swing.text.AbstractDocument.AbstractDocument(Content,AttributeContext)中,读取SystemProperty“ i18n”:

...
if (defaultI18NProperty == null) {
  // determine default setting for i18n support
  String o = java.security.AccessController.doPrivileged(
    new java.security.PrivilegedAction<String>() {
      public String run() {
        return System.getProperty(I18NProperty);
      }
    }
  );
  if (o != null) {
    defaultI18NProperty = Boolean.valueOf(o);
  } else {
    defaultI18NProperty = Boolean.FALSE;
  }
}
putProperty( I18NProperty, defaultI18NProperty);
....


就我而言,该属性应始终设置为“ true”,因此我使用自己的JTextField-class:

class MyTextField extends JTextField {
  MyTextField() {
    super();
    Document doc = new PlainDocument();
    doc.putProperty("i18n", Boolean.TRUE);
    this.setDocument(doc);
  }
}

08-05 01:23