Java 无法从jpanel中删除组件
我已经重构了我的代码,以生成一个最小的、可复制的示例 问题-我无法从面板中移除卡(我已经在出现问题的代码中进行了注释,请参阅类“ClearCardEventListener”) 完整代码如下 在运行程序之前,需要下载一个映像并将其添加到resources文件夹=Java 无法从jpanel中删除组件,java,swing,oop,jpanel,jcomponent,Java,Swing,Oop,Jpanel,Jcomponent,我已经重构了我的代码,以生成一个最小的、可复制的示例 问题-我无法从面板中移除卡(我已经在出现问题的代码中进行了注释,请参阅类“ClearCardEventListener”) 完整代码如下 在运行程序之前,需要下载一个映像并将其添加到resources文件夹= 运行程序 单击“添加卡”按钮(这将在面板上添加2个红心图像图标) 单击“清除卡”按钮(这就是问题所在,我无法从面板中移除卡) package debug.debug; 导入java.awt.Insets; 导入java.awt.even
package debug.debug;
导入java.awt.Insets;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入java.util.ArrayList;
导入java.util.array;
导入java.util.Collections;
导入java.util.List;
导入javax.swing.ImageIcon;
导入javax.swing.JButton;
导入javax.swing.JFrame;
导入javax.swing.JLabel;
导入javax.swing.JPanel;
公共类应用程序扩展了JFrame{
公共静态void main(字符串[]args){
App App=新App();
Insets Insets=app.getInsets();
应用设置尺寸(300+插图左+插图右,
300+插图。顶部+插图。底部);
}
JPanel小组;
JButton clearCardButton;
JButton addCardButton;
List playerCards=new ArrayList();
甲板=新甲板();
公共应用程序(){
setTitle(“21点游戏”);
setVisible(真);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(空);
panel=新的JPanel();
添加(面板);
panel.setLayout(空);
addCardButton=新JButton(“添加卡”);
clearCardButton=新的JButton(“清除卡”);
面板。添加(添加卡片按钮);
面板。添加(clearCardButton);
addCardButton.addActionListener(新的AddCardEventListener(this,this.deck));
addActionListener(新的ClearCardEventListener(this,this.deck));
addCardButton.setBounds(150,50,addCardButton.getPreferredSize().width,addCardButton.getPreferredSize().height);
clearCardButton.setBounds(150100,clearCardButton.getPreferredSize().width,clearCardButton.getPreferredSize().height);
}
公共JPanel getPanel(){
返回面板;
}
公共作废addPlayerCard(卡片){
玩家卡。添加(卡片);
}
公共列表getPlayerCards(){
返回游戏卡;
}
公共列表getPlayerCardLabels(){
List playerCardLabels=new ArrayList();
对于(int i=0;i问题#1
每次调用Card#getCardLabel
时,它都在创建一个新的JLabel
实例
class Card {
// Hardcoded for debugging, so every card image is a 2 of hearts
public JLabel getCardLabel() {
return new JLabel(new ImageIcon(getClass()
.getResource("/cards/2h.png")));
}
}
这意味着当你这样做的时候
app.getPanel().add(app.getPlayerCards().get(0).getCardLabel()).setBounds(0, 0, 72, 96);
而且
System.out.println("DEBUG: " + app.getPlayerCards().get(0).getCardLabel());
app.getPlayerCards().get(0).getCardLabel().setIcon(null);
app.getPlayerCards().get(0).getCardLabel().revalidate();
app.getPlayerCards().get(0).getCardLabel().repaint();
app.getPanel().remove(app.getPlayerCards().get(0).getCardLabel());
而且
System.out.println("DEBUG: " + app.getPlayerCards().get(0).getCardLabel());
app.getPlayerCards().get(0).getCardLabel().setIcon(null);
app.getPlayerCards().get(0).getCardLabel().revalidate();
app.getPlayerCards().get(0).getCardLabel().repaint();
app.getPanel().remove(app.getPlayerCards().get(0).getCardLabel());
每个调用实际上都是创建JLabel
的新实例,因此屏幕上的调用与您试图修改的调用无关
因此,您的卡#getCardLabel
应该只创建一次JLabel
,这也被称为“延迟加载”
问题2
Swing是惰性的(好吧,它是“优化的”),这意味着添加或删除组件本身不会触发布局或绘制过程。这样做是为了让您可以对UI进行大量更改,而不是让它尝试更新每个更改,这将非常缓慢
这意味着在添加或删除组件时,还应该调用repaint
来触发新的绘制过程(我也建议revalidate
,但您没有使用任何布局管理器,因此它不会对您做任何事)
在app.getPanel()下面添加app.getPanel().repaint()
).remove
call-我还强烈建议使用适当的布局管理器,这将对您有很大帮助。此外,getCardLabel
在每次调用时都会创建一个新的JLabel
,这意味着屏幕上的标签不是您试图移除的标签。通常,Swing组件不应不能从视图中添加或删除。创建一个保存信息的逻辑模型。Swing视图读取逻辑模型。您的控制器类更新逻辑模型并要求视图重新绘制。谢谢,它现在可以工作了!面板上的重新绘制清楚了。
app.getPanel().remove(app.getPlayerCards().get(0).getCardLabel());
app.getPanel().repaint();