当系统比例为 1.25 或不是 100% 时,Java Swing 图形不是像素完美的

Java Swing Graphics are not pixel perfect when system scale is 1.25 or not 100%

提问人:Fraŋkini 提问时间:11/5/2023 最后编辑:Fraŋkini 更新时间:11/5/2023 访问量:37

问:

在 100% 屏幕缩放时,绘制的形状始终是像素完美的。

enter image description here

在 125% 的屏幕缩放绘制的形状时,在这种情况下,有时会绘制得好像顶部有一行额外的像素 (1),而不是应该绘制的方式 (2)

enter image description here

我观察到这取决于组件位置,也许我想它会在 2 个像素之间绘制形状,因此它“随机”选择上面的像素作为组件或下面的像素作为另一个组件......

package debug;

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import javax.swing.border.EmptyBorder;

public class TestBugScaling implements Runnable {
    
    private final int size = 38;
    
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new TestBugScaling());
    }
    
    @Override
    public void run() {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.setPreferredSize(new Dimension(400, 400));
        
        Container contentPane = frame.getContentPane();
        contentPane.setLayout(new BorderLayout());
        contentPane.setPreferredSize(new Dimension(400, 400));
        
        JScrollPane scrollPane = new JScrollPane();
        scrollPane.setPreferredSize(new Dimension(size + 10, 400));
        scrollPane.getVerticalScrollBar().setUnitIncrement(size + 5);
        scrollPane.getVerticalScrollBar().setBlockIncrement((size + 5) * 2);
        
        JPanel container = new JPanel();
        container.setBorder(new EmptyBorder(5, 5, 5, 5));
        container.setLayout(new GridLayout(20, 0, 0, 5));
        container.setPreferredSize(new Dimension(size + 10, (size + 5) * 20));
        
        container.add(new CirclePanel());
        container.add(new CirclePanel());
        container.add(new CirclePanel());
        container.add(new CirclePanel());
        container.add(new CirclePanel());
        container.add(new CirclePanel());
        container.add(new CirclePanel());
        container.add(new CirclePanel());
        container.add(new CirclePanel());
        container.add(new CirclePanel());
        container.add(new CirclePanel());
        container.add(new CirclePanel());
        container.add(new CirclePanel());
        container.add(new CirclePanel());
        container.add(new CirclePanel());
        container.add(new CirclePanel());
        container.add(new CirclePanel());
        container.add(new CirclePanel());
        container.add(new CirclePanel());
        container.add(new CirclePanel());
        
        scrollPane.setViewportView(container);
        
        contentPane.add(scrollPane, BorderLayout.NORTH);
        
        frame.pack();
        frame.setVisible(true);
    }

    public class CirclePanel extends JPanel {

        public CirclePanel() {
            super();
            setPreferredSize(new Dimension(size, size));
            setMinimumSize(new Dimension(size, size));
            setMaximumSize(new Dimension(size, size));
        }

        @Override
        public void paintComponent(Graphics g) {
            Graphics2D g2 = (Graphics2D) g.create();
            g2.fillOval(0, 0, getHeight(), getHeight());
            g2.dispose();
        }

    }

}

使用此代码,如果您有 100% 的屏幕比例,您将看到圆圈的平滑滚动。 取而代之的是,在 125% 的屏幕比例下,如果您仔细观察,您会看到圆圈在滚动时上下摆动 1 个像素......

有没有办法防止/解决这个问题?是什么原因造成的?

Java Swing 缩放 图形2D 屏幕分辨率

评论

3赞 user85421 11/5/2023
如果比例为 1.25,则它不能是像素完美的(数学/物理) 您是否尝试过设置抗锯齿?这个网站上一定有一些帖子来解释如何
2赞 Gilbert Le Blanc 11/5/2023
Stack Overflow 问题的答案告诉您如何禁用 DPI 感知 Java Swing 代码。

答: 暂无答案