Swing HiDPI 边框渲染Windows 10/OpenJRE 11

如何解决Swing HiDPI 边框渲染Windows 10/OpenJRE 11

我维护了一个旧的 Swing 应用程序,该应用程序使用自定义 border 实现作为带有扩展 MetalLookAndFeellook and feel 实现的窗口装饰。 look and feel 覆盖 initComponentDefaults(UIDefaults table) 并将自定义边框安装为 "RootPane.frameBorder" 等。

自定义边框本身通过实现 paintBorder(Component c,Graphics g,int x,int y,int width,int height) 将 32 行预定义颜色水平绘制在一起。当 display scalingSettings > display > Scale and layout 中设置为 100% 时,这适用于 Windows 10 2004 或更新版本。当 display scaling 设置为 125% 或更高时,边框将无法正确绘制,在应绘制在一起的线条之间出现白线。

Fix scaling for apps 中的

Advanced scaling settings 似乎不影响边框绘制。

我使用 AdoptOpenJDK OpenJDK 11.0.4+11 x64。我希望 Swing 也能放大线条,比如字体等。

为什么会这样?如何解决这个问题?

边框实现:

public class CustomWindowBorder implements Border{

   public static final int BORDER_THICKnesS = 3;
   
   private static final CustomWindowBorder globalInstance = new CustomWindowBorder();

   public static CustomWindowBorder getInstance(){

      return CustomWindowBorder.globalInstance;
   }

   private CustomWindowBorder(){}
   
   @Override
   public Insets getBorderInsets(Component c){

      return new Insets(1,CustomWindowBorder.BORDER_THICKnesS,CustomWindowBorder.BORDER_THICKnesS);
   }

   @Override
   public boolean isBorderOpaque(){

      return true;
   }

   @Override
   public void paintBorder(Component c,int height){

      Color[] decorationColors = [ommited]; // 30 colors in total
      Color[] borderColors = [ommited]; // 3 colors in total

      int yStart = 30;

      for(int i = 0; i < decorationColors.length; i++ ){
         // top
         Color clr = decorationColors[i];
         g.setColor(clr);

         g.drawLine(0,i,width,i);
      }

      for(int i = 0; i < borderColors.length; i++ ){
         Color clr = borderColors[i];
         g.setColor(clr);

         // left
         g.drawLine(i,yStart,height - i - 1);
         // right
         g.drawLine(width - i - 1,width - i - 1,height - i - 1);
         // below
         g.drawLine(i,height - i - 1,height - i - 1);
      }
   }
}

解决方法

我发现当使用具有一个像素宽度或高度的 Graphics::drawLineGraphics::fillRect 时,Swing 会在屏幕上精确绘制一条未缩放的像素宽线,与 Windows 的显示缩放无关。

当我用 Graphics::fillRect 绘制边框并让它填充顶部的每 30 条水平线和其他边的 3 条线时,空白将完全填充。

我的解决方案是在 Graphics::fillRect 上绘制每条线并用颜色填充整个剩余的线,在将填充矩形移动到下一行的同时减小填充矩形的宽度/高度。这不是最有效的绘制方式,但它对我有用。

修改后的paintBorder方法:

@Override
public void paintBorder(Component c,Graphics g,int x,int y,int width,int height){

   Color[] decorationColors = [ommited]; // 30 colors in total
   Color[] borderColors = [ommited]; // 3 colors in total

   int yStart = 30;

   for(int i = 0; i < decorationColors.length; i++ ){
      // top
      Color clr = decorationColors[i];
      g.setColor(clr);

      g.fillRect(0,i,width,decorationColors.length - i);
   }

   for(int i = 0; i < borderColors.length; i++ ){
      Color clr = borderColors ;
      g.setColor(clr);

      // left
      g.fillRect(i,yStart,borderColors.length - i,height - yStart - i);

   }
   for(int i = borderColors.length - 1; i >= 0; i-- ){
      Color clr = borderColors[i];
      g.setColor(clr);

      // right
      g.fillRect(width - i - 1,height - yStart - i);
      // below
      g.fillRect(i,height - i - 1,width - i,borderColors.length - i);
   }
}

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

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?