在循环中添加 JLayeredPane 后,将显示 JLabel 上的最后一张图像
Last image on JLabel is shown for all after adding JLayeredPane in loop
抱歉标题不好,想不出更好的了。
我正在制作纸牌游戏。
下面的方法将 Card object 作为参数,returns 我将 JLayeredPane 与 JLabel 一起使用,该 JLabel 具有卡片图像。
private JLayeredPane getCardPane(Card card) {
JLayeredPane cardPane = new JLayeredPane();
GridBagLayout gblCardPane = new GridBagLayout();
cardPane.setLayout(gblCardPane);
cardImageIcon = card.getImageIcon();
JLabel lblCard = new JLabel() {
@Override
public void paintComponent(Graphics g) {
g.drawImage(cardImageIcon.getImage(), 0, 0, null);
super.paintComponent(g);
}
};
GridBagConstraints gbcLblCard = new GridBagConstraints();
cardPane.add(lblCard,gbcLblCard);
return cardPane;
}
我有一个像下面这样的部分,将我手中的所有卡片添加到另一个 JLayeredPane jlpMyCards:
for (int i = 0; i < hand.getCardCount(); i++) {
JLayeredPane thisCard = getCardPane(hand.getCard(i));
//JOptionPane.showMessageDialog(null,thisCard);
jlpMyCards.add(thisCard);
}
最后将 jlpMyCards 添加到框架中。
在渲染帧上,我看到所有卡片在手(根据计数),但所有卡片都显示加载的最后一张图像。 - 为什么?
我尝试用
打印卡片
JOptionPane.showMessageDialog(null,thisCard);
弹出对话框显示正确的图像。
注意:我猜 Card class 中的以下方法也可能会造成问题。
public ImageIcon getImageIcon() {
BufferedImage img = null;
try {
img = ImageIO.read(new File(this.getClass().getResource(
getValueAsString().toLowerCase() + "_of_"+
getSuitAsString().toLowerCase() + ".png").toURI()));
//Rescaling Image
Image dimg = img.getScaledInstance(100, 146, Image.SCALE_SMOOTH);
return new ImageIcon(dimg);
} catch (IOException e) {
e.printStackTrace();
} catch (URISyntaxException e) {
e.printStackTrace();
}
return null;
}
在循环的每次迭代中,您将值分配给字段 cardImageIcon
。并且在渲染所有标签时调用 getImage()
(在它们的 paintComponent
方法中)相同的 cardImageIcon
对象(在上次迭代期间设置)。
您可以将其作为局部变量,而不是将其保留为字段:
final ImageIcom cardImageIcon = card.getImageIcon();
JLabel lblCard = new JLabel() {
@Override
public void paintComponent(Graphics g) {
g.drawImage(cardImageIcon.getImage(), 0, 0, null);
super.paintComponent(g);
}
};
重要的是将其声明为 final 以便在 paintComponent
方法中使用它。
或
也许您可以只使用 JLabel
构造函数,该构造函数将 Icon
作为构造函数中的参数:
JLabel lblCard = new JLabel(card.getImageIcon());
考虑到所有建议,我更改了 card.getImageIcon()
。相反,我现在使用 getCardImagePane()
其中 returns 一个 JLayeredPane 在设置图像后。
下面是我现在使用的代码:
public CardImagePane getCardImagePane(boolean small) {
return new CardImagePane(this.getClass().getResource(
getValueAsString().toLowerCase() + "_of_"
+ getSuitAsString().toLowerCase() + ".png"), small);
}
class CardImagePane extends JLayeredPane {
private static final long serialVersionUID = 6829613165978637891L;
private Image image;
public CardImagePane(URL imgURL, boolean small) {
Image tempImg = new ImageIcon(imgURL).getImage();
this.image = tempImg.getScaledInstance(Constants.CARD_WIDTH,
Constants.CARD_HEIGHT, Image.SCALE_SMOOTH);
Dimension size = new Dimension(small ? Constants.CARD_WIDTH_SMALL
: Constants.CARD_WIDTH, Constants.CARD_HEIGHT);
setPreferredSize(size);
setMinimumSize(size);
setMaximumSize(size);
setSize(size);
setLayout(null);
}
public void paintComponent(Graphics g) {
g.drawImage(image, 0, 0, null);
}
}
感谢大家。请告诉我是否可以做一些更好的事情。
抱歉标题不好,想不出更好的了。
我正在制作纸牌游戏。
下面的方法将 Card object 作为参数,returns 我将 JLayeredPane 与 JLabel 一起使用,该 JLabel 具有卡片图像。
private JLayeredPane getCardPane(Card card) {
JLayeredPane cardPane = new JLayeredPane();
GridBagLayout gblCardPane = new GridBagLayout();
cardPane.setLayout(gblCardPane);
cardImageIcon = card.getImageIcon();
JLabel lblCard = new JLabel() {
@Override
public void paintComponent(Graphics g) {
g.drawImage(cardImageIcon.getImage(), 0, 0, null);
super.paintComponent(g);
}
};
GridBagConstraints gbcLblCard = new GridBagConstraints();
cardPane.add(lblCard,gbcLblCard);
return cardPane;
}
我有一个像下面这样的部分,将我手中的所有卡片添加到另一个 JLayeredPane jlpMyCards:
for (int i = 0; i < hand.getCardCount(); i++) {
JLayeredPane thisCard = getCardPane(hand.getCard(i));
//JOptionPane.showMessageDialog(null,thisCard);
jlpMyCards.add(thisCard);
}
最后将 jlpMyCards 添加到框架中。
在渲染帧上,我看到所有卡片在手(根据计数),但所有卡片都显示加载的最后一张图像。 - 为什么?
我尝试用
打印卡片JOptionPane.showMessageDialog(null,thisCard);
弹出对话框显示正确的图像。
注意:我猜 Card class 中的以下方法也可能会造成问题。
public ImageIcon getImageIcon() {
BufferedImage img = null;
try {
img = ImageIO.read(new File(this.getClass().getResource(
getValueAsString().toLowerCase() + "_of_"+
getSuitAsString().toLowerCase() + ".png").toURI()));
//Rescaling Image
Image dimg = img.getScaledInstance(100, 146, Image.SCALE_SMOOTH);
return new ImageIcon(dimg);
} catch (IOException e) {
e.printStackTrace();
} catch (URISyntaxException e) {
e.printStackTrace();
}
return null;
}
在循环的每次迭代中,您将值分配给字段 cardImageIcon
。并且在渲染所有标签时调用 getImage()
(在它们的 paintComponent
方法中)相同的 cardImageIcon
对象(在上次迭代期间设置)。
您可以将其作为局部变量,而不是将其保留为字段:
final ImageIcom cardImageIcon = card.getImageIcon();
JLabel lblCard = new JLabel() {
@Override
public void paintComponent(Graphics g) {
g.drawImage(cardImageIcon.getImage(), 0, 0, null);
super.paintComponent(g);
}
};
重要的是将其声明为 final 以便在 paintComponent
方法中使用它。
或
也许您可以只使用 JLabel
构造函数,该构造函数将 Icon
作为构造函数中的参数:
JLabel lblCard = new JLabel(card.getImageIcon());
考虑到所有建议,我更改了 card.getImageIcon()
。相反,我现在使用 getCardImagePane()
其中 returns 一个 JLayeredPane 在设置图像后。
下面是我现在使用的代码:
public CardImagePane getCardImagePane(boolean small) {
return new CardImagePane(this.getClass().getResource(
getValueAsString().toLowerCase() + "_of_"
+ getSuitAsString().toLowerCase() + ".png"), small);
}
class CardImagePane extends JLayeredPane {
private static final long serialVersionUID = 6829613165978637891L;
private Image image;
public CardImagePane(URL imgURL, boolean small) {
Image tempImg = new ImageIcon(imgURL).getImage();
this.image = tempImg.getScaledInstance(Constants.CARD_WIDTH,
Constants.CARD_HEIGHT, Image.SCALE_SMOOTH);
Dimension size = new Dimension(small ? Constants.CARD_WIDTH_SMALL
: Constants.CARD_WIDTH, Constants.CARD_HEIGHT);
setPreferredSize(size);
setMinimumSize(size);
setMaximumSize(size);
setSize(size);
setLayout(null);
}
public void paintComponent(Graphics g) {
g.drawImage(image, 0, 0, null);
}
}
感谢大家。请告诉我是否可以做一些更好的事情。