在 100% 屏幕缩放下,绘制的形状始终是“像素完美”。
在 125% 屏幕缩放下,在这种情况下,相同的形状有时会被绘制为顶部有一行额外的像素 (1),而不是应有的绘制方式 (2)。这些形状绘制在滚动窗格的列表中,当上下滚动时,它们会闪烁,从一个版本变为另一个版本,非常明显且分散注意力。
我观察到这取决于组件位置,也许我认为它会在 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 个像素...
有办法防止/解决这个问题吗?是什么造成的?
我不介意形状不完全完美,但我确实介意它闪烁并且始终不一致......
我找到了问题...更重要的是我找到了解决方案!
Graphics 和 Graphics2D 对象需要一些边距才能正确绘制弯曲形状,事后看来这实际上很有意义......
只需将
g2.fillOval(0, 0, getHeight(), getHeight());
替换为 g2.fillOval(1, 1, getHeight() - 2, getHeight() - 2);
,在形状周围留出 1 个单位的间距,就可以为其提供足够的空间来处理抗锯齿,并自动修复我遇到的故障...