[英]How to query current anti-aliasing settings in Swing L&F?
TL; DR:設置Graphics
實例以使用默認設置呈現字符串的最簡單,最正確的方法是什么? 或者如何使用默認的抗鋸齒設置渲染字符串,使其看起來像JLabel? 該問題的更詳細描述如下......
我正在嘗試創建一個自定義的JComponent子類。 實際上,它是一種能夠顯示富文本的TableCellRenderer
。 擴展JEditorPane
太沉重和緩慢(實際上嘗試過),JLabel無法顯示富文本,因此我決定實現自己的,輕量級和快速。 現在,它(顯然)需要在paintComponent()
繪制一些文本,我希望這個文本看起來像所有其他文本組件,如JLabel。
但是,當我這樣做時,似乎從應用程序的其余部分使用不同的抗鋸齒設置,所以它看起來相當丑陋。 我意識到我可以將Graphics
為Graphics2D
以使用適當的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.
或者,在JLabel
或JPanel
的圖形上下文中覆蓋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.