drawRect()在某些颜色上无法正常工作

Luk*_*ter 5 java swing graphics2d

我总是用这样的轮廓创建矩形(using Graphics(2D)):

g.setColor(aColor);
g.fillRect(x, y, width, height);
g.setColor(anotherColor);
g.drawRect(x, y, width, height);
Run Code Online (Sandbox Code Playgroud)

这样可以正常工作,除了一些颜色Color.BLUE.有些线条的厚度不同:

在此输入图像描述

第一眼看上去可能很难看,但如果仔细观察,你会发现左边的线太粗而右边太细.这种情况也会发生在其他颜色上,但不是那么明显:(我仍然不确定这是否会发生青色,无法准确判断)

在此输入图像描述

我无法理解这一点,因为黑线只是被绘制在内部蓝色矩形上,内部矩形不会对它产生影响.(没有fillRect()线条甚至厚度)

我在下面提供了一个示例,可能会帮助您更好地了解差异.我的问题:为什么会出现某些RGB颜色,我该如何解决?

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.HashMap;

import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JToggleButton;
import javax.swing.WindowConstants;

public class LineExample {

    Color colors[] = new Color[] { Color.BLACK, Color.BLUE, Color.CYAN, Color.DARK_GRAY, Color.GRAY, Color.GREEN,
            Color.LIGHT_GRAY, Color.MAGENTA, Color.ORANGE, Color.PINK, Color.RED, Color.WHITE, Color.YELLOW };
    String colorNames[] = new String[] { "Black", "Blue", "Cyan", "Dark Gray", "Gray", "Green", "Light Gray", "Magenta",
            "Orange", "Pink", "Red", "White", "Yellow" };
    HashMap<String, Color> hashMap = new HashMap<String, Color>();
    Color currentColor = colors[2];

    public LineExample() {

        fillHashMap(hashMap);

        JFrame frame = new JFrame();

        JPanel mainPanel = new JPanel(new BorderLayout());
        JPanel northPanel = new JPanel(new FlowLayout());
        JPanel centerPanel = new JPanel(new GridLayout(1, 2));
        CustomPanel customPanel = new CustomPanel();
        BluePanel bluePanel = new BluePanel();

        JComboBox<String> comboBox = new JComboBox<String>();
        addItems(comboBox);
        comboBox.addItemListener(new ItemListener() {
            @Override
            public void itemStateChanged(ItemEvent e) {
                currentColor = hashMap.get(comboBox.getSelectedItem());
                centerPanel.repaint();
            }
        });

        JToggleButton toggleButton = new JToggleButton("Switch");
        toggleButton.addItemListener(new ItemListener() {
            @Override
            public void itemStateChanged(ItemEvent e) {
                centerPanel.removeAll();
                if (e.getStateChange() == ItemEvent.SELECTED) {
                    centerPanel.add(bluePanel);
                    centerPanel.add(customPanel);
                } else if (e.getStateChange() == ItemEvent.DESELECTED) {
                    centerPanel.add(customPanel);
                    centerPanel.add(bluePanel);
                }
                centerPanel.revalidate();
                centerPanel.repaint();
            }
        });

        northPanel.add(comboBox);
        northPanel.add(toggleButton);
        centerPanel.add(customPanel);
        centerPanel.add(bluePanel);
        mainPanel.add(northPanel, BorderLayout.NORTH);
        mainPanel.add(centerPanel, BorderLayout.CENTER);

        frame.setContentPane(mainPanel);

        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setSize(250, 250);
        frame.setVisible(true);

    }

    public void addItems(JComboBox<String> comboBox) {
        for (int i = 0; i < colors.length; i++) {
            comboBox.addItem(colorNames[i]);
        }
        comboBox.setSelectedIndex(2);
    }

    public void fillHashMap(HashMap<String, Color> hashmap) {
        for (int i = 0; i < colors.length; i++) {
            hashMap.put(colorNames[i], colors[i]);
        }
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new LineExample();
            }
        });
    }

    public class BluePanel extends JPanel {
        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            int width = 100;
            int height = 100;
            int x = ((this.getWidth() - width) / 2);
            int y = ((this.getHeight() - height) / 2);
            g.setColor(Color.BLUE);
            g.fillRect(x, y, width, height);
            g.setColor(Color.BLACK);
            g.drawRect(x, y, width, height);
        }
    }

    public class CustomPanel extends JPanel {
        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            int width = 100;
            int height = 100;
            int x = ((this.getWidth() - width) / 2);
            int y = ((this.getHeight() - height) / 2);
            g.setColor(currentColor);
            g.fillRect(x, y, width, height);
            g.setColor(Color.BLACK);
            g.drawRect(x, y, width, height);
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

Zon*_*ong 8

由于LCD显示器中的子像素排列,这是一个有趣的问题.我用手机拍了一些显示器的照片来解释这个效果.

首先我们看左侧.该线看起来约为2像素厚.这是因为在线上从左到右是从黑到蓝的过渡.由于红色和绿色像素无法照亮蓝色,我们必须等到线后的下一个蓝色子像素结束.

在此输入图像描述

然后我们看右边.该线约为1像素厚.这次是黑色到白色的过渡,因此红色和绿色像素可以在线后照亮.

在此输入图像描述

出现此问题的原因是Java图形库不是亚像素感知的(至少对于形状而言).对于每个显示器上的某些颜色组合,您总会遇到此问题.红绿蓝原色最为明显,这就是为什么在你的青色例子中很难说清楚的原因.

  • @HovercraftFullOfEels考虑赏金;-) (2认同)