2017-05-11 2 views
1

Ich versuche, zwischen Zellen, die JLabel sind, Linien zu zeichnen, aber nicht ihre Koordinaten zu erhalten. Die Linien müssen einem Pfad von einem StartPoint zu einem EndPoint folgen.Zeichnen von Zeilen zwischen JLabel in 2d Array Raster

Meiner Ansicht Klasse erstellt der folgende Code, um das Gitter: für die View-Klasse

private Icon createIcon(Color color) { 

     BufferedImage img = new BufferedImage(ICON_W, ICON_W, BufferedImage.TYPE_INT_ARGB); 
     Graphics2D g2 = img.createGraphics(); 
     g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 
     g2.setColor(color); 
     g2.fillOval(1, 1, ICON_W - 2, ICON_W - 2); // int ICON_W = 20; 
     g2.dispose(); 

     return new ImageIcon(img); 
    } 

Der gesamte Code:

void createGrid(int rows, int cols) { 

MyMouseListener listener = new MyMouseListener(); 
setRows(rows); 

mainPanel.setLayout(new GridLayout(rows, cols, 1, 1)); 
mainPanel.setBorder(BorderFactory.createLineBorder(Color.BLACK)); 
mainPanel.setBackground(Color.DARK_GRAY); 
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].addMouseListener(listener); 
     grid[r][c].setOpaque(true); 
     grid[r][c].setBackground(Color.WHITE); 
     //grid[r][c].setPreferredSize(new Dimension(ICON_W, ICON_W)); 
     mainPanel.add(grid[r][c]); 
    } 
} 

}

Während dies die Symbole erstellt: https://pastebin.com/sgyn6rSR Code für den Pfad algo: https://pastebin.com/Gcw9YVMF

Ich habe so etwas wie unten versucht, funktioniert aber nicht

Graphics2D g2d = (Graphics2D) g.create(); 

      for (JLabel[] grid : cells) { 
       g2d.setColor(Color.BLUE); 
       Point startPoint = grid[0].getLocation(); 
       Point endPoint = grid[1].getLocation(); 
       startPoint.x += (grid[0].getWidth()/2); 
       startPoint.y += (grid[1].getHeight()/ 2); 
       endPoint.x += (grid[0].getWidth()/2); 
       endPoint.y += (grid[1].getHeight()/ 2); 

       if(startPoint != null){ 
       g2d.draw(new Line2D.Double(startPoint, endPoint)); 
      } 

      startPoint = endPoint; 

     } 

Antwort

1

Hier wird die View-Klasse ist modifizierten Zeilen hinzuzufügen, wie gewünscht.
Bitte überprüfen und sehen, Kommentare:

import java.awt.BasicStroke; 
import java.awt.Color; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.GridBagConstraints; 
import java.awt.GridBagLayout; 
import java.awt.GridLayout; 
import java.awt.Point; 
import java.awt.Rectangle; 
import java.awt.RenderingHints; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import java.awt.image.BufferedImage; 
import java.beans.PropertyChangeListener; 
import java.util.EnumMap; 
import java.util.Map; 

import javax.swing.BorderFactory; 
import javax.swing.Icon; 
import javax.swing.ImageIcon; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 


public class View { 

    public static final String CELL_SELECTION = "cell selection"; 
    private final static int GAP = 2; 
    private static int iconWidth; 
    private int rows; 

    private JPanel mainPanel; 
    private JLabel[][] grid; 
    private Map<Token, Icon> iconMap = new EnumMap<>(Token.class); 
    private int selectedRow; 
    private int selectedCol; 

    //a collection of cells representing a path 
    private CellsList path; 

    //a pane to hold two panels one on top of the other 
    JPanel layeredPanel; 

