TL; DR:设置Graphics
实例以使用默认设置呈现字符串的最简单,最正确的方法是什么?或者如何使用默认的抗锯齿设置呈现字符串,使其看起来像JLabel?问题的更详细说明如下...
我正在尝试创建一个自定义JComponent子类。实际上,它是一种TableCellRenderer
能够显示富文本格式的文件。扩展JEditorPane
太繁琐,太慢(实际上尝试过),并且JLabel无法显示富文本,因此我决定实现自己的,轻量级的和快速的。现在,(显然)它需要在中绘制一些文本paintComponent()
,并且我希望此文本在所有其他文本组件(如JLabel)中都看起来像。
但是,当我这样做时,它似乎使用了与应用程序其余部分不同的抗锯齿设置,因此它看起来很丑陋。我意识到我可以强制Graphics
转换Graphics2D
为使用适当的API,但是问题是,要使用什么确切的设置?也就是说,setRenderingHint()
作为第二个参数传递给什么?
我可以通过使用各种AA值使它在系统上看起来不错,但是在其他具有不同默认AA设置的系统上,它不会突然变得糟糕吗?
我尝试查看JLabel和LabelUI的源代码,但它们似乎使用了很多黑魔法,例如使用来查询某些神秘属性JComponent.getClientProperty()
,SwingUtilities2
而Swing甚至都不包含这些属性。当然,我可以尝试模仿这一点,但这太麻烦了,而且b)不得不使用一些没有太多文档证明的功能,这些功能不能保证拥有稳定的API。
也许有一种方法可以重用一些现有的UI委托?基本上,我只希望我的文本看起来与所显示的完全相同JLabel
。我什至可以使用JLabel
或其子类的实例作为一种“橡皮图章”来绘制文本,但这看起来有些丑陋,而且我不确定性能。我意识到JTable
实际上确实可以做到这一点,但是使用aJLabel
绘制整个单元格是一回事,使用它绘制部分单元格感觉并不对。例如,某些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]呈现富文本,甚至您也可以JXLabel
从SwingX使用它来实现更多功能(旋转!换行!)。
考虑到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;
}
}
或者您可以JTable
在prepareRenderer()
方法中修改您的
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,而是与委托结合使用,但是我认为这是说明发生情况的好方法。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句