永远不会调用paintComponent()
Posted
技术标签:
【中文标题】永远不会调用paintComponent()【英文标题】:paintComponent() Is Never Called 【发布时间】:2021-04-15 23:05:24 【问题描述】:在完善我的程序的过程中,我不可避免地打破了一些东西。以前,我的迷宫画得很漂亮,但现在从不调用 paintComponent()(根据 sys-out 调试文本)。我已经让其他元素可以很好地改变可见性,但是当mazep
设置为可见时,它们从不绘画。任何帮助将不胜感激 - 我可能只是盯着它太久才发现问题。
GUI.java
package com.whatever;
import javax.swing.*;
import com.whatever.models.Maze;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class GUI extends JFrame
private static final long serialVersionUID = 1L;
public GUI()
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(1000, 500);
JPanel startp = new JPanel();
MazePanel mazep1 = new MazePanel();
mazep1.setMaze(Maze.Maze1);
add(mazep1);
mazep1.setVisible(true);
MazePanel mazep2 = new MazePanel();
mazep2.setMaze(Maze.Maze2);
add(mazep2, BorderLayout.CENTER);
mazep2.setVisible(false);
MazePanel mazep3 = new MazePanel();
mazep3.setMaze(Maze.Maze3);
add(mazep3, BorderLayout.CENTER);
mazep3.setVisible(false);
JMenuBar menuBar = new JMenuBar();
JMenuItem reset = new JMenuItem("Reset");
JMenuItem back = new JMenuItem("Return");
menuBar.add(reset);
reset.addActionListener(new ActionListener()
public void actionPerformed(ActionEvent evt)
System.out.println("Reset has been pushed!");
mazep1.setMaze(Maze.Maze1);
mazep2.setMaze(Maze.Maze2);
mazep3.setMaze(Maze.Maze3);
);
menuBar.add(Box.createHorizontalGlue());
menuBar.add(back);
back.addActionListener(new ActionListener()
public void actionPerformed(ActionEvent evt)
System.out.println("Back to the main screen!");
menuBar.setVisible(false);
startp.setVisible(true);
mazep1.setVisible(false);
mazep2.setVisible(false);
mazep3.setVisible(false);
);
setJMenuBar(menuBar);
menuBar.setVisible(false);
startp.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
Label title = new Label("Heaven & Earth");
title.setAlignment(Label.CENTER);
c.gridx = 0;
c.gridy = 0;
startp.add(title, c);
JButton easy = new JButton("Easy");
c.gridy = 1;
startp.add(easy, c);
easy.addActionListener(new ActionListener()
public void actionPerformed(ActionEvent evt)
System.out.println("To the easy maze!");
menuBar.setVisible(true);
mazep1.setVisible(true);
startp.setVisible(false);
mazep2.setVisible(false);
mazep3.setVisible(false);
);
JButton medium = new JButton("Medium");
c.gridy = 2;
startp.add(medium, c);
medium.addActionListener(new ActionListener()
public void actionPerformed(ActionEvent evt)
System.out.println("To the medium maze!");
menuBar.setVisible(true);
mazep2.setVisible(true);
startp.setVisible(false);
mazep1.setVisible(false);
mazep3.setVisible(false);
);
JButton hard = new JButton("Hard");
c.gridy = 3;
startp.add(hard, c);
hard.addActionListener(new ActionListener()
public void actionPerformed(ActionEvent evt)
System.out.println("To the hard maze!");
menuBar.setVisible(true);
mazep3.setVisible(true);
startp.setVisible(false);
mazep1.setVisible(false);
mazep2.setVisible(false);
);
startp.setVisible(true);
add(startp);
setVisible(true);
class MazePanel extends JPanel
private static final long serialVersionUID = 1L;
private static char[][] maze = null;
private static int x1, y1, x2, y2 = 0;
public void setMaze(char[][] maze)
String type = null;
if (maze.equals(Maze.Maze1))
type = "easy";
else if (maze.equals(Maze.Maze2))
type = "medium";
else if (maze.equals(Maze.Maze3))
type = "hard";
System.out.println("I've set the " + type + " maze!");
this.maze = maze;
boolean first = true;
for(int i = 0; i < maze.length; i++)
for(int j = 0; j < maze[i].length; j++)
if(maze[i][j] == 's' && first)
x1 = j;
y1 = i;
first = false;
else if(maze[i][j] == 's' && !first)
x2 = j;
y2 = i;
if (maze[i][j] == 0)
//System.out.print(maze[i][j] + " ");
//System.out.println();
@Override
public Dimension getPreferredSize()
return new Dimension(1000, 500);
@Override
protected void paintComponent(Graphics g)
super.paintComponent(g);
System.out.println("Painting now!");
final int HOROFF = 250;
final int VEROFF = 50;
for(int i = 0; i < maze.length; i++)
for(int j = 0; j < maze[i].length; j++)
if(maze[i][j] == 1)
g.setColor(Color.BLACK);
g.fillRect(j * 25 + HOROFF, i * 25 + VEROFF, 25, 25);
else if((i == y1 && j == x1) || (i == y2 && j == x2))
g.setColor(Color.BLUE);
g.fillRect(j * 25 + HOROFF, i * 25 + VEROFF, 25, 25);
else if(maze[i][j] == 'e')
g.setColor(Color.WHITE);
g.fillRect(j * 25 + HOROFF, i * 25 + VEROFF, 25, 25);
g.setColor(Color.BLACK);
g.drawRect(HOROFF, VEROFF, maze[0].length * 25, maze.length * 25);
迷宫.java
import java.awt.Panel;
public class Maze extends Panel
private static final long serialVersionUID = 1L;
public static char[][] Maze1 =
0,0,0,0,0,0,0,'e',1,0,1,0,0,0,0,0,'e',
0,1,0,1,1,1,1,0,1,0,1,0,1,1,1,1,1,
0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,
0,1,1,1,1,1,1,0,1,0,1,1,1,1,1,1,0,
0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,
0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,
0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,
0,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,0,
0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,
0,1,1,1,1,1,1,0,1,0,1,1,1,1,1,1,0,
0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,
1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,0,
's',0,0,0,0,0,0,0,1,'s',0,0,0,0,0,0,0
;
public static char[][] Maze2 =
0,0,0,0,0,0,0,0,1,'e',1,0,0,0,0,0,0,0,0,0,'e',
0,0,0,1,0,0,0,1,0,0,1,0,1,1,0,0,0,1,0,1,0,
0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,
0,1,0,0,0,1,0,1,0,1,1,1,0,0,0,0,0,1,0,1,0,
0,0,0,0,1,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,
0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,1,0,
0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,
1,0,1,0,0,0,0,0,1,0,1,0,0,0,0,1,0,1,0,0,0,
0,0,0,0,1,0,0,0,0,0,1,0,0,1,0,0,0,0,0,1,0,
0,1,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,
's',0,0,0,0,0,0,0,0,1,1,'s',0,0,1,0,0,0,0,0,0
;
public static char[][] Maze3 =
0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,
0,1,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,1,0,1,0,0,
0,0,0,0,1,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,
0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,1,0,1,0,
1,0,0,0,0,1,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,
1,0,0,1,0,0,0,1,0,'s',1,'s',1,0,0,0,0,1,1,0,1,0,
0,0,0,0,0,1,0,0,0,1,'e',0,'e',1,0,0,0,0,0,0,0,1,
0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,1,0,0,
0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,
1,0,0,1,0,0,0,1,0,0,0,0,1,0,1,0,0,1,0,0,0,0,
0,0,0,0,1,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,1,0,
1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0
;
【问题讨论】:
在这种情况下使用static
将为MazePanel
的每个实例呈现相同的迷宫数据
每次更改组件树时都要记住repaint 和revalidate。在这种情况下,您可以在所有这些 ActionListener 中执行此操作。
我也会考虑看看CardLayout
JFrame
默认使用BorderLayout
,这只会管理/布局添加到每个可用位置的最后一个组件 - 因此,这意味着,实际布局的唯一组件是面板包含startp
,所有其他组件都保留在原始大小 0x0 并且 Swing 足够聪明,不会绘制没有大小的组件
【参考方案1】:
JFrame
默认使用BorderLayout
,这只会管理/布局添加到每个可用位置的最后一个组件 - 因此,这意味着,实际布局的唯一组件是startp
面板,所有其他组件保持原始大小为 0x0,Swing 足够聪明,不会绘制没有大小的组件。
更好的解决方案是使用 CardLayout
旨在完全按照您的要求进行操作。
例如...
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Label;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
public class GUI extends JFrame
private static final long serialVersionUID = 1L;
public static void main(String[] args)
EventQueue.invokeLater(new Runnable()
@Override
public void run()
JFrame frame = new GUI();
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
);
private CardLayout cardLayout = new CardLayout();
public GUI()
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(1000, 500);
setLayout(cardLayout);
JPanel startp = new JPanel();
MazePanel mazep1 = new MazePanel();
mazep1.setMaze(Maze.Maze1);
add(mazep1, "easyMaze");
MazePanel mazep2 = new MazePanel();
mazep2.setMaze(Maze.Maze2);
add(mazep2, "medMaze");
MazePanel mazep3 = new MazePanel();
mazep3.setMaze(Maze.Maze3);
add(mazep3, "hardMaze");
JMenuBar menuBar = new JMenuBar();
JMenuItem reset = new JMenuItem("Reset");
JMenuItem back = new JMenuItem("Return");
menuBar.add(reset);
reset.addActionListener(new ActionListener()
public void actionPerformed(ActionEvent evt)
System.out.println("Reset has been pushed!");
mazep1.setMaze(Maze.Maze1);
mazep2.setMaze(Maze.Maze2);
mazep3.setMaze(Maze.Maze3);
);
menuBar.add(Box.createHorizontalGlue());
menuBar.add(back);
back.addActionListener(new ActionListener()
public void actionPerformed(ActionEvent evt)
System.out.println("Back to the main screen!");
cardLayout.show(getContentPane(), "startup");
menuBar.setVisible(false);
);
setJMenuBar(menuBar);
menuBar.setVisible(false);
startp.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
Label title = new Label("Heaven & Earth");
title.setAlignment(Label.CENTER);
c.gridx = 0;
c.gridy = 0;
startp.add(title, c);
JButton easy = new JButton("Easy");
c.gridy = 1;
startp.add(easy, c);
easy.addActionListener(new ActionListener()
public void actionPerformed(ActionEvent evt)
System.out.println("To the easy maze!");
menuBar.setVisible(true);
cardLayout.show(getContentPane(), "easyMaze");
);
JButton medium = new JButton("Medium");
c.gridy = 2;
startp.add(medium, c);
medium.addActionListener(new ActionListener()
public void actionPerformed(ActionEvent evt)
System.out.println("To the medium maze!");
cardLayout.show(getContentPane(), "medMaze");
menuBar.setVisible(true);
);
JButton hard = new JButton("Hard");
c.gridy = 3;
startp.add(hard, c);
hard.addActionListener(new ActionListener()
public void actionPerformed(ActionEvent evt)
System.out.println("To the hard maze!");
cardLayout.show(getContentPane(), "hardMaze");
menuBar.setVisible(true);
);
add(startp, "startup");
cardLayout.show(getContentPane(), "startup");
//setVisible(true);
static class MazePanel extends JPanel
private final long serialVersionUID = 1L;
private char[][] maze = null;
private int x1, y1, x2, y2 = 0;
public void setMaze(char[][] maze)
String type = null;
if (maze.equals(Maze.Maze1))
type = "easy";
else if (maze.equals(Maze.Maze2))
type = "medium";
else if (maze.equals(Maze.Maze3))
type = "hard";
System.out.println("I've set the " + type + " maze!");
this.maze = maze;
boolean first = true;
for (int i = 0; i < maze.length; i++)
for (int j = 0; j < maze[i].length; j++)
if (maze[i][j] == 's' && first)
x1 = j;
y1 = i;
first = false;
else if (maze[i][j] == 's' && !first)
x2 = j;
y2 = i;
if (maze[i][j] == 0)
//System.out.print(maze[i][j] + " ");
//System.out.println();
@Override
public Dimension getPreferredSize()
return new Dimension(1000, 500);
@Override
protected void paintComponent(Graphics g)
super.paintComponent(g);
System.out.println("Painting now!");
final int HOROFF = 250;
final int VEROFF = 50;
for (int i = 0; i < maze.length; i++)
for (int j = 0; j < maze[i].length; j++)
if (maze[i][j] == 1)
g.setColor(Color.BLACK);
g.fillRect(j * 25 + HOROFF, i * 25 + VEROFF, 25, 25);
else if ((i == y1 && j == x1) || (i == y2 && j == x2))
g.setColor(Color.BLUE);
g.fillRect(j * 25 + HOROFF, i * 25 + VEROFF, 25, 25);
else if (maze[i][j] == 'e')
g.setColor(Color.WHITE);
g.fillRect(j * 25 + HOROFF, i * 25 + VEROFF, 25, 25);
g.setColor(Color.BLACK);
g.drawRect(HOROFF, VEROFF, maze[0].length * 25, maze.length * 25);
public static class Maze
private static final long serialVersionUID = 1L;
public static char[][] Maze1 =
0, 0, 0, 0, 0, 0, 0, 'e', 1, 0, 1, 0, 0, 0, 0, 0, 'e',
0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1,
0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0,
0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0,
's', 0, 0, 0, 0, 0, 0, 0, 1, 's', 0, 0, 0, 0, 0, 0, 0
;
public static char[][] Maze2 =
0, 0, 0, 0, 0, 0, 0, 0, 1, 'e', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'e',
0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0,
0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0,
0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0,
0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0,
0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
's', 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 's', 0, 0, 1, 0, 0, 0, 0, 0, 0
;
public static char[][] Maze3 =
0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0,
0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0,
1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 1, 0, 0, 0, 1, 0, 's', 1, 's', 1, 0, 0, 0, 0, 1, 1, 0, 1, 0,
0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 'e', 0, 'e', 1, 0, 0, 0, 0, 0, 0, 0, 1,
0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0,
1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0,
0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0,
1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
;
另外,在MazePanel
中使用static
是不可取的,因为这意味着MazePanel
的每个实例都将具有相同的数据
【讨论】:
以上是关于永远不会调用paintComponent()的主要内容,如果未能解决你的问题,请参考以下文章
Java - 方法 repaint() 不调用 paintComponent() 方法