合金外观和反锯齿技术

4
有人在使用合金外观吗?我遇到了一个关于抗锯齿和JTextComponents的奇怪问题。默认情况下,合金不使用任何抗锯齿技术,因此我必须通过创建自己的UI类来强制执行它。这在大多数情况下都很好用,但有些字符会对抗锯齿产生破坏。
例如,如果将Alloy设置为外观,并在JTextComponent中插入一些希伯来文本,例如:שלום,מה שלומך שמי הוא האקזיד',整个JTextComponent突然永久失去了抗锯齿。
奇怪的是,我甚至没有扩展AlloyTextPaneUI,而是扩展了BasicTextPaneUI来进行抗锯齿处理,所以我很困惑Alloy从何处涉及(其他外观似乎都能正常工作)。
我很难追踪这个错误......有人遇到过相同的问题吗?
以下是一个简短的示例,演示了这个问题:
import com.incors.plaf.alloy.AlloyLookAndFeel;
import com.incors.plaf.alloy.themes.glass.GlassTheme;

import javax.swing.*;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicTextPaneUI;
import javax.swing.text.BadLocationException;
import javax.swing.text.StyledDocument;
import java.awt.*;

public class Scrap {

    static {
        // NOTE: You need a license code for Alloy!
        AlloyLookAndFeel.setProperty("alloy.licenseCode", "your license here");

        UIManager.put("TextPaneUI", MyTextPaneUI.class.getName());

        try {
            UIManager.setLookAndFeel(new AlloyLookAndFeel(new GlassTheme()));
        } catch (UnsupportedLookAndFeelException e) {
            e.printStackTrace();
        }

        // With system Look and Feel everything works just fine...
//      try {
//          UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
//      } catch (ClassNotFoundException e) {
//          e.printStackTrace();
//      } catch (InstantiationException e) {
//          e.printStackTrace();
//      } catch (IllegalAccessException e) {
//          e.printStackTrace();
//      } catch (UnsupportedLookAndFeelException e) {
//          e.printStackTrace();
//      }
    }

    public static void main(final String args[]) {
        JTextPane text = new JTextPane();

        text.setFont(new Font("Monospaced", Font.PLAIN, 14));

        StyledDocument doc = text.getStyledDocument();

        try {

            doc.insertString(doc.getLength(), "Here's some regular text. Nice and smooth with anti-aliasing.\n\n", null);

            doc.insertString(doc.getLength(), "Here's some more text Blaa Blaa Blaaa. Lorem ipsum... now try to uncomment the Hebrew text.\n\n", null);

            // Try to uncomment this line and the anti-aliasing breaks for the whole JTextPane
//          doc.insertString(doc.getLength(), "שלום, מה שלומך שמי הוא האקזידן\n\n", null);

            // Here's another strange glyph that breaks the anti-aliasing
//          doc.insertString(doc.getLength(), "ಠ", null);

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

        JFrame frame = new JFrame();

        JScrollPane scroll = new JScrollPane();
        scroll.setViewportView(text);
        scroll.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);

        frame.add(scroll, BorderLayout.CENTER);
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setSize(600, 300);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static class MyTextPaneUI extends BasicTextPaneUI {

        @Override
        protected void paintSafely(Graphics g) {
            Graphics2D g2 = (Graphics2D) g;
            g2.setRenderingHint(
                            RenderingHints.KEY_TEXT_ANTIALIASING,
                            RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);
            super.paintSafely(g);
        }

        public static ComponentUI createUI(JComponent c) {
            return new MyTextPaneUI();
        }
    }
}

我不知道出了什么问题,但请提供一些文本的屏幕截图,包括修改前和修改后的。同时,一个SSCCE也不会有害。额外信息,有些文本最好不要进行反锯齿处理...否则可能会出现模糊。请阅读使用渲染提示显示抗锯齿文本 - David Kroukamp
我添加了一个简短的例子来演示问题,您可以自己看到抗锯齿如何被破坏。在这种情况下,没有抗锯齿的文本肯定不是首选,它会使文本看起来非常糟糕(特别是使用我的应用程序中的字体Consolas时)。 - n00bster
2个回答

3
经过一些令人沮丧的尝试,我修复了它... 我仍然不确定到底是什么原因导致的,但以下是我的修复方法。显然,在Alloy的UIDefaults中缺少/损坏了一个关键字(我不知道是哪个)。因此,我将所有默认值从初始外观添加到Alloy属性中。这是一种快速而简单的解决方案(唯一的问题是菜单变得不透明),但对我来说足够好了。也许其他人也会发现它有帮助。
AlloyLookAndFeel laf = new AlloyLookAndFeel(theme) {
    @Override
    public UIDefaults getDefaults() {
        UIDefaults defs = new UIDefaults();

        defs.putAll(UIManager.getLookAndFeelDefaults());

        initClassDefaults(defs);
        initSystemColorDefaults(defs);
        initComponentDefaults(defs);

        defs.put("Menu.opaque", true);

        return defs;
    }
};

0

我有同样的问题很长一段时间了。建议将“Menu.opaque”属性设置为true确实有助于使文本抗锯齿(奇怪),但它会破坏我的菜单外观,所以我不得不放弃。

这里真正的问题是Alloy L&F的支持不好,但它看起来很好,从我的经验来看性能也非常好。在反编译混淆代码(Alloy Look&Feel v1.4.4)后,我追踪到了一个方法:

public class AlloyLookAndFeel extends BasicLookAndFeel{
    ...
    private static boolean j = false;
    ...
    public static boolean isTextAntialiasingEnabled()  {
        return j;
    }
    ...
}

我找不到一种编程方式来改变值,也无法覆盖静态方法。所以我不得不采用一些黑客技巧:

  1. 使用JD(请参见http://jd.benow.ca/)反编译代码。代码是混淆的,因此变量和方法名称没有太多意义。
  2. 将com.incors.plaf.alloy.AlloyLookAndFeel的代码复制到依赖于合金LAF的项目中(包名称必须相同)
  3. 更正j的值

    private static boolean j = true;

  4. 在反编译后,存在一个小问题,即无法访问布尔f.b变量,因此将所有出现的f.b替换为fbValue,并向类添加声明(调试器将帮助您找到当前值,在我的情况下为false)。

    private static boolean fbVariable = false;

编译项目后,您应该具有文本抗锯齿功能。 这是一种黑客技巧,但这就是您要做的,以保存一个好但支持不佳的库。我希望有人有更简单的解决方案。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接