    View() { 

     mainPanel = new JPanel(); 

     //add layerd pane to hold two panels one on top of the other 
     layeredPanel = new JPanel(); 

     //set GridBagLayout to allow placing two components one on top of the other 
     layeredPanel.setLayout(new GridBagLayout()); 
      GridBagConstraints gbc = new GridBagConstraints(); 
      gbc.gridx = 0; 
      gbc.gridy = 0; 
      gbc.weightx = 1; 
      gbc.weighty = 1; 
      gbc.fill = GridBagConstraints.BOTH; 

     //add main panel to layered panel 
     layeredPanel.add(mainPanel, gbc); 

     //create and add a drawing panel 
     DrawJPanel drawPanel = new DrawJPanel(); 
     drawPanel.setOpaque(false); //set if to transparent so it does not 
            //hide mainPanel under it 
     layeredPanel.add(drawPanel, gbc); 

     //set z-order (depth) of two panels 
     layeredPanel.setComponentZOrder(mainPanel,1); 
     layeredPanel.setComponentZOrder(drawPanel,0); 
    } 

    void createGrid(int rows, int cols) { 

     MyMouseListener listener = new MyMouseListener(); 
     setRows(rows); 
     setIcons(); 

     mainPanel.setLayout(new GridLayout(rows, cols, 1, 1)); 
     mainPanel.setBorder(BorderFactory.createLineBorder(Color.BLACK)); 
     mainPanel.setBackground(Color.BLACK); 
     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].addMouseListener(listener); 
       grid[r][c].setOpaque(true); 
       grid[r][c].setBackground(Color.WHITE); 
       mainPanel.add(grid[r][c]); 
      } 
     } 

     layeredPanel.setPreferredSize(mainPanel.getPreferredSize()); 
    } 

    int getSelectedRow() { 
     return selectedRow; 
    } 

    int getSelectedCol() { 
     return selectedCol; 
    } 

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

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

    int getRows() { 
     return rows; 
    } 

    void setRows(int rows) { 
     this.rows = rows; 
    } 

    //added to each cell to listen to mouse clicks 
    //fires property change with cell index 
    private class MyMouseListener extends MouseAdapter { 
     @Override 
     public void mousePressed(MouseEvent e) { 
      JLabel selection = (JLabel) e.getSource(); 
      for (int r = 0; r < grid.length; r++) { 
       for (int c = 0; c < grid[r].length; c++) { 
        if (selection == grid[r][c]) { 
         selectedRow = r; 
         selectedCol = c; 
         int index = (r * grid[r].length) + c; 
         mainPanel.firePropertyChange(CELL_SELECTION, -1, index); 
        } 
       } 
      } 
     } 
    } 

    void start() { 

     JFrame frame = new JFrame("MVC Pha"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.getContentPane().add(layeredPanel); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

    //add listener to listen to property changes fired by MyMouseListener 
    void addPropertyChangeListener(PropertyChangeListener viewListener) { 

     mainPanel.addPropertyChangeListener(viewListener); 
    } 

    void setPath(CellsList path) { 

     this.path = path; 
     if(path != null) { 
      drawPath(); 
     } 
    } 
    //highlight path by changing background color. 
    //It can be changed to draw lines between cells 
    private void drawPath() { 

     for (int row = 0; row < grid.length; row++) { 
      for (int col = 0; col < grid[row].length; col++) { 

       if((path != null) && path.contains(new int[] {row,col})) { 
        grid[row][col].setBackground(Color.YELLOW); 
       } else { 
        grid[row][col].setBackground(Color.WHITE); 
       } 
      } 
     } 
    } 

    //receives rectangle and returns its center point 
    private Point getComponentCenter(Rectangle bounds) { 

     int xCenter = (int) ((bounds.getX()+ bounds.getMaxX())/2); 
     int yCenter = (int) ((bounds.getMinY()+ bounds.getMaxY())/2); 
     return new Point(xCenter, yCenter); 
    } 

    void refresh() { 

     layeredPanel.repaint(); 
    } 

    private void setIcons() { 

     if(rows <= 20) { 
      iconWidth = 24; 
     } else if(rows <= 40) { 
      iconWidth = 20; 
     } else if(rows <= 60) { 
      iconWidth = 15; 
     } else if(rows <= 80) { 
      iconWidth = 12; 
     } else { 
      iconWidth = 8; 
     } 

     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)); 
    } 

    private Icon createIcon(Color color) { 

     BufferedImage img = new BufferedImage(iconWidth, iconWidth, BufferedImage.TYPE_INT_ARGB); 
     Graphics2D g2 = img.createGraphics(); 
     g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 
     g2.setColor(color); 
     g2.fillOval(1, 1, iconWidth - GAP, iconWidth - GAP); 
     g2.dispose(); 

     return new ImageIcon(img); 
    } 

    //a panel to draw line on 
    class DrawJPanel extends JPanel { 

     @Override 
     protected void paintComponent(Graphics g){ 

      super.paintComponent(g); 

      if((path == null) || path.isEmpty()) { 
       return; 
      } 

      //calculate points to construct line along the path 
      Point[] polygon = new Point[path.size()]; 

      int i=0; 
      for(int[] address : path) { //iterate over path 

       //get cell location (row/col) 
       int row = address[0]; int col = address[1]; 

       //get label in that location 
       JLabel lable = grid[row][col]; 

       //add center of label as a point in polygon 
       polygon[i++] = getComponentCenter(lable.getBounds()); 
      } 

      //draw points in polygon 
      g.setColor(Color.CYAN); //set line color and width 
      Graphics2D g2 = (Graphics2D) g; 
      g2.setStroke(new BasicStroke(2)); 

      int j; 
      for (j = 0; j < (polygon.length -1); j++)  { 

       Point point1 = polygon[j]; 
       Point point2 = polygon[j+1]; 
       g2.draw(new Line2D.Float(point1, point2)); 
      } 

      //add line to connect last point to first 
      g2.draw(new Line2D.Float(polygon[j], polygon[0])); 
     } 
    } 
} 
+0

