Frame
-> MainContentPane
-> MapPanel
-> map
-> Tile[]
JFrame
-> JPanel(new GridBagLayout)
-> JPanel
-> JPanel(new GridLayout(31,30)
-> JComponent
我正在尝试在 JPanel 上绘制 32x32 像素图 block ,但无论我在哪里调用 repaint();如果我调用 validate(),它只会绘制瓷砖;在 JFrame 上。
如果我绕过面板并直接在 MapPanel
上绘制(使用 draw() 方法),则仅当我调整大小或移动 JFrame
以使框架具有由repaintmanager
重新绘制。但是,在我的 ContentPanel
上调用 repaint()
、validate()
或两者都不会绘制图像。
如果我理解 Java.swing 如何正确绘制事物,如果我在最高级别的组件上调用重绘,它应该重新绘制 repaintmanager
认为应该重新绘制的所有子组件。由于我在框架设置为可见后添加组件,因此我需要在最高级别组件上调用 validate()
来告诉 repaintmanager
有新的东西。我的这种理解正确吗?
不起作用的事情:
告诉我在将框架设置为可见之前添加所有组件。 Map
和 Tile[]
会定期更改,每次添加/删除某些内容时都重置 Frame 是非常不切实际的。
public class NetScore {
public static void main(String[] args) {
MapPanel mapPanel = new MapPanel();
InfoPanel infoPanel = new InfoPanel();
ImageLoader imageLoader = new ImageLoader();
Player player = new Player("Tester", imageLoader);
JPanel contentPane = new MainContentPane((JPanel)mapPanel, (JPanel)infoPanel);
System.out.println(mapPanel.getHeight());
System.out.println(mapPanel.getWidth());
MapBuilder mapBuilder = new MapBuilder(player, imageLoader);
Map map = new Map(mapBuilder, mapPanel, player);
map.drawMap();
System.out.println();
}
}
public class MapPanel extends JPanel implements ActionListener{
Map map;
Timer clock;
public MapPanel(){
clock = new Timer(500, this);
clock.start();
}
public void addMap(Map map){
this.map = map;
this.add(map);
this.validate();
}
public void paintComponent(Graphics g){
super.paintComponent(g);
System.out.println(map == null);
System.out.println("paint mapPanel");
Graphics2D g2 = (Graphics2D) g;
if(map == null){
//map.draw(g2);
}
}
@Override
public void actionPerformed(ActionEvent e) {
//repaint();
}
}
public class MainContentPane extends JPanel implements ActionListener{
public JFrame frame;
Timer clock;
public MainContentPane(JPanel mapPanel ,JPanel infoPanel){
clock = new Timer(500, this);
clock.start();
frame = new Frame();
JPanel contentPane = new JPanel();
frame.setContentPane(contentPane);
contentPane.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
c.weightx = 2;
c.gridx = 0;
c.gridy = 0;
c.fill = GridBagConstraints.BOTH;
contentPane.add(mapPanel, c);
c.weightx = 1;
c.weighty = 1;
c.gridx = 1;
c.gridy = 0;
c.fill = GridBagConstraints.BOTH;
contentPane.add(infoPanel, c);
frame.setVisible(true);
}
@Override
public void actionPerformed(ActionEvent e) {
repaint();
}
class Frame extends JFrame{
public Frame(){
this.setTitle("netScore");
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setBounds(100, 10, 1500, 1000);
this.setResizable(false);
}
}
}
public class Map extends JPanel{
private Tile[][] tiles;
private MapBuilder mapBuilder;
private Player player;
public Map(MapBuilder mapBuilder, MapPanel mapPanel, Player player){
this.player = player;
this.mapBuilder = mapBuilder;
this.setLayout(new GridLayout(31,30));
mapPanel.addMap(this);
}
public void loadMap(){
tiles = mapBuilder.buildMap();
}
public void drawMap(){
loadMap();
this.removeAll();
for(int i = 0; i < tiles.length; i++){
for(int p = 0; p < tiles[i].length; p++){
this.add(tiles[i][p]);
}
}
validate();
}
public void draw(Graphics2D g2){
if(tiles != null){
for(int i = 0; i < tiles.length; i++){
for(int p = 0; p <tiles[i].length; p++){
tiles[i][p].draw(g2, i*32, p*32);
}
}
}
}
// private class GlassPanel extends JComponent{
//
//
// @Override
// protected void paintComponent(Graphics g) {
// super.paintComponent(g);
// Graphics2D g2 = (Graphics2D) g;
// g2.drawImage(player.getImage(), player.getX(), player.getY(), null);
//
// }
//
// }
}
public class Tile extends JComponent{
private int id;
private boolean collision;
private BufferedImage image;
public Tile(char diCo, int id, ImageLoader imageLoader){
this.id = id;
collision = (Character.isUpperCase(diCo));
image = imageLoader.getTileImage(id, diCo);
setPreferredSize(new Dimension(32, 32));
}
// public Dimension getPreferredSize(){
// return new Dimension(32,32);
// }
public boolean isCollision() {
return collision;
}
public void draw(Graphics2D g2, int x, int y){
System.out.println("paint tile, id "+ id);
g2.drawImage(image, null, x, y);
}
public void paintComponent(Graphics g){
System.out.println("paint tile, id "+ id);
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.drawImage(image, null, 0, 0);
}
}
编辑:添加了最少的代码。 如果我替换 validate(); 这将起作用使用重新验证();但我不想使用 revalidate();如果面板上没有任何内容需要无效。我的想法正确吗?
public class test {
public static void main(String[] args) throws Exception {
MapPanel mapPanel = new MapPanel();
ContentPanel contentPanel = new ContentPanel((JPanel)mapPanel);
Map map = new Map();
mapPanel.add(map);
map.loadMap();
}
}
class MapPanel extends JPanel{
public MapPanel(){
//this.setBackground(Color.BLACK);
}
}
class Map extends JPanel{
BufferedImage image;
public Map(){
try {
image = ImageIO.read(new File("graphics//brick_brown0.png"));
} catch (IOException e) {
System.err.println("can't find file.");
}
setLayout(new GridLayout(31,30));
setPreferredSize(new Dimension(962,992));
}
public void loadMap(){
for(int i = 0; i < 30; i++){
for(int p = 0; p < 31; p++){
add(new Tile(image));
}
}
validate();
}
}
class Tile extends JComponent{
BufferedImage image;
public Tile(BufferedImage image){
this.image = image;
setPreferredSize(new Dimension(32,32));
}
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.drawImage(image, null, null);
}
}
class ContentPanel extends JPanel implements ActionListener{
Timer clock = new Timer(100, this);
public ContentPanel(JPanel mapPanel){
clock.start();
setLayout(new BorderLayout());
JFrame frame = new Frame();
frame.setContentPane(this);
add(mapPanel);
frame.setVisible(true);
}
@Override
public void actionPerformed(ActionEvent e) {
repaint();
}
private class Frame extends JFrame{
public Frame(){
setDefaultCloseOperation(EXIT_ON_CLOSE);
setBounds(100, 100, 1000, 1000);
}
}
}
最佳答案
发布的代码的基本问题是在添加组件之前将 JFrame
设置为可见。虽然有多种方法可以添加组件并在顶级容器变得可见后使它们可见,但在这种情况下它们似乎没有必要。
这是一个工作版本,它使用运行时生成的图像,在 GridLayout
中留出一点空间来显示网格是 31 x 30 组件。
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
public class TestRepaint {
public static void main(String[] args) throws Exception {
MapPanel mapPanel = new MapPanel();
Map map = new Map();
mapPanel.add(map);
map.loadMap();
new ContentPanel((JPanel) mapPanel);
}
}
class MapPanel extends JPanel {
public MapPanel() {
this.setBackground(Color.RED);
}
}
class Map extends JPanel {
BufferedImage image;
public Map() {
image = new BufferedImage(10, 10, BufferedImage.TYPE_INT_BGR);
setLayout(new GridLayout(31, 30,2,2));
//setPreferredSize(new Dimension(962, 992));
}
public void loadMap() {
for (int i = 0; i < 30; i++) {
for (int p = 0; p < 31; p++) {
add(new Tile(image));
}
}
validate();
}
}
class Tile extends JComponent {
BufferedImage image;
public Tile(BufferedImage image) {
this.image = image;
setPreferredSize(new Dimension(image.getWidth(), image.getHeight()));
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.drawImage(image, null, null);
}
}
class ContentPanel extends JPanel implements ActionListener {
Timer clock = new Timer(100, this);
public ContentPanel(JPanel mapPanel) {
clock.start();
setLayout(new BorderLayout());
JFrame frame = new Frame();
frame.setContentPane(this);
add(mapPanel);
frame.pack();
frame.setVisible(true);
}
@Override
public void actionPerformed(ActionEvent e) {
repaint();
}
private class Frame extends JFrame {
public Frame() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
//setBounds(100, 100, 1000, 1000);
}
}
}
关于java - 除非 JFrame.validate(),否则 JPanel JComponent 不会重新绘制;将组件添加到可见框架后调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43175571/