我维护了一个旧的Swing应用程序,它使用自定义的border实现作为窗口装饰,并使用扩展MetalLookAndFeel的look and feel实现。look and feel覆盖initComponentDefaults(UIDefaults table)并将自定义边框安装为"RootPane.frameBorder",依此类推。
自定义边框本身通过实现paintBorder(Component c, Graphics g, int x, int y, int width, int height)将32行预定义颜色水平绘制在一起。当Settings > Display > Scale and layout中的display scaling设置为100%时,这在Windows102004或更高版本上运行良好。当display scaling设置为125%或更大时,边框将不会正确绘制,它会在应该一起绘制的线条之间显示白色线条。
Advanced scaling settings中的Fix scaling for apps似乎不会影响边框绘制。
我使用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);
}
}
}发布于 2021-02-22 19:10:39
我发现,当使用具有一个像素宽度或高度的Graphics::drawLine或Graphics::fillRect时,Swing只在屏幕上绘制一个未缩放的像素宽度的线条,独立于窗口的显示缩放。
当我用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);
}
}https://stackoverflow.com/questions/66261145
复制相似问题