Sie haben mich unzählige Stunden des Versuchs, es zu arbeiten, gespeichert. Danke –

+0

Aber ich würde gerne wissen, warum Line2D.Float statt Line2D verwenden.Double gibt es hier einen Unterschied? –

+0

Sie können beide verwenden. Double hat eine höhere Genauigkeit (und Speicherauslastung), die hier nicht benötigt wird. – c0der

2

Aufschalten der paintComponent() Methode des Panels Sie die Etiketten hinzuzufügen.

würde der Grund Code sein:

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

    for (int i = 0; i < getComponentCount() - 1; i++) 
    { 
     Component component1 = getComponent(i); 
     Point point1 = component1.getLocation(); 
     Component component2 = getComponent(i + 1); 
     Point point2 = component2.getLocation(); 

     g.drawLine(point1.x, point1.y, point2.x, point2.y); 
    } 
} 

Sobald Sie diese Arbeiten Sie die Logik ändern kann die Linie von der vom/zum Zentrum jeder Komponente zu ziehen.

+0

Wird dies den Weg folgen ? Ich habe paintComponent überschrieben. Bitte schauen Sie sich den Code auf pastebin an. –

+2

@esQmo Wir betrachten den Code auf Pastebin nicht. Veröffentlichen Sie eine ordnungsgemäße [mcve], die das Problem veranschaulicht. Alles, was Sie brauchen, ist ein Code, um ein paar Beschriftungen zu einem Panel hinzuzufügen. Dann fügen Sie die benutzerdefinierte Logik hinzu, die ich zur Verfügung gestellt habe. Sie fügen dann das Panel zu einem Rahmen hinzu. Das ganze "MCVE" wird ungefähr 30 Codezeilen umfassen. Sobald Sie das Grundkonzept verstanden haben, integrieren Sie die Lösung in Ihre reale Anwendung.Der von mir bereitgestellte Code zeichnet die Linie in der Reihenfolge, in der die Komponenten zum Panel hinzugefügt werden. Wenn Sie eine andere Reihenfolge haben, dann würden Sie den Ansatz ändern, um durch Ihre Liste zu gehen. – camickr

+0

Ok, ich werde meine Frage mit den notwendigen –

1

Das hat lange gedauert. Sorry, aber ich habe eine Menge Zusammenhang auf die ursprüngliche Frage, einschließlich der Basis View und Path Code: P

