如何突出显示主 JPanel 中的特定子面板?

Posted

技术标签:

【中文标题】如何突出显示主 JPanel 中的特定子面板?【英文标题】:How to highlight specific subpanel in a master JPanel? 【发布时间】:2022-01-15 14:07:34 【问题描述】:

我正在为基于迷宫的游戏构建 GUI。

主 JPanel 由较小的 JPanel 组成,我称之为 Tiles。我的目标是当玩家在该单元格中时突出显示特定的 Tile JPanel。它看起来像这样:

这是 MRE 的代码。我认为您可以使用任何 3 test.png 。我认为它不起作用,因为上面带有图像的 JLabel 掩盖了高光。


public class testGui extends JFrame 
  
  private final Board board;
  
  public testGui() 
    
    this.setSize(600, 600);
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.setResizable(false);

    this.board = new Board();
    JScrollPane scroller = new JScrollPane(board);
    this.add(scroller, BorderLayout.CENTER);
  
  
  
  
  
  public ImageIcon getImage(int i) 
    

    try 
      
      BufferedImage imageBase = ImageIO.read(getClass().getResource(String.format("/images/test%d.png", i)));
      
      int width = imageBase.getWidth();
      int height = imageBase.getHeight();
      
      BufferedImage combined = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
      Graphics g = combined.getGraphics();
      g.drawImage(imageBase, 0, 0, null);        
        ImageIcon icon = new ImageIcon(combined);
        return icon;

       
   catch (IOException ex) 
      Logger.getLogger(DungeonGui.class.getName()).log(Level.SEVERE, null, ex);

  

   return null; 
  
  
  private class Board extends JPanel 

    public Board() 

      setLayout(new GridBagLayout());
      GridBagConstraints gbc = new GridBagConstraints();
      gbc.gridx = 0;
      gbc.gridy = 0;
      

      for (int i = 0; i < 3; i++) 
        
        Tile tile = new Tile(i);
        
        cellPanel.setName(String.format("%d", i));
        add(tile, gbc);
        gbc.gridx++;
        if (gbc.gridx >= 3) 
            gbc.gridx = 0;
            gbc.gridy++;
        

if (i ==2) 

//TODO highlight JUST this tile


    
    
    
    
   
  
  

  private class Tile extends JPanel  
    

    private int i;
    private JLabel label;
    private Color highlight = new Color(0, 0, 255, 128);
    
    public CellPanel(int i) 
      super();
      this.i = i;
      
      this.setLayout(new GridLayout(1, 1));
      
      ImageIcon imageIcon = getImage(i);
      
      this.label = new JLabel(imageIcon);
      this.add(label);
      
      setOpaque(false);
      
    

    @Override
    public void paintComponent(Graphics g) 
      
      super.paintComponent(g);
      
      ImageIcon imageIcon = getImage(i);
      
      this.label.setIcon(imageIcon);
      
      Graphics2D g2d = (Graphics2D) g.create();
      
      g2d.setColor(highlight);
      g2d.fillRect(0, 0, getWidth(), getHeight());
      g2d.dispose();
      

    
    
  
  
  @Override
  public void refresh() 
    
    this.repaint();
  

  @Override
  public void makeVisible() 

    this.setVisible(true);
    
  



【问题讨论】:

你的minimal reproducible example在哪里?您在其他问题中被要求提供 MRE,因此是时候学习如何在您的问题中发布一个 MRE。使用 JFrame、您的 JLabel(带有文本)和自定义绘画代码创建一个简单示例,以尝试突出显示标签。如果它有效,那么您将解决方案应用于您的实际应用程序。如果它不起作用,那么您可以在此处发布您的 MRE。注意绘制方法应该只绘制组件的当前状态。这意味着您的逻辑不应该在绘画方法中设置图标。这就是为什么您需要 MRE,首先学习基础知识。 好的,我现在尝试设置一个 MRE。感谢您的反馈 另请注意,在您的另一个问题中,有两个人建议您不需要单独的面板。您的“Tile”可以使用您的自定义绘画扩展 JLabel,并将标签添加到您的“Board”类。 在没有“tiles”子面板的情况下,我无法弄清楚如何在每次操作后使用paintComponent 重新绘制我的迷宫。我确信有一种方法可以在主面板中使用paintComponent。 你没有做任何特别的事情。如果“Tile”类扩展 JPanel 或 JLabel,则没有区别。当“Tile”组件被重新绘制时,paintComponent() 方法将被自动调用。如果不是你有一个大的绘画问题,这就是为什么我说你需要在尝试构建应用程序之前先学习绘画基础知识。 【参考方案1】:

