0

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

自定义边框本身通过实现将 32 行预定义颜色水平绘制在一起paintBorder(Component c, Graphics g, int x, int y, int width, int height)。当display scalingSettings > Display > Scale and layout. 当display scaling设置为 125% 或更高时,将无法正确绘制边框,它在应该一起绘制的线条之间有白线。

Fix scaling for appsinAdvanced 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,
                        CustomWindowBorder.BORDER_THICKNESS);
   }

   @Override
   public boolean isBorderOpaque(){

      return true;
   }

   @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.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,
                    i,
                    height - i - 1);
         // right
         g.drawLine(width - i - 1,
                    yStart,
                    width - i - 1,
                    height - i - 1);
         // below
         g.drawLine(i,
                    height - i - 1,
                    width - i - 1,
                    height - i - 1);
      }
   }
}
4

1 回答 1

0

我发现 Swing 在使用Graphics::drawLineGraphics::fillRect使用一个像素宽度或高度时,会在屏幕上准确地绘制一条未缩放的像素宽线,与 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,
                 yStart,
                 borderColors.length - i,
                 height - yStart - i);
      // below
      g.fillRect(i,
                 height - i - 1,
                 width - i,
                 borderColors.length - i);
   }
}
于 2021-02-22T11:10:38.880 回答