Test Result

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.RenderingHints; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import java.awt.geom.Line2D; 
import java.awt.image.BufferedImage; 
import java.beans.PropertyChangeListener; 
import java.util.ArrayList; 
import java.util.EnumMap; 
import java.util.List; 
import java.util.Map; 
import java.util.Stack; 
import java.util.StringJoiner; 
import javax.swing.BorderFactory; 
import javax.swing.DebugGraphics; 
import javax.swing.Icon; 
import javax.swing.ImageIcon; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.SwingUtilities; 

public class View extends JPanel { 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       DrawLines drawLines = new DrawLines(); 
       JFrame frame = new JFrame(); 
       frame.setGlassPane(drawLines); 
       frame.add(new View(20, 20, drawLines)); 
       frame.getGlassPane().setVisible(true); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    enum Token { 
     VIDE, CERCLE_BLEU, CERCLE_ROUGE 
    } 

    private static final int ICON_W = 20; 
    public static final String CELL_SELECTION = "cell selection"; 
    private int rows; 

    private Token[][] tokens; 
    private JLabel[][] grid; 
    private Map<Token, Icon> iconMap = new EnumMap<>(Token.class); 
    private int selectedRow; 
    private int selectedCol; 

    //a collection of cells representing a path 
    private ArrayList<Cell> path; 

    private DrawLines drawLines; 

    View(int rows, int cols, DrawLines drawLines) { 
     this.drawLines = drawLines; 
     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); 
    } 

    private Icon createIcon(Color color) { 

     BufferedImage img = new BufferedImage(ICON_W, ICON_W, BufferedImage.TYPE_INT_ARGB); 
     Graphics2D g2 = img.createGraphics(); 
     g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 
     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) { 

     tokens = new Token[rows][cols]; 

     MyMouseListener listener = new MyMouseListener(); 
     setRows(rows); 

     setLayout(new GridLayout(rows, cols, 1, 1)); 
     setBorder(BorderFactory.createLineBorder(Color.BLACK)); 
     setBackground(Color.DARK_GRAY); 
     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].addMouseListener(listener); 
       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]); 
      } 
     } 

     set(6, 6, Token.CERCLE_ROUGE); 
     set(6, 7, Token.CERCLE_ROUGE); 
     set(6, 8, Token.CERCLE_ROUGE); 
     set(6, 9, Token.CERCLE_ROUGE); 
     set(7, 9, Token.CERCLE_ROUGE); 
     set(8, 9, Token.CERCLE_ROUGE); 
     set(9, 9, Token.CERCLE_ROUGE); 
     set(10, 9, Token.CERCLE_ROUGE); 
     set(10, 6, Token.CERCLE_ROUGE); 
     set(10, 7, Token.CERCLE_ROUGE); 
     set(10, 8, Token.CERCLE_ROUGE); 
     set(10, 9, Token.CERCLE_ROUGE); 
     set(7, 6, Token.CERCLE_ROUGE); 
     set(8, 6, Token.CERCLE_ROUGE); 
     set(9, 6, Token.CERCLE_ROUGE); 
