gpt4 book ai didi

java - 在 Swing 中更新 JLabel 中的图像图标?使用 revalidate() 和 repaint() 但不起作用

转载 作者:行者123 更新时间:2023-11-30 06:07:28 24 4
gpt4 key购买 nike

好吧,我刚刚习惯 OOP,并且正在学习 swing。我正在制作一个简单的应用程序,它是由 4 个图像(一个 X、一个 O、一个正方形和一个三角形)组成的 2x2 网格,单击任意一个图像会将颜色的形状切换为蓝色。

虽然我无法让它切换到新图像,但我认为这与我的程序的一些基本内容有关。

介意看一下吗?

JFrame 类:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.ImageIcon;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import java.io.File;
import java.io.IOException;
import javax.swing.JPanel;

public class Frame1 {

public JFrame frame;

Frame1 window = new Frame1();
window.frame.setVisible(true);

}

public Frame1() {
initialize();
}

private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 900, 900);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);

Squares x = new Squares("images\\black-X.png", "images\\blue-X.png", 0, 0, 450, 450, "x");
Squares o = new Squares("images\\black-O.png", "images\\blue-O.png", 450, 0, 450, 450, "o");
Squares sq = new Squares("images\\black-sq.png", "images\\blue-sq.png", 0, 425, 450, 450, "sq");
Squares tri = new Squares("images\\black-tri.png", "images\\blue-tri.png", 450, 410, 450, 450, "tri");


frame.getContentPane().add(x.getLabel());
frame.getContentPane().add(o.getLabel());
frame.getContentPane().add(sq.getLabel());
frame.getContentPane().add(tri.getLabel());
}


}

鼠标监听器类:

import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

public class clickListener implements MouseListener{

Squares ob = new Squares();

public clickListener(Squares newSquare) {
ob = newSquare;
}

public void mouseClicked(MouseEvent e) {
ob.changePic();
}

}

然后我为每个图像创建一个对象类

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

public class Squares {

String pic1, pic2, name;
int x, y, width, height;

JPanel panel = new JPanel();
JLabel label = new JLabel();

public Squares() {
;
}

public Squares(String pic1, String pic2, int x, int y, int width, int height, String name) {
this.pic1 = pic1;
this.pic2 = pic2;
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.name = name;

BufferedImage myPic1 = null;

try {
myPic1 = ImageIO.read(new File(pic1));

} catch (IOException ex) {System.out.println("error in image upload");}

/*
panel.setBounds(x, y, width, height);
panel.add(new JLabel(new ImageIcon(myPic1)));
panel.addMouseListener(new clickListener(this));
*/

label = new JLabel(new ImageIcon(myPic1));
label.setBounds(x, y, width, height);
label.addMouseListener(new clickListener(this));
}

public JLabel getLabel() {
return label;
}

public String getName() {
return this.name;
}

public void changePic() {
JOptionPane.showMessageDialog(null, "change pic reached for " + this.name);
BufferedImage myPic2 = null;
try {myPic2 = ImageIO.read(new File(pic2));}
catch(IOException ex) {System.out.println("error in image upload");}
label = new JLabel(new ImageIcon(myPic2));
label.setBounds(x, y, width, height);
label.repaint();
label.revalidate();
}
}

我最初使用包含每个 JLabel 的 JPanel,但为了简化事情,我将它们全部删除。

所以,是的,任何建议都会受到赞赏。谢谢!

最佳答案

所以“核心”问题在于您的 changePic 方法

public void changePic() {
JOptionPane.showMessageDialog(null, "change pic reached for " + this.name);
BufferedImage myPic2 = null;
try {
myPic2 = ImageIO.read(new File(pic2));
} catch (IOException ex) {
System.out.println("error in image upload");
}
label = new JLabel(new ImageIcon(myPic2));
label.setBounds(x, y, width, height);
label.repaint();
label.revalidate();
}

在此方法中,您创建了一个 JLabel 的新实例,但它永远不会添加到附加到屏幕的任何容器中,因此它永远不会显示。

简单的解决方案是简单地更改 JLabel 现有实例的 icon 属性

public void changePic() {
JOptionPane.showMessageDialog(null, "change pic reached for " + this.name);
BufferedImage myPic2 = null;
try {
myPic2 = ImageIO.read(new File(pic2));
} catch (IOException ex) {
System.out.println("error in image upload");
}
label.setIcon(new ImageIcon(pic2));
}

观察结果...

在检查代码时,我发现了一些可以做得更好的事情。

  • (尽管它的名字如此)管理主框架确实不是 Frame1 的责任。通过不同的容器可以更好地管理核心功能,这可以解耦组件,并使其在长期错误中更加灵活和可重用 - 您也不需要在组件中包含框架管理的复杂性和其他职责。
  • 您应该避免 null 布局。更简单的解决方案是使用 GridLayout,因为您提供的实现存在布局问题
  • Squares 不需要知道父容器想要的位置或大小 - 这实际上并不是父容器应该直接做出的决定。相反,Squares 应该向父容器提供大小调整提示,以便它可以就如何布局所有子组件做出更好的决策。 JLabel 本身能够提供此信息。
  • 可以说,Squares 应该从 JLabel 扩展 - 这纯粹是为了简单起见。 JLabel 是显示图像的首选位置,因此它是这项工作的不错选择,但围绕它包装一个类只会使其管理变得更加麻烦,在这种情况下,增加的值(value)非常小。对于组合优于继承达成了一项协议(protocol),但在这种情况下,我不确定它会增加任何更多的值(value)
  • ClickListener 不需要创建 Squares 的实例,它只是构造函数要求任何调用者将 Squares 的实例传递给它不管怎样
  • 由于它的核心功能,如果无法加载任一图像,Squares 就会失败,这将使诊断这些问题变得更加容易,而不是让程序继续在“ splinter ”状态

恕我直言

示例

import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Game {

public static void main(String[] args) {
new Game();
}

public Game() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}

JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new GamePane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (IOException ex) {
ex.printStackTrace();
}
}
});
}

public class GamePane extends JPanel {

public GamePane() throws IOException {
initialize();

}

private void initialize() throws IOException {
Square x = new Square("images\\black-X.png", "images\\blue-X.png", "x");
Square o = new Square("images\\black-O.png", "images\\blue-O.png", "o");
Square sq = new Square("images\\black-sq.png", "images\\blue-sq.png", "sq");
Square tri = new Square("images\\black-tri.png", "images\\blue-tri.png", "tri");

setLayout(new GridLayout(2, 2));

add(x);
add(o);
add(sq);
add(tri);
}

}

public class ClickListener extends MouseAdapter {

private Square ob;

public ClickListener(Square newSquare) {
ob = newSquare;
}

public void mouseClicked(MouseEvent e) {
ob.changePic();
}

}

public class Square extends JLabel {

String name;
private BufferedImage myPic1, myPic2;

public Square(String pic1, String pic2, String name) throws IOException {
this.name = name;

myPic1 = ImageIO.read(new File(pic1));
myPic2 = ImageIO.read(new File(pic2));

setIcon(new ImageIcon(myPic1));
addMouseListener(new ClickListener(this));
}

public String getName() {
return this.name;
}

public void changePic() {
setIcon(new ImageIcon(myPic2));
}
}
}

关于java - 在 Swing 中更新 JLabel 中的图像图标?使用 revalidate() 和 repaint() 但不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51004785/

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