永远不要在 paint 方法中更新组件的状态,从长远来看,这将给您带来无穷无尽的问题。

如果您想更好地控制图像,那么您可以考虑创建一个自定义组件,该组件能够绘制图像,然后执行您想要的任何叠加/突出显示,例如

public class CellPane extends JPanel 

    private BufferedImage image;
    private boolean highlighted;

    public CellPane(BufferedImage image) 
        this.image = image;
    

    @Override
    public Dimension getPreferredSize() 
        BufferedImage image = getImage();
        return image == null ? new Dimension(128, 128) : new Dimension(image.getWidth(), image.getHeight());
    

    public boolean isHighlighted() 
        return highlighted;
    

    public void setHighlighted(boolean highlighted) 
        this.highlighted = highlighted;
        repaint();
    

    public BufferedImage getImage() 
        return image;
    

    @Override
    protected void paintComponent(Graphics g) 
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g.create();
        g2d.drawImage(image, 0, 0, this);
        if (isHighlighted()) 
            g2d.setColor(new Color(0, 0, 255, 128));
            g2d.fillRect(0, 0, getWidth(), getHeight());
        
        g2d.dispose();
    


可运行示例

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

public class Test 

    public static void main(String[] args) 
        new Test();
    

    public Test() 
        EventQueue.invokeLater(new Runnable() 
            @Override
            public void run() 
                List<Maze.Direction> directions = new ArrayList<>(32);
                directions.add(Maze.Direction.EAST_SOUTH);
                directions.add(Maze.Direction.EAST_SOUTH_WEST);
                directions.add(Maze.Direction.EAST_SOUTH_WEST);
                directions.add(Maze.Direction.EAST_SOUTH_WEST);
                directions.add(Maze.Direction.EAST_SOUTH_WEST);
                directions.add(Maze.Direction.SOUTH_WEST);
                directions.add(Maze.Direction.NORTH_EAST_SOUTH);
                directions.add(Maze.Direction.NORTH_EAST_SOUTH_WEST);
                directions.add(Maze.Direction.NORTH_EAST_SOUTH_WEST);
                directions.add(Maze.Direction.NORTH_EAST_SOUTH_WEST);
                directions.add(Maze.Direction.NORTH_EAST_SOUTH_WEST);
                directions.add(Maze.Direction.NORTH_SOUTH_WEST);
                directions.add(Maze.Direction.NORTH_SOUTH);
                directions.add(Maze.Direction.NORTH_SOUTH);
                directions.add(Maze.Direction.NORTH_SOUTH);
                directions.add(Maze.Direction.NORTH_SOUTH);
                directions.add(Maze.Direction.NORTH_SOUTH);
                directions.add(Maze.Direction.NORTH_SOUTH);
                directions.add(Maze.Direction.NORTH_SOUTH);
                directions.add(Maze.Direction.NORTH_SOUTH);
                directions.add(Maze.Direction.NORTH_SOUTH);
                directions.add(Maze.Direction.NORTH_SOUTH);
                directions.add(Maze.Direction.NORTH_SOUTH);
                directions.add(Maze.Direction.NORTH_SOUTH);
                directions.add(Maze.Direction.NORTH);
                directions.add(Maze.Direction.NORTH);
                directions.add(Maze.Direction.NORTH);
                directions.add(Maze.Direction.NORTH);
                directions.add(Maze.Direction.NORTH);
                directions.add(Maze.Direction.NORTH);

                System.out.println(directions.size());

                Maze maze = new DefaultMaze(5, 6, directions);

                MazeGui frame = new MazeGui(maze);
                frame.addClickListener(null);
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            
        );
    

    public interface Maze 

        enum Direction 
            EAST_SOUTH("EastSouth.png"), EAST_SOUTH_WEST("EastSouthWest.png"), SOUTH_WEST("SouthWest.png"),
            NORTH_EAST_SOUTH("NorthEastSouth.png"), NORTH_EAST_SOUTH_WEST("NorthEastSouthWest.png"),
            NORTH_SOUTH_WEST("NorthSouthWest.png"), NORTH_SOUTH("NorthSouth.png"), NORTH("North.png");

            private BufferedImage image;

            private Direction(String name) 
                try 
                    image = ImageIO.read(getClass().getResource("/images/" + name));
                 catch (IOException ex) 
                    Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
                
            

            public BufferedImage getImage() 
                return image;
            

        

        public int getRows();

        public int getColumns();

        public Direction getRoomDirections(int index);
    

    public class DefaultMaze implements Maze 

        int rows;
        int columns;

        private List<Direction> directions;

        public DefaultMaze(int rows, int columns, List<Direction> directions) 
            this.rows = rows;
            this.columns = columns;
            this.directions = directions;
        

        public int getRows() 
            return rows;
        

        public int getColumns() 
            return columns;
        

        @Override
        public Direction getRoomDirections(int index) 
            return directions.get(index);
        
    

    // Missing code
    public interface DungeonController 
    

    public class MazeGui extends JFrame 

        private final Board board;

        public MazeGui(Maze m) 
            this.setSize(600, 600);
            this.setResizable(false);

            this.board = new Board(m);
            JScrollPane scroller = new JScrollPane(board);
            this.add(scroller, BorderLayout.CENTER);

            setTitle("Dungeon Escape");
        

        public Board getBoard() 
            return board;
        

        public void addClickListener(DungeonController listener) 
            Board board = getBoard();
            board.addMouseMotionListener(new MouseAdapter() 
                @Override
                public void mouseMoved(MouseEvent e) 
                    board.highlightCellAt(e.getPoint());
                
            );
        

        private class Board extends JPanel 

            private Maze maze;
            private CellPane lastHighlightedCell = null;

            public Board(Maze maze) 
                this.maze = maze;
                setLayout(new GridBagLayout());
                GridBagConstraints gbc = new GridBagConstraints();
                gbc.gridx = 0;
                gbc.gridy = 0;

                for (int index = 0; index < maze.getRows() * maze.getColumns(); index++) 
                    Maze.Direction direction = maze.getRoomDirections(index);
                    // Could use direction directly
                    CellPane cellPane = new CellPane(direction.getImage());
                    cellPane.setName(direction.name());
                    add(cellPane, gbc);
                    gbc.gridx++;
                    if (gbc.gridx >= maze.getColumns()) 
                        gbc.gridx = 0;
                        gbc.gridy++;
                    
                
            

            public void highlightCellAt(Point p) 
                Component component = getComponentAt(p);
                if (component instanceof CellPane) 
                    CellPane cell = (CellPane) component;
                    cell.setHighlighted(true);
                    if (lastHighlightedCell != null && cell != lastHighlightedCell) 
                        lastHighlightedCell.setHighlighted(false);
                    
                    lastHighlightedCell = cell;
                
            
        
    

    public class CellPane extends JPanel 

        private BufferedImage image;
        private boolean highlighted;

        public CellPane(BufferedImage image) 
            this.image = image;
        

        @Override
        public Dimension getPreferredSize() 
            BufferedImage image = getImage();
            return image == null ? new Dimension(128, 128) : new Dimension(image.getWidth(), image.getHeight());
        

        public boolean isHighlighted() 
            return highlighted;
        

        public void setHighlighted(boolean highlighted) 
            this.highlighted = highlighted;
            repaint();
        

        public BufferedImage getImage() 
            return image;
        

        @Override
        protected void paintComponent(Graphics g) 
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.drawImage(image, 0, 0, this);
            if (isHighlighted()) 
                g2d.setColor(new Color(0, 0, 255, 128));
                g2d.fillRect(0, 0, getWidth(), getHeight());
            
            g2d.dispose();
        

    