// 
//  set(7, 6, Token.CERCLE_ROUGE); 
//  set(7, 7, Token.CERCLE_BLEU); 
//  set(7, 8, Token.CERCLE_BLEU); 
// 
//  set(8, 6, Token.CERCLE_ROUGE); 
//  set(8, 7, Token.CERCLE_ROUGE); 
//  set(8, 8, Token.CERCLE_ROUGE); 
// 
//  set(5, 7, Token.CERCLE_ROUGE); 
//  set(5, 8, Token.CERCLE_ROUGE); 
//  set(5, 9, Token.CERCLE_ROUGE); 
//  set(6, 9, Token.CERCLE_ROUGE); 
//  set(7, 9, Token.CERCLE_ROUGE); 
     Path path = new Path(tokens); 
     if (path.findPath(new int[]{6, 6})) { 
      setPath(path.getPath()); 
     } 
    } 

    void set(int row, int col, Token token) { 
     grid[row][col].setIcon(iconMap.get(token)); 
     tokens[row][col] = token; 
    } 

    int getSelectedRow() { 
     return selectedRow; 
    } 

    int getSelectedCol() { 
     return selectedCol; 
    } 

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

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

    int getRows() { 
     return rows; 
    } 

    void setRows(int rows) { 
     this.rows = rows; 
    } 

    //added to each cell to listen to mouse clicks 
    //fires property change with cell index 
    private class MyMouseListener extends MouseAdapter { 

     @Override 
     public void mousePressed(MouseEvent e) { 
      JLabel selection = (JLabel) e.getSource(); 
      for (int r = 0; r < grid.length; r++) { 
       for (int c = 0; c < grid[r].length; c++) { 
        if (selection == grid[r][c]) { 
         selectedRow = r; 
         selectedCol = c; 
         int index = (r * grid[r].length) + c; 
         selection.setIcon(iconMap.get(Token.CERCLE_BLEU)); 
         tokens[selectedRow][selectedCol] = Token.CERCLE_BLEU; 
         System.out.println(c + "x" + r + " = " + index); 
         firePropertyChange(CELL_SELECTION, -1, index); 

         Path path = new Path(tokens); 
         if (path.findPath(new int[]{selectedRow, selectedCol})) { 
          setPath(path.getPath()); 
         } 
        } 
       } 
      } 
     } 
    } 

    //add listener to listen to property changes fired by MyMouseListener 
    public void addPropertyChangeListener(PropertyChangeListener viewListener) { 

     addPropertyChangeListener(viewListener); 
    } 

    void setPath(ArrayList<Cell> path) { 

     this.path = path; 
     if (path != null) { 
      drawPath(); 
     } 
    } 

    //highlight path by changing background color. 
    //It can be changed to draw lines between cells 
    private void drawPath() { 
     if (path != null) { 
      List<JLabel> labels = new ArrayList<>(25); 
      for (Cell cell : path) { 
       JLabel label = grid[cell.y][cell.x]; 
       label.setBackground(Color.YELLOW); 
       labels.add(label); 
      } 
      for (int r = 0; r < grid.length; r++) { 
       for (int c = 0; c < grid[r].length; c++) { 

        if (!path.contains(new Cell(c, r))) { 
         grid[r][c].setBackground(Color.WHITE); 
        } 

       } 
      } 

      drawLines.setPath(labels); 
     } 
    } 

    void refresh() { 

     repaint(); 
    } 

