gpt4 book ai didi

java - 除非 JFrame.validate(),否则 JPanel JComponent 不会重新绘制;将组件添加到可见框架后调用

转载 作者:行者123 更新时间:2023-11-30 06:48:59 25 4
gpt4 key购买 nike

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 有新的东西。我的这种理解正确吗?

不起作用的事情:

告诉我在将框架设置为可见之前添加所有组件。 MapTile[] 会定期更改,每次添加/删除某些内容时都重置 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 组件。

enter image description here

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/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com