Frame
- > MainContentPane
- > MapPanel
- > Map
- > Tile[]
JFrame
- > JPanel(new GridBagLayout)
- > JPanel
- > JPanel(new GridLayout(31,30)
- > JComponent
我正在尝试在JPanel上绘制32x32像素图块,但无论我在哪里调用repaint();如果我调用validate(),它只会绘制tile。在JFrame上。
如果我绕过Panels并直接绘制(使用draw()方法)到MapPanel
上,只有当我调整大小或移动JFrame
时才会绘制图像,以便框架必须由{重新绘制{ {1}}。但是,在repaintmanager
上调用repaint()
,validate()
或两者都不会绘制图像。
如果我理解Java.swing是如何正确绘制的,如果我在最高级别的Component上调用重绘,它应该重新绘制ContentPanel
认为应该重新绘制的所有子组件。由于我在将帧设置为可见后添加组件,因此我需要在最高级别的Component上调用repaintmanager
来告诉validate()
有新内容。我对这种理解是对的吗?
不起作用的事情:
告诉我在将帧设置为可见之前添加所有组件。 repaintmanager
和Map
将会定期更改,每次添加/删除内容时重置Frame都是非常不切实际的。
Tile[]
编辑:添加最少的代码。 如果我替换validate(); with revalidate();但我不想使用revalidate();如果小组中没有任何内容需要被无效。我是否怀疑这种想法?
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);
}
}
答案 0 :(得分:1)
发布的代码的基本问题是在添加组件之前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);
}
}
}