//This is what I added to try drawing lines 
    public static class DrawLines extends JLabel { 

     List<JLabel> path; 

     public void setPath(List<JLabel> path) { 
      this.path = new ArrayList<>(path); 
      this.path.add(path.get(0)); 
      repaint(); 
     } 

     @Override 
     public void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      if (path != null) { 
       Graphics2D g2d = (Graphics2D) g.create(); 
       Point startPoint = null; 
       for (JLabel label : path) { 
        g2d.setColor(Color.DARK_GRAY); 
        Point endPoint = label.getLocation(); 
        endPoint.x += (label.getWidth()/2); 
        endPoint.y += (label.getHeight()/2); 
        if (startPoint != null) { 
         g2d.draw(new Line2D.Float(startPoint, endPoint)); 
        } 
        startPoint = endPoint; 
       } 
       g2d.dispose(); 
      } 
     } 

    } 

    class Cell { 

     private int x, y; 

     public Cell(int x, int y) { 
      this.x = x; 
      this.y = y; 
     } 

     public int getX() { 
      return x; 
     } 

     public int getY() { 
      return y; 
     } 

     @Override 
     public int hashCode() { 
      int hash = 7; 
      return hash; 
     } 

     @Override 
     public boolean equals(Object obj) { 
      if (this == obj) { 
       return true; 
      } 
      if (obj == null) { 
       return false; 
      } 
      if (getClass() != obj.getClass()) { 
       return false; 
      } 
      final Cell other = (Cell) obj; 
      if (this.x != other.x) { 
       return false; 
      } 
      if (this.y != other.y) { 
       return false; 
      } 
      return true; 
     } 

     @Override 
     public String toString() { 
      return x + "x" + y; 
     } 

    } 

    class Path extends Stack<Cell> { 

     private Token[][] grid; 

     //a path shorter than min can not surround any cell 
     private static final int MIN_PATH_LEGTH = 3; 

     //a collection of cells that has been tested 
     private ArrayList<Cell> checked; 

     //represents the cell where the search starts from 
     Cell origin; 
     //represents the token of the origin 
     Token originToken; 

     private int rows; 
     private int cols; 

     Path(Token[][] grid) { 

      this.grid = grid; 
      rows = grid.length; 
      cols = grid[0].length; 
     } 

     //search for a path 
     boolean findPath(int[] origin) { 

      int row = origin[0], col = origin[1]; 
      this.origin = new Cell(col, row); 

      //represents the token of the origin 
      originToken = grid[row][col]; 

      //initialize list of checked items 
      checked = new ArrayList<>(); 

      boolean found = findPath(row, col); 

      if (found) { 
       printPath(); 
      } else { 
       System.out.println("No path found"); 
      } 

      return found; 
     } 

     //recursive method to find path. a cell is represented by its row, col 
     //returns true when path was found 
     private boolean findPath(int row, int col) { 

      //check if cell has the same token as origin 
      if (grid[row][col] != originToken) { 
       return false; 
      } 

      Cell cell = new Cell(col, row); 

      //check if this cell was tested before to avoid checking again 
      if (checked.contains(cell)) { 
       return false; 
      } 

      //get cells neighbors 
      ArrayList<Cell> neighbors = getNeighbors(row, col); 

      //check if solution found. If path size > min and cell 
      //neighbors contain the origin it means that path was found 
      if ((size() >= MIN_PATH_LEGTH) && neighbors.contains(origin)) { 

       add(cell); 
       return true; 
      } 

      //add cell to checked list 
      checked.add(cell); 

      //add cell to path 
      add(cell); 

      //if path was not found check cell neighbors 
      for (Cell neighbor : neighbors) { 

       boolean found = findPath(neighbor.getY(), neighbor.getX()); 
       if (found) { 
        return true; 
       } 
      } 

      //path not found 
      pop(); //remove last element from stack 
      return false; 
     } 

     //return a list of all neighbors of cell row, col 
     private ArrayList<Cell> getNeighbors(int row, int col) { 

      ArrayList<Cell> neighbors = new ArrayList<Cell>(); 

      for (int colNum = col - 1; colNum <= (col + 1); colNum += 1) { 

       for (int rowNum = row - 1; rowNum <= (row + 1); rowNum += 1) { 

        if (!((colNum == col) && (rowNum == row))) { 

         if (withinGrid(rowNum, colNum)) { 

          neighbors.add(new Cell(colNum, rowNum)); 
         } 
        } 
       } 
      } 

      return neighbors; 
     } 

     private boolean withinGrid(int colNum, int rowNum) { 

      if ((colNum < 0) || (rowNum < 0)) { 
       return false; 
      } 
      if ((colNum >= cols) || (rowNum >= rows)) { 
       return false; 
      } 
      return true; 
     } 

     //use for testing 
     private void printPath() { 
      StringJoiner sj = new StringJoiner(",", "Path: ", ""); 
      for (Cell cell : this) { 
       sj.add(cell.toString()); 
      } 
      System.out.println(sj); 

     } 

     public ArrayList<Cell> getPath() { 
      ArrayList<Cell> cl = new ArrayList<>(); 
      cl.addAll(this); 
      return cl; 
     } 
    } 
} 

aber die Linien sind Neulackierung nicht. Gibt es eine Möglichkeit, sie zu retten?

Die DrawLines zeichnet den Pfad, den Sie übergeben. Um eine „Geschichte“ zu liefern, müssen Sie eine andere List aller Pfade halten Sie weitergeben, zum Beispiel ...

public static class DrawLines extends JLabel { 

