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

时间:2017-05-25 10:19:59

标签: java swing 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,它取决于每个细胞群,但是没有找到如何做到这一点。

下面是您可以测试的示例(注意:我删除了所有import语句):

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 个答案:

答案 0 :(得分:3)

我建议采用以下方法:
修改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