另一种方法...

另一种方法可能是利用GridBagLayout。您可以获取用于布局给定组件的约束,然后重新使用它们将“覆盖”面板应用到同一位置。

这意味着您可以保留JLabel 用于显示迷宫方向并使用“叠加”组件来提供不同的亮点

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

public class Test 

    public static void main(String[] args) 
        new Test();
    

    public Test() 
        EventQueue.invokeLater(new Runnable() 
            @Override
            public void run() 
                List<Maze.Direction> directions = new ArrayList<>(32);
                directions.add(Maze.Direction.EAST_SOUTH);
                directions.add(Maze.Direction.EAST_SOUTH_WEST);
                directions.add(Maze.Direction.EAST_SOUTH_WEST);
                directions.add(Maze.Direction.EAST_SOUTH_WEST);
                directions.add(Maze.Direction.EAST_SOUTH_WEST);
                directions.add(Maze.Direction.SOUTH_WEST);
                directions.add(Maze.Direction.NORTH_EAST_SOUTH);
                directions.add(Maze.Direction.NORTH_EAST_SOUTH_WEST);
                directions.add(Maze.Direction.NORTH_EAST_SOUTH_WEST);
                directions.add(Maze.Direction.NORTH_EAST_SOUTH_WEST);
                directions.add(Maze.Direction.NORTH_EAST_SOUTH_WEST);
                directions.add(Maze.Direction.NORTH_SOUTH_WEST);
                directions.add(Maze.Direction.NORTH_SOUTH);
                directions.add(Maze.Direction.NORTH_SOUTH);
                directions.add(Maze.Direction.NORTH_SOUTH);
                directions.add(Maze.Direction.NORTH_SOUTH);
                directions.add(Maze.Direction.NORTH_SOUTH);
                directions.add(Maze.Direction.NORTH_SOUTH);
                directions.add(Maze.Direction.NORTH_SOUTH);
                directions.add(Maze.Direction.NORTH_SOUTH);
                directions.add(Maze.Direction.NORTH_SOUTH);
                directions.add(Maze.Direction.NORTH_SOUTH);
                directions.add(Maze.Direction.NORTH_SOUTH);
                directions.add(Maze.Direction.NORTH_SOUTH);
                directions.add(Maze.Direction.NORTH);
                directions.add(Maze.Direction.NORTH);
                directions.add(Maze.Direction.NORTH);
                directions.add(Maze.Direction.NORTH);
                directions.add(Maze.Direction.NORTH);
                directions.add(Maze.Direction.NORTH);

                System.out.println(directions.size());

                Maze maze = new DefaultMaze(5, 6, directions);

                MazeGui frame = new MazeGui(maze);
                frame.addClickListener(null);
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            
        );
    

    public interface Maze 

        enum Direction 
            EAST_SOUTH("EastSouth.png"), EAST_SOUTH_WEST("EastSouthWest.png"), SOUTH_WEST("SouthWest.png"),
            NORTH_EAST_SOUTH("NorthEastSouth.png"), NORTH_EAST_SOUTH_WEST("NorthEastSouthWest.png"),
            NORTH_SOUTH_WEST("NorthSouthWest.png"), NORTH_SOUTH("NorthSouth.png"), NORTH("North.png");

            private BufferedImage image;

            private Direction(String name) 
                try 
                    image = ImageIO.read(getClass().getResource("/images/" + name));
                 catch (IOException ex) 
                    Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
                
            

            public BufferedImage getImage() 
                return image;
            

        

        public int getRows();

        public int getColumns();

        public Direction getRoomDirections(int index);
    

    public class DefaultMaze implements Maze 

        int rows;
        int columns;

        private List<Direction> directions;

        public DefaultMaze(int rows, int columns, List<Direction> directions) 
            this.rows = rows;
            this.columns = columns;
            this.directions = directions;
        

        public int getRows() 
            return rows;
        

        public int getColumns() 
            return columns;
        

        @Override
        public Direction getRoomDirections(int index) 
            return directions.get(index);
        
    

    // Missing code
    public interface DungeonController 
    

    public class MazeGui extends JFrame 

        // Missing code
        public interface DungeonController 
        

        private final Board board;

        public MazeGui(Maze m) 
            this.setSize(600, 600);
            this.setResizable(false);

            this.board = new Board(m);
            JScrollPane scroller = new JScrollPane(board);
            this.add(scroller, BorderLayout.CENTER);

            setTitle("Dungeon Escape");
        

        public Board getBoard() 
            return board;
        

        public void addClickListener(DungeonController listener) 
            Board board = getBoard();
            board.addMouseListener(new MouseAdapter() 
                @Override
                public void mouseClicked(MouseEvent e) 
                    board.highlightCellAt(e.getPoint());
                
            );
        

        private class Board extends JPanel 

            private Maze maze;
            private HighlighPane highlightPane = new HighlighPane();

            public Board(Maze maze) 
                this.maze = maze;
                setLayout(new GridBagLayout());
                GridBagConstraints gbc = new GridBagConstraints();
                gbc.gridx = 0;
                gbc.gridy = 0;

                for (int index = 0; index < maze.getRows() * maze.getColumns(); index++) 
                    Maze.Direction direction = maze.getRoomDirections(index);
                    JLabel label = new JLabel(new ImageIcon(direction.getImage()));
                    label.setName(direction.name());
                    add(label, gbc);
                    gbc.gridx++;
                    if (gbc.gridx >= maze.getColumns()) 
                        gbc.gridx = 0;
                        gbc.gridy++;
                    
                
            

            public void highlightCellAt(Point point) 
                Component component = getComponentAt(point);
                remove(highlightPane);
                if (component != null) 
                    GridBagLayout layout = (GridBagLayout) getLayout();
                    GridBagConstraints gbc = layout.getConstraints(component);
                    gbc.fill = gbc.BOTH;
                    add(highlightPane, gbc, 0);
                
                revalidate();
                repaint(); 
            
        
    

    public class HighlighPane extends JPanel 

        private Color highlight = new Color(0, 0, 255, 128);

        public HighlighPane() 
            setOpaque(false);
        

        @Override
        protected void paintComponent(Graphics g) 
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.setColor(highlight);
            g2d.fillRect(0, 0, getWidth(), getHeight());
            g2d.dispose();
        

    