    private List<List<JLabel>> history; 

    public DrawLines() { 
     history = new ArrayList<>(25); 
    } 

    public void setPath(List<JLabel> path) { 
     List<JLabel> copy = new ArrayList<>(path); 
     copy.add(path.get(0)); 

     history.add(copy); 
     repaint(); 
    } 

    @Override 
    public void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     Graphics2D g2d = (Graphics2D) g.create(); 
     Point startPoint = null; 
     for (List<JLabel> path : history) { 
      for (JLabel label : path) { 
       g2d.setColor(Color.DARK_GRAY); 
       Point endPoint = label.getLocation(); 
       endPoint.x += (label.getWidth()/2); 
       endPoint.y += (label.getHeight()/2); 
       if (startPoint != null) { 
        g2d.draw(new Line2D.Float(startPoint, endPoint)); 
       } 
       startPoint = endPoint; 
      } 
     } 
     g2d.dispose(); 
    } 

} 
+0

Works wie erwartet, leider keine Möglichkeit, mehr als 1 Antwort zu akzeptieren. Aber die Linien werden nicht neu gestrichen. Gibt es eine Möglichkeit, sie zu retten? –

+0

Es hängt davon ab, was Sie erreichen möchten, aber, DrawPanel erstellt eine neue Liste der JLabels, also könnten Sie eine andere Liste haben, in die Sie diese Pfade hinzufügen – MadProgrammer

+0

Ja, werde versuchen diesen Ansatz dann wieder kommen, wenn irgendwo stecken. –

1

Die folgende Antwort die gleiche Lösung wie in meinem vorherigen answer präsentieren.
Zum Wohle aller (anderen Benutzern, diejenigen, die versuchen, sowie für das Plakat zu antworten), ich glaube, die Frage gestellt werden sollte und beantworten als mcve:

import java.awt.BasicStroke; 
import java.awt.Color; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.GridBagConstraints; 
import java.awt.GridBagLayout; 
import java.awt.GridLayout; 
import java.awt.Point; 
import java.awt.Rectangle; 
import java.awt.RenderingHints; 
import java.awt.geom.Line2D; 
import java.awt.image.BufferedImage; 
import java.util.ArrayList; 
import java.util.HashMap; 
import java.util.Map; 
import javax.swing.BorderFactory; 
import javax.swing.Icon; 
import javax.swing.ImageIcon; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 

public class View { 

    private static final String WHITE = "white"; 
    private static final String BLUE = "blue"; 

    private final static int GAP = 2; 
    private static final int iconWidth = 24; 

    private Map<String, Icon> iconMap = new HashMap<>(); 

    private JPanel mainPanel; 
    private JLabel[][] grid; 

    //a collection of cells representing a path 
    private ArrayList<int[]> path; 

    //a pane to hold two panels one on top of the other 
    JPanel layeredPanel; 

