2015-09-15 81 views
5

正常工作,我總是創造了這樣的輪廓的矩形(使用Graphics2D)):的drawRect()是不是在某些顏色

g.setColor(aColor); 
g.fillRect(x, y, width, height); 
g.setColor(anotherColor); 
g.drawRect(x, y, width, height); 

這工作得很好,除了一些顏色像Color.BLUE。有沒有相同厚度的線:

enter image description here

可能是很難看到的第一眼,但如果你仔細觀察,你會發現,左線太厚,右線太薄。這也正好與其他顏色搭配,只是不那麼明顯:(我仍然不知道,如果發生這種情況與青色,不能確切地告訴)

enter image description here

我不能做這個,因爲感覺黑色線條正被繪製到內部藍色矩形上,內部矩形不應該對其產生影響。 (沒有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); 
     } 
    } 

} 
+0

'左邊線太厚,右邊線太細。' - 我總是看到1像素的黑線。我拍了一張屏幕打印並將圖像加載到MS Paint中並放大。我還將張貼的圖像加載到了Paint中。即使你的圖像是1像素。所以我不確定你在描述什麼。 – camickr

+0

當您保存圖像並在某個圖像查看器中查看圖像並放大時,您會注意到左側和右側的邊框都只有一個像素寬。你在那裏看到的東西(順便說一句,我沒有真正看到它)幾乎肯定會在這裏描述:http://graphicdesign.stackexchange。com/questions/42306/why-do-two-perfectly-adjacent-rectangles-create-black-or-white-lines-in-between – Marco13

回答

8

這是因爲出現在LCD顯示器子像素排列的一個有趣的問題。我用手機拍了一些我的顯示器的照片來解釋這種效果。

首先我們看左側。該線似乎約2個像素厚。這是由於在線上從左到右是從黑到藍的過渡。由於紅色和綠色像素對於藍色不能點亮,因此我們必須等待直到該行結束後藍色子像素爲止的下一個。

enter image description here

然後我們看看右側。這條線約爲1像素厚。這次是黑到白的過渡,所以紅線和綠線可以在線後面照亮。

enter image description here

產生這一問題作爲Java圖形庫不知道的子像素(至少對於形狀)。每個顯示器上的顏色組合都會有這個問題。對於紅綠藍色的原色來說,這將是最明顯的,這就是爲什麼在你的青色的例子中很難說清楚。

+0

非常令人印象深刻 - 感謝和1+(希望我可以投票100 +)。 –

+2

@HovercraftFullOfEels考慮一個賞金;-) – Marco13

+1

我想我的視力不足以看到這個問題(或所有的LCD屏幕上都不會發生這種情況嗎?)。很高興知道它存在(1+)。 – camickr

0

可能與antialiasing有關?當我面對這些類型的問題,我通常做這樣的事情......

Graphics2D g2 = (Graphics2D)g; 
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 

// draw stuff 

g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_DEFAULT); 
+0

我已經嘗試過,沒有工作。請注意,你可以先用我的例子自己試試。 –