HiDPI支持java 9,使用Windows L&F的JTable网格线的scalling问题 – 但不是Nimbus

我正在将我的Swing应用程序迁移到Java 11以利用hidpi显示支持.我正在使用三星显示器,分辨率设置为3840×2160,缩放率为125%,使用Windows 10.

虽然java 9及以上版本被宣传为正确处理hidpi缩放,但在显示简单的JTable时,网格线显示不同的厚度,如下所示:

JTable gridlines issue

这是以下代码

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时,问题就会消失:

JTable Nimbus

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);
    }
}

如何使用认的Windows L& F实现相同的功能

(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克隆.

然后,这样就可以调用drawLine(),看起来效果好于125%.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


应用场景 C端用户提交工单、工单创建完成之后、会发布一条工单创建完成的消息事件(异步消息)、MQ消费者收到消息之后、会通知各处理器处理该消息、各处理器处理完后都会发布一条将该工单写入搜索引擎的消息、最终该工单出现在搜索引擎、被工单处理人检索和处理。 事故异常体现 1、异常体现 从工单的流转记录发现、
线程类,设置有一个公共资源 package cn.org.chris.concurrent; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * @Descrip
Java中的数字(带有0前缀和字符串)
在Java 9中使用JLink的目的是什么?
Java Stream API Filter(过滤器)
在Java中找到正数和负数数组元素的数量
Java 9中JShell中的不同启动脚本是什么?
使用Java的位填充错误检测技术
java中string是什么
如何使用Java中的JSON-lib API将Map转换为JSON对象?
Java菜单驱动程序以检查数字类型
使用Junit的Maven项目 - 检查银行账号
JAVA编程基础
在Java中使用throw、catch和instanceof来处理异常
在Java中,将数组分割为基于给定查询的子数组后,找到子数组的最大子数组和
如何在Java中从给定的字符串中删除HTML标签?
在PHP中,IntlChar getBlockCode()函数的翻译如下:
如何在Android中实现按下返回键再次退出的功能?
如何使用Java中的流式API解析JSON字符串?
Java中的模式类