    View(int rows) { 

     JFrame frame = new JFrame("Line between JLabels"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     mainPanel = new JPanel(); 

     //add layered pane to hold two panels one on top of the other 
     layeredPanel = new JPanel(); 

     //set GridBagLayout to allow placing two components one on top of the other 
     layeredPanel.setLayout(new GridBagLayout()); 
      GridBagConstraints gbc = new GridBagConstraints(); 
      gbc.gridx = 0; 
      gbc.gridy = 0; 
      gbc.weightx = 1; 
      gbc.weighty = 1; 
      gbc.fill = GridBagConstraints.BOTH; 

     //add main panel to layered panel 
     layeredPanel.add(mainPanel, gbc); 

     //create and add a drawing panel 
     DrawJPanel drawPanel = new DrawJPanel(); 
     drawPanel.setOpaque(false); //set if to transparent so it does not 
            //hide mainPanel under it 
     layeredPanel.add(drawPanel, gbc); 

     //set z-order (depth) of two panels 
     layeredPanel.setComponentZOrder(mainPanel,1); 
     layeredPanel.setComponentZOrder(drawPanel,0); 

     path = new ArrayList<>(); 
     setTestData(); 
     createGrid(rows,rows); 

     frame.getContentPane().add(layeredPanel); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

    void createGrid(int rows, int cols) { 

     setIcons(); 

     mainPanel.setLayout(new GridLayout(rows, cols, 1, 1)); 
     mainPanel.setBorder(BorderFactory.createLineBorder(Color.BLACK)); 
     mainPanel.setBackground(Color.BLACK); 
     grid = new JLabel[rows][cols]; 
     for (int r = 0; r < grid.length; r++) { 
      for (int c = 0; c < grid[r].length; c++) { 
       if(isInPath(new int[] {r,c})) { 
        grid[r][c] = new JLabel(iconMap.get(BLUE)); 
       } else { 
        grid[r][c] = new JLabel(iconMap.get(WHITE)); 
       } 
       grid[r][c].setOpaque(true); 
       grid[r][c].setBackground(Color.WHITE); 
       mainPanel.add(grid[r][c]); 
      } 
     } 

     layeredPanel.setPreferredSize(mainPanel.getPreferredSize()); 
    } 

    //receives rectangle and returns its center point 
    private Point getComponentCenter(Rectangle bounds) { 

     int xCenter = (int) ((bounds.getX()+ bounds.getMaxX())/2); 
     int yCenter = (int) ((bounds.getMinY()+ bounds.getMaxY())/2); 
     return new Point(xCenter, yCenter); 
    } 

    private void setIcons() { 

     iconMap.put(WHITE, createIcon(new Color(0, 0, 0, 0))); 
     iconMap.put(BLUE, createIcon(Color.BLUE)); 
    } 

    private Icon createIcon(Color color) { 

     BufferedImage img = new BufferedImage(iconWidth, iconWidth, BufferedImage.TYPE_INT_ARGB); 
     Graphics2D g2 = img.createGraphics(); 
     g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 
     g2.setColor(color); 
     g2.fillOval(1, 1, iconWidth - GAP, iconWidth - GAP); 
     g2.dispose(); 

     return new ImageIcon(img); 
    } 

    private boolean isInPath(int[] cell) { 

     if((path == null) || path.isEmpty()) { 
      return false; 
     } 

     for(int[] p : path) { 

      if((cell[0]== p[0]) && (cell[1] == p[1])) { 
       return true; 
      } 
     } 

     return false; 
    } 

    //a panel to draw line on 
    class DrawJPanel extends JPanel { 

     @Override 
     protected void paintComponent(Graphics g){ 

      super.paintComponent(g); 

      if((path == null) || path.isEmpty()) { 
       return; 
      } 

      //calculate points to construct line along the path 
      Point[] polygon = new Point[path.size()]; 

      int i=0; 
      for(int[] address : path) { //iterate over path 

       //get cell location (row/col) 
       int row = address[0]; int col = address[1]; 

       //get label in that location 
       JLabel lable = grid[row][col]; 

       //add center of label as a point in polygon 
       polygon[i++] = getComponentCenter(lable.getBounds()); 
      } 

      //draw points in polygon 
      g.setColor(Color.CYAN); //set line color and width 
      Graphics2D g2 = (Graphics2D) g; 
      g2.setStroke(new BasicStroke(2)); 

      int j; 
      for (j = 0; j < (polygon.length -1); j++)  { 

       Point point1 = polygon[j]; 
       Point point2 = polygon[j+1]; 
       g2.draw(new Line2D.Float(point1, point2)); 
      } 

      //add line to connect last point to first 
      g2.draw(new Line2D.Float(polygon[j], polygon[0])); 
     } 
    } 

    public static void main(String[] args) { 

     new View(10); 
    } 

    private void setTestData() { 

     path.add(new int[] {3,3}); 
     path.add(new int[] {3,4}); 
     path.add(new int[] {3,5}); 
     path.add(new int[] {4,6}); 
     path.add(new int[] {5,5}); 
     path.add(new int[] {5,4}); 
     path.add(new int[] {5,3}); 
     path.add(new int[] {4,4}); 
    } 
}