“MCVE”的修改

这是对您的代码的另一种修改。这向我强调了您没有花时间阅读Performing Custom Painting,尤其是A Closer Look at the Paint Mechanism,它突出了绘制方法链接在一起的顺序。

基本上paint

paintComponent paintBorder paintChildren

这里需要注意的重要一点是,paintComponent 在绘制任何子组件之前被称为 FIRST。您还需要注意,子组件完全有可能在不涉及父组件的情况下进行绘制。

Sooo,在设计“突出显示”或“叠加”解决方案时,您需要牢记这一点,这就是为什么第一个建议是取消 JLabel 并自己做所有事情的原因。

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import ***.Test.ReadOnlyModel;

public class Test 

    public static void main(String[] args) 
        new Test();
    

    public Test() 
        EventQueue.invokeLater(new Runnable() 
            @Override
            public void run() 

                List<List<String>> directions = new ArrayList<>(32);

                List<String> row = new ArrayList<>();
                row.add("EastSouth");
                row.add("EastSouthWest");
                row.add("EastSouthWest");
                row.add("EastSouthWest");
                row.add("EastSouthWest");
                row.add("SouthWest");
                directions.add(row);

                row = new ArrayList<>();
                row.add("NorthEastSouth");
                row.add("NorthEastSouthWest");
                row.add("NorthEastSouthWest");
                row.add("NorthEastSouthWest");
                row.add("NorthEastSouthWest");
                row.add("NorthSouthWest");
                directions.add(row);

                row = new ArrayList<>();
                row.add("NorthSouth");
                row.add("NorthSouth");
                row.add("NorthSouth");
                row.add("NorthSouth");
                row.add("NorthSouth");
                row.add("NorthSouth");
                directions.add(row);

                row = new ArrayList<>();
                row.add("NorthSouth");
                row.add("NorthSouth");
                row.add("NorthSouth");
                row.add("NorthSouth");
                row.add("NorthSouth");
                row.add("NorthSouth");
                directions.add(row);

                row = new ArrayList<>();
                row.add("North");
                row.add("North");
                row.add("North");
                row.add("North");
                row.add("North");
                row.add("North");
                directions.add(row);

                System.out.println(directions.size());

                DefaultModel maze = new DefaultModel(5, 6, directions);

                TestGUI frame = new TestGUI(maze);
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            
        );
    

    public interface ReadOnlyModel 

        public int getRows();

        public int getColumns();

        public String getDirectionAt(int row, int column);

        public Image getImageFor(String direction);
    

    public class DefaultModel implements ReadOnlyModel 

        int rows;
        int columns;

        private List<List<String>> directions;

        public DefaultModel(int rows, int columns, List<List<String>> directions) 
            this.rows = rows;
            this.columns = columns;
            this.directions = directions;
        

        public int getRows() 
            return rows;
        

        public int getColumns() 
            return columns;
        

        @Override
        public String getDirectionAt(int row, int column) 
            return directions.get(row).get(column);
        

        @Override
        public Image getImageFor(String direction) 
            try 
                return ImageIO.read(getClass().getResource(String.format("/images/%s.png", direction)));
             catch (IOException ex) 
                System.out.println(direction);
                ex.printStackTrace();
            
            return null;
        

    

    public class TestGUI extends JFrame 

        private final Board board;

        public TestGUI(ReadOnlyModel m) 

            this.setSize(600, 600);
            this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            this.setResizable(false);

            this.board = new Board(m);
            JScrollPane scroller = new JScrollPane(board);
            this.add(scroller, BorderLayout.CENTER);
        

        private class Board extends JPanel 

            public Board(ReadOnlyModel m) 

                setLayout(new GridBagLayout());
                GridBagConstraints gbc = new GridBagConstraints();
                gbc.gridx = 0;
                gbc.gridy = 0;

                int counter = 0;
                for (int row = 0; row < m.getRows(); row++) 
                    for (int col = 0; col < m.getColumns(); col++) 
                        String direction = m.getDirectionAt(row, col);
                        Image image = m.getImageFor(direction);
                        Tile tile = new Tile(direction, image);
                        add(tile, gbc);
                        gbc.gridx++;
                        counter++;
                        if (counter % 2 == 0) 
                            tile.setHighlighted(true);
                        
                    
                    counter++;
                    gbc.gridx = 0;
                    gbc.gridy++;
                

            

            private class Tile extends JPanel 

                private String direction;
                private Color highlight = new Color(0, 0, 255, 128);
                private Image image;

                private boolean highlighted = false;

                public Tile(String direction, Image image) 
                    this.direction = direction;
                    setName(direction);
                    setOpaque(false);
                    this.image = image;
                

                @Override
                public Dimension getPreferredSize() 
                    Image image = getImage();
                    return image == null ? new Dimension(128, 128) : new Dimension(image.getWidth(this), image.getHeight(this));
                

                public void setHighlighted(boolean highlighted) 
                    this.highlighted = highlighted;
                

                public boolean isHighlighted() 
                    return highlighted;
                

                public Image getImage() 
                    return image;
                

                public Color getHighlight() 
                    return highlight;
                

                @Override
                public void paintComponent(Graphics g) 
                    super.paintComponent(g);
                    Graphics2D g2d = (Graphics2D) g.create();

                    Image image = getImage();
                    if (image != null) 
                        g2d.drawImage(image, 0, 0, this);
                    

                    if (isHighlighted()) 
                        g2d.setColor(highlight);
                        g2d.fillRect(0, 0, getWidth(), getHeight());
                    
                    g2d.dispose();
                

            

