我正在将我的Swing应用程序迁移到Java 11以利用hidpi显示支持.我正在使用三星显示器,分辨率设置为3840×2160,缩放率为125%,使用Windows 10.
虽然java 9及以上版本被宣传为正确处理hidpi缩放,但在显示简单的JTable时,网格线显示不同的厚度,如下所示:
这是以下代码:
import javax.swing.*;
public class TestTable {
public static void main(String[] args) {
new TestTable();
}
public TestTable() {
JTable table = new JTable(12,6);
jdialog dialog = new jdialog();
JScrollPane sp = new JScrollPane(table);
table.setShowGrid(true);
table.setRowHeight(25);
dialog.setContentPane(sp);
dialog.setSize(300,300);
dialog.setVisible(true);
dialog.setLocationRelativeto(null);
}
}
但是,在设置Nimbus L& F时,问题就会消失:
import javax.swing.*;
public class TestTable {
public static void main(String[] args) {
try {
for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (Exception e) { }
new TestTable();
}
public TestTable() {
JTable table = new JTable(12,300);
dialog.setVisible(true);
dialog.setLocationRelativeto(null);
}
}
(java 9& 10中观察到相同的行为)
默认外观MetalLookAndFeel(和WindowsLookAndFeel)基于BasicLookAndFeel,它使用BasicTableuI类来呈现JTable.在BasicTableUI.paintGrid()它调用如SwingUtilities2.drawHLine() – 实际上调用Graphics.fillRect()这是问题.
Nimbus外观使用SynthTableuI类.在SynthTableUI.paintGrid()它最终调用Graphics.drawLine(),它在缩放时清晰地绘制了一条更清晰的线.
正如你所说,这听起来像主要的外观和感觉在hidpi下的感觉.
使用正在使用的图形的自定义版本,如果宽度或高度为1,则可以覆盖fillRect()以使用drawLine().在绘制表时,可以专门引入此自定义图形:
JTable table = new JTable(12,6) {
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(new GraphicsWorkaround(g));
}
};
(匿名子类仅用于简洁).
然后将GraphicsWorkaround类编写为传入的真实g的包装.在这里子类化DebugGraphics只是一个技巧,可以节省在Graphics中的所有其他方法中编写委托调用:
import java.awt.Graphics;
import javax.swing.DebugGraphics;
public class GraphicsWorkaround extends DebugGraphics {
private final Graphics g;
public GraphicsWorkaround(Graphics g) {
super(g);
this.g = g;
}
@Override
public Graphics create() {
return new GraphicsWorkaround(g.create());
}
@Override
public void fillRect(int x,int y,int width,int height) {
if (width == 1)
g.drawLine(x,y,x,y + height - 1);
else if (height == 1)
g.drawLine(x,x + width - 1,y);
else
super.fillRect(x,width,height);
}
}
(create()方法用于处理在JComponent.paintComponent()中创建的内部scratchGraphics克隆.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。