簡體   English   中英

如何在Swing L&F中查詢當前的抗鋸齒設置?

[英]How to query current anti-aliasing settings in Swing L&F?

TL; DR:設置Graphics實例以使用默認設置呈現字符串的最簡單,最正確的方法是什么? 或者如何使用默認的抗鋸齒設置渲染字符串,使其看起來像JLabel? 該問題的更詳細描述如下......

我正在嘗試創建一個自定義的JComponent子類。 實際上,它是一種能夠顯示富文本的TableCellRenderer 擴展JEditorPane太沉重和緩慢(實際上嘗試過),JLabel無法顯示富文本,因此我決定實現自己的,輕量級和快速。 現在,它(顯然)需要在paintComponent()繪制一些文本,我希望這個文本看起來像所有其他文本組件,如JLabel。

但是,當我這樣做時,似乎從應用程序的其余部分使用不同的抗鋸齒設置,所以它看起來相當丑陋。 我意識到我可以將GraphicsGraphics2D以使用適當的API,但問題是,要使用哪些確切的設置? 也就是說,傳遞給setRenderingHint()作為第二個參數是什么?

通過使用各種AA值,我可以在我的系統上看起來很好看,但是在其他具有不同默認 AA設置的系統上突然看起來不是很糟糕嗎?

我試圖查看JLabel和LabelUI源代碼,但它們似乎使用了很多黑魔法,比如使用JComponent.getClientProperty()SwingUtilities2查詢一些隱藏屬性,而SwingUtilities2甚至不是官方Swing的一部分。 當然,我可以嘗試模仿它,但這是a)太繁瑣b)必然會使用一些沒有保證事件保證具有穩定API的未記錄的功能。

或者也許有一種方法可以重用一些現有的UI委托? 基本上,我只是希望我的文本看起來與JLabel完全一樣。 我甚至可以使用JLabel或其子類的實例作為繪制文本的“橡皮圖章”,但這看起來有點難看,而且我不確定性能。 我意識到JTable實際上確實如此,但是使用JLabel繪制整個單元格是一回事,使用它來繪制單元格的部分感覺不對。 例如,一些L&F可能會以一種特殊的方式裝飾這些JLabel ,這看起來很難看。

理想情況下,我想有這樣的東西(虛構的代碼):

((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING,
    JLabel.getDefaultUI().getRenderingHint());

或者更好(設置一切,而不僅僅是AA):

JLabel.getDefaultUI().setupGraphics(g); // this sets up g just like for drawing a JLabel

但就我所見,似乎沒有這么簡單的事情。

有時我們看不到森林里的樹木......

和JLabel無法顯示富文本

如果您需要在表格渲染器中使用富文本,那么(也許)這就是問題所在! 事實上, JLabel通過HTML [Doc]渲染富文本,甚至可以使用SwingX的 JXLabel實現更多功能(旋轉!換行!)。

考慮到DefaultTableRenderer實際上是一個JLabel ,你可以擴展它並做一個簡單的修改:

public class AATableRenderer extends DefaultTableCellRenderer {

    public Component getTableCellRendererComponent(JTable table, Object value,
            boolean isSelected, boolean hasFocus, int row, int column) {
        DefaultTableCellRenderer c = (DefaultTableCellRenderer) super
                .getTableCellRendererComponent(table, value, isSelected,
                        hasFocus, row, column);

        String text = c.getText();

        // Do some style transformations maybe...

        c.setText("<html>" + text + "</html>");

        return c;
    }

}

或者您可以在prepareRenderer()方法中修改JTable

public class AATable extends JTable {

    public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
        Component c = super.prepareRenderer(renderer, row, column);

        if (c instanceof JLabel) {
            JLabel l = (JLabel) c;
            String text = l.getText();

            // Do some style transformations maybe...

            l.setText("<html>" + text + "</html>");
        }

        return c;
    }

}

但也許你不能使用HTML的東西...在這種情況下,如果你必須堅持你的自定義組件,你可能必須按照外觀和感覺來做,因為每個都是按照自己的方式管理。 例如,請注意,有時此屬性是在系統中設置的,並且大多數Swing L&F都尊重它們(Windows 7在“我的電腦”>“屬性”>“高級系統配置”>“性能”>“平滑字體”(列表中的檢查)中進行配置)。

我不認為你可以重復使用LabelUI (基本的),因為當你想要平滑時,可能所有的魔法干擾你想要繪畫的方式...不確定,這不是不可能,但我不知道。

這是對原始問題的回答

簡短的回答

g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

答案很長

組件使用不同設置的原因是因為Swing使用了繪制的委托體系結構:L&F為每種類型的組件保存委托原型,當組件實例化時創建並注入委托,並在那里繪制(和行為)完成了。 當您剛剛實現paintComponent(Graphics)方法時,您正在跳過所有該架構並直接進行繪制,並且您缺少可能在委托中完成的那些設置*。 [文檔]

合適的 (“適當的”並不總是最好的解決方案!)方法來構建您的自定義組件是構建您的UI委托,注冊它並執行適當的過程。 [文檔]

無論如何這是一項冗長乏味的工作,所以讓我們切合實際:如果你的應用程序只使用一種外觀,如果你不打算重復使用這個組件,如果你的時間限制不允許你花費大量時間開發一個單個組件...如果您只需要將組件設置為消除鋸齒,請使用以下代碼段:

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import javax.swing.JComponent;

public class AAComponent extends JComponent {

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g); // Maybe you want to skip this, up to your needs...

        Graphics2D g2 = null;
        try {
            g2 = (Graphics2D) g.create();

            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

            // Your painting procedures
        } finally {
            if (g2 != null) {
                g2.dispose();
            }
        }
    }

}

也許g2的實例化看起來有點奇怪,但它是非常優化的,它是一種不在Graphics傳播變化並且計算成本低於最小值的方法。 此外,如果您想將抗鋸齒傳播到超類繪畫(在這種情況下JComponent不執行任何操作),只需在設置渲染提示后調用super實現。

*這有點不准確,因為配置不一定依賴於L&F,而是與代表的組合,但我認為這是一個很好的方式來說明發生了什么。

出於一般目的,以下屬性應在整個應用程序中設置抗鋸齒。

    System.out.println(System.getProperty("awt.useSystemAAFontSettings"));
    System.setProperty("awt.useSystemAAFontSettings","on"); 
    System.out.println(System.getProperty("awt.useSystemAAFontSettings"));
    System.setProperty("swing.aatext", "true");
    // etc.

或者,在JLabelJPanel的圖形上下文中覆蓋paintComponent()時:

        @Override
        protected void paintComponent(Graphics g) {
            Graphics2D g2 = (Graphics2D) g.create();
            try {
                // you can query the RenderingHints here
                g2.getRenderingHint(RenderingHints.KEY_ANTIALIASING);
                g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                g2.getRenderingHint(RenderingHints.KEY_ANTIALIASING);
            } finally {
                if(g2 != null) {
                    g2.dispose();
                }
            }
        }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM