如何根据2D网格上的路径设置不同颜色的线条

问题描述:

我有这个简单的程序,绘制了从单元格到单元格的线条,形成一条路径。我有两组路径:一组由红细胞组成,另一组由蓝细胞组成。 我只能够一次设置一种颜色,并且适用于两组。如何根据2D网格上的路径设置不同颜色的线条

现在我想要做的是设置线条的颜色以匹配单元格的颜色,每个组合使用自己的线条颜色。我使用自定义的绘画与下面的代码借鉴glassPane行:

@Override 
    public void paintComponent(Graphics g) {  
     super.paintComponent(g); 

     Graphics2D g2d = (Graphics2D) g.create(); 
     g2d.setColor(Color.RED); //Lines' Color is set here 
     g2d.setStroke(new BasicStroke(3)); 

     for(List<JLabel> line : lines) { 

      for(int i=0; i <(line.size()) ; i++) { 
       JLabel label1 = line.get(i); 
       int n = (i == (line.size()-1)) ? 0: i+1; 
       JLabel label2 = line.get(n); 
       g2d.draw(new Line2D.Float(getCenter(label1), getCenter(label2))); 
      } 
     } 

     g2d.dispose(); 
    } 

Screenshot of the result of the above code. A grid contains four red dots connected by red lines and four blue dots connected by red lines.

我怎样才能做到这一点?我正在考虑制作一个变量color,这取决于每个单元组,但没有找到如何做到这一点。

以下是你可以测试一个例子(注意:我删除了所有导入语句):

public class Example extends JPanel { 

    enum Token {VIDE, CERCLE_BLEU, CERCLE_ROUGE} 

    private static final int ICON_W = 21; 
    private JLabel[][] grid; 
    private Map<Token, Icon> iconMap = new EnumMap<>(Token.class); 

    List<JLabel> redCels = new ArrayList<>(); 
    List<JLabel> blueCells = new ArrayList<>(); 
    List<List<JLabel>> paths = new ArrayList<>(); 

    Example(int rows, int cols) { 

     setLayout(new GridLayout(rows, cols, 1, 1)); 
     setBorder(BorderFactory.createLineBorder(Color.BLACK)); 
     setBackground(Color.BLACK); 

     iconMap.put(Token.VIDE, createIcon(new Color(0, 0, 0, 0))); 
     iconMap.put(Token.CERCLE_BLEU, createIcon(Color.BLUE)); 
     iconMap.put(Token.CERCLE_ROUGE, createIcon(Color.RED)); 
     createGrid(rows, cols); 
     setTestData(); 
    } 

    private Icon createIcon(Color color) { 

     BufferedImage img = new BufferedImage(ICON_W, ICON_W, BufferedImage.TYPE_INT_ARGB); 
     Graphics2D g2 = img.createGraphics(); 
     g2.setColor(color); 
     g2.fillOval(1, 1, ICON_W - 2, ICON_W - 2); 
     g2.dispose(); 

     return new ImageIcon(img); 
    } 

    void createGrid(int rows, int cols) { 

     grid = new JLabel[rows][cols]; 
     for (int r = 0; r < grid.length; r++) { 
      for (int c = 0; c < grid[r].length; c++) { 
       grid[r][c] = new JLabel(iconMap.get(Token.VIDE)); 
       grid[r][c].setOpaque(true); 
       grid[r][c].setBackground(Color.WHITE); 
       grid[r][c].setPreferredSize(new Dimension(ICON_W, ICON_W)); 
       add(grid[r][c]); 
      } 
     } 
    } 

    void setTestData() { 

     //test data 
     set(11, 3, Token.CERCLE_ROUGE); 
     set(10, 2, Token.CERCLE_ROUGE); 
     set(9, 3, Token.CERCLE_ROUGE); 
     set(10, 4, Token.CERCLE_ROUGE); 

     set(8, 13, Token.CERCLE_BLEU); 
     set(9, 12, Token.CERCLE_BLEU); 
     set(10, 13, Token.CERCLE_BLEU); 
     set(9, 14, Token.CERCLE_BLEU); 

     paths.add(redCels); paths.add(blueCells); 
    } 

    void set(int row, int col, Token token) { 

     grid[row][col].setIcon(iconMap.get(token)); 

     if(token == Token.CERCLE_ROUGE) { 
      redCels.add(grid[row][col]); 
     }else { 
      blueCells.add(grid[row][col]); 
     } 
    } 

    private List<List<JLabel>> getPahs() { 
     return paths; 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 

       JFrame frame = new JFrame("TEST CASE"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       Example example = new Example(20, 20); 
       frame.add(example); 
       DrawLines glassPane = new DrawLines(example.getPahs()); 
       frame.setGlassPane(glassPane); 
       frame.getGlassPane().setVisible(true); 
       frame.setLocationRelativeTo(null); 
       frame.pack(); 
       frame.setResizable(false); 
       frame.setVisible(true); 
      } 
     }); 
    } 
} 

//used as glass pane to draw lines 
class DrawLines extends JPanel { 


    private List<List<JLabel>> lines; 
    DrawLines(List<List<JLabel>> lines) { 

     this.lines = lines; 
     setOpaque(false); 
    } 

    @Override 
    public void paintComponent(Graphics g) { 

     super.paintComponent(g); 

     Graphics2D g2d = (Graphics2D) g.create(); 
     g2d.setColor(Color.RED); 
     g2d.setStroke(new BasicStroke(3)); 

     for(List<JLabel> line : lines) { 

      for(int i=0; i <(line.size()) ; i++) { 
       JLabel label1 = line.get(i); 
       int n = (i == (line.size()-1)) ? 0: i+1; 
       JLabel label2 = line.get(n); 
       g2d.draw(new Line2D.Float(getCenter(label1), getCenter(label2))); 
      } 
     } 

     g2d.dispose(); 
    } 

    private Point getCenter(JComponent comp) { 
     int x = comp.getX()+ (comp.getWidth()/2); 
     int y = comp.getY() + (comp.getHeight()/2); 
     return new Point(x,y); 
    } 
} 
+1

请注意,发帖[ mvce]还需要所有导入 – c0der

+0

我认为这是没有必要的,因为IDE可以添加它们 –

我建议以下方法:
修改Token枚举所以其持有的颜色和图标信息:

enum Token { 

    VIDE (Color.WHITE), CERCLE_BLEU (Color.BLUE), CERCLE_ROUGE(Color.RED); 

    private static final int ICON_W = 21; 
    public Color color; 
    public Icon icon; 

    Token(Color color) { 

     this.color = color; 
     icon = createIcon(color); 
    } 

    private Icon createIcon(Color color) { 

     BufferedImage img = new BufferedImage(ICON_W, ICON_W, BufferedImage.TYPE_INT_ARGB); 
     Graphics2D g2 = img.createGraphics(); 
     g2.setColor(color); 
     g2.fillOval(1, 1, ICON_W - 2, ICON_W - 2); 
     g2.dispose(); 

     return new ImageIcon(img); 
    } 
} 

子类JLabel创建JLabel使用Token可以初始化:

class TLabel extends JLabel{ 

    Token token; 
    TLabel(Token token) { 
     setToken(token); 
    } 

    void setToken(Token token) { 

     this.token = token; 
     setIcon(token.icon); 
     setPreferredSize(new Dimension(
       token.icon.getIconWidth(), token.icon.getIconHeight())); 
    } 
    Token getToken() { 
     return token; 
    } 

    Color getColor() { 
     return token.color; 
    } 
} 


注意的TLabel一个实例持有Token和色彩信息,具有相应的图标和正确的首选尺寸。
使用TLabel在你的应用程序如下:

import java.awt.BasicStroke; 
import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.GridLayout; 
import java.awt.Point; 
import java.awt.geom.Line2D; 
import java.awt.image.BufferedImage; 
import java.util.ArrayList; 
import java.util.List; 
import javax.swing.BorderFactory; 
import javax.swing.Icon; 
import javax.swing.ImageIcon; 
import javax.swing.JComponent; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.SwingUtilities; 


public class Example extends JPanel { 

    private TLabel[][] grid; 

    List<TLabel> redCels = new ArrayList<>(); 
    List<TLabel> blueCells = new ArrayList<>(); 
    List<List<TLabel>> paths = new ArrayList<>(); 

    Example(int rows, int cols) { 

     setLayout(new GridLayout(rows, cols, 1, 1)); 
     setBorder(BorderFactory.createLineBorder(Color.BLACK)); 
     setBackground(Color.BLACK); 
     createGrid(rows, cols); 
     setTestData(); 
    } 

    void createGrid(int rows, int cols) { 

     grid = new TLabel[rows][cols]; 
     for (int r = 0; r < grid.length; r++) { 
      for (int c = 0; c < grid[r].length; c++) { 
       grid[r][c] = new TLabel(Token.VIDE); 
       grid[r][c].setOpaque(true); 
       grid[r][c].setBackground(Color.WHITE); 
       add(grid[r][c]); 
      } 
     } 
    } 

    void setTestData() { 

     //test data 
     set(11, 3, Token.CERCLE_ROUGE); 
     set(10, 2, Token.CERCLE_ROUGE); 
     set(9, 3, Token.CERCLE_ROUGE); 
     set(10, 4, Token.CERCLE_ROUGE); 

     set(8, 13, Token.CERCLE_BLEU); 
     set(9, 12, Token.CERCLE_BLEU); 
     set(10, 13, Token.CERCLE_BLEU); 
     set(9, 14, Token.CERCLE_BLEU); 

     paths.add(redCels); paths.add(blueCells); 
    } 

    void set(int row, int col, Token token) { 

     grid[row][col].setToken(token); 

     if(token == Token.CERCLE_ROUGE) { 
      redCels.add(grid[row][col]); 
     }else { 
      blueCells.add(grid[row][col]); 
     } 
    } 

    private List<List<TLabel>> getPahs() { 
     return paths; 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 

       JFrame frame = new JFrame("TEST CASE"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       Example example = new Example(20, 20); 
       frame.add(example); 
       DrawLines glassPane = new DrawLines(example.getPahs()); 
       frame.setGlassPane(glassPane); 
       frame.getGlassPane().setVisible(true); 
       frame.setLocationRelativeTo(null); 
       frame.pack(); 
       frame.setResizable(false); 
       frame.setVisible(true); 
      } 
     }); 
    } 


} 

enum Token { 

    VIDE (Color.WHITE), CERCLE_BLEU (Color.BLUE), CERCLE_ROUGE(Color.RED); 

    private static final int ICON_W = 21; 
    public Color color; 
    public Icon icon; 

    Token(Color color) { 

     this.color = color; 
     icon = createIcon(color); 
    } 

    private Icon createIcon(Color color) { 

     BufferedImage img = new BufferedImage(ICON_W, ICON_W, BufferedImage.TYPE_INT_ARGB); 
     Graphics2D g2 = img.createGraphics(); 
     g2.setColor(color); 
     g2.fillOval(1, 1, ICON_W - 2, ICON_W - 2); 
     g2.dispose(); 

     return new ImageIcon(img); 
    } 
} 

class TLabel extends JLabel{ 

    Token token; 
    TLabel(Token token) { 
     setToken(token); 
    } 

    void setToken(Token token) { 

     this.token = token; 
     setIcon(token.icon); 
     setPreferredSize(new Dimension(
       token.icon.getIconWidth(), token.icon.getIconHeight())); 
    } 
    Token getToken() { 
     return token; 
    } 

    Color getColor() { 
     return token.color; 
    } 
} 

//used as glass pane to draw lines 
class DrawLines extends JPanel { 

    private List<List<TLabel>> lines; 
    DrawLines(List<List<TLabel>> lines) { 

     this.lines = lines; 
     setOpaque(false); 
    } 

    @Override 
    public void paintComponent(Graphics g) { 

     super.paintComponent(g); 

     Graphics2D g2d = (Graphics2D) g.create(); 
     g2d.setStroke(new BasicStroke(3)); 

     for(List<TLabel> line : lines) { 

      //use color information from TLabel 
      //the whole path is of the same color so do it one per path 
      g2d.setColor(line.get(0).getColor()); 

      for(int i=0; i <(line.size()) ; i++) { 
       TLabel label1 = line.get(i); 
       int n = (i == (line.size()-1)) ? 0: i+1; 
       TLabel label2 = line.get(n); 
       g2d.draw(new Line2D.Float(getCenter(label1), getCenter(label2))); 
      } 
     } 

     g2d.dispose(); 
    } 


注意,设置线的颜色,你只需从获得颜色TLabel,如:g2d.setColor(tLabel.getColor());

enter image description here

+1

谢谢,按预期工作! –