//            @Override
//            public void refresh() 
//
//                this.repaint();
//            
//
//            @Override
//            public void makeVisible() 
//
//                this.setVisible(true);
//
//            
        
    

【讨论】:

我将您推荐的更改添加到我的代码中,以尝试突出显示每个 Tile 面板。它似乎没有用。我认为有两个课程,一个有亮点,一个没有,作为一种解决方案。然后我可以使用逻辑将适当的类添加到 Board Jpanel。 @Nova 一般来说,如果它不适合您,那么我建议您实施解决方案的方式有问题。我现在有 3 个可运行的示例,所有这些都有效 @Nova 您需要提供minimal reproducible example,我们才能为您提供更多的存在 好的,只提供了一个!我只是没有图片。 @Nova 好的,只是提供了一个! - 这不是 MRE,你忽略了我提供的每一个建议。您还没有学会如何进行基本的绘画,并且正在尝试编写一个完整的应用程序。忘记尝试使用 64 个图块编写整个迷宫应用程序,并学习如何创建一个简单的图块,您可以在其中控制自定义绘画。您甚至不需要图像来测试它。您所需要的只是一个使用自定义绘画扩展 JLabel 的 Tile 类。这里的解决方案太复杂了,因为您甚至没有自定义绘画的基础知识。在跑步之前先学会走路。

以上是关于如何突出显示主 JPanel 中的特定子面板?的主要内容,如果未能解决你的问题,请参考以下文章

jpanel 中 jlabels 的搜索栏

突出显示 JTextArea 中的一个特定行/行

如何突出显示在 div 中的字符串中的特定文本?

我们如何在 ext js 4.2 中突出显示网格面板的行和列?

Sharepoint Online 突出显示的内容 Web 部件 - 显示文件子文件夹 CAML 查询

如何避免以特定符号开头的行中字符串的文本突出显示[java]