else if 只显示最后一个面板
Else if only displays the last panel
我建立了一个庞大的游戏项目。我正在使用 CardLayout
来显示何时在 JLabel
上释放鼠标。我让它在其他 类' JLabels
上工作,但是当我按 JLabel
它只显示 CardLayout
的最后一个 JPanel
。我希望它显示我设置的特定 JPanel
。
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Timer;
import java.util.TimerTask;
class ChooseGame extends JPanel {
Icon imgIcon = new ImageIcon(this.getClass().getResource("gameOne.gif"));
Icon imgIcon2 = new ImageIcon(this.getClass().getResource("gameTwo.gif"));
Icon imgIcon3 = new ImageIcon(this.getClass().getResource("gameThree.gif"));
Icon imgIcon4 = new ImageIcon(this.getClass().getResource("gameFour.gif"));
JLabel game1 = new JLabel(imgIcon);
JLabel game2 = new JLabel(imgIcon2);
JLabel game3 = new JLabel(imgIcon3);
JLabel game4 = new JLabel(imgIcon4);
JLabel game5 = new JLabel(imgIcon);
JLabel game6 = new JLabel(imgIcon2);
JLabel game7 = new JLabel(imgIcon);
JLabel game8 = new JLabel(imgIcon2);
JLabel game9 = new JLabel(imgIcon);
Handler handler = new Handler();
public ChooseGame() {
setVisible(true);
setBackground(Color.RED);
setForeground(Color.BLACK);
setLayout(new GridLayout(3, 3));
addMouseListener(handler);
addMouseMotionListener(handler);
buttons();
add(game1);
add(game2);
add(game3);
add(game4);
add(game5);
add(game6);
add(game7);
add(game8);
add(game9);
}
public void buttons() {
game1.addMouseListener(handler);
game1.addMouseMotionListener(handler);
game1.setVisible(true);
game2.addMouseListener(handler);
game2.addMouseMotionListener(handler);
game2.setVisible(true);
game3.addMouseListener(handler);
game3.addMouseMotionListener(handler);
game3.setVisible(true);
game4.addMouseListener(handler);
game4.addMouseMotionListener(handler);
game4.setVisible(true);
game5.addMouseListener(handler);
game5.addMouseMotionListener(handler);
game5.setVisible(true);
game6.addMouseListener(handler);
game6.addMouseMotionListener(handler);
game6.setVisible(true);
game7.addMouseListener(handler);
game7.addMouseMotionListener(handler);
game7.setVisible(true);
game8.addMouseListener(handler);
game8.addMouseMotionListener(handler);
game8.setVisible(true);
game9.addMouseListener(handler);
game9.addMouseMotionListener(handler);
game9.setVisible(true);
}
private class Handler implements MouseListener, MouseMotionListener {
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
time(e);
}
public void time(MouseEvent e) {
Timer timer = new Timer();
// adds new Timer
TimerTask task = new TimerTask() {
// sets new task for said timer
@Override
public void run() {
if (game1.contains(e.getX(), e.getY())) {
CardPanel.layout.show(CardPanel.cardPanel, "one");
} else if (game2.contains(e.getX(), e.getY())) {
CardPanel.layout.show(CardPanel.cardPanel, "two");
} else if (game3.contains(e.getX(), e.getY())) {
CardPanel.layout.show(CardPanel.cardPanel, "three");
} else if (game4.contains(e.getX(), e.getY())) {
CardPanel.layout.show(CardPanel.cardPanel, "four");
} else if (game5.contains(e.getX(), e.getY())) {
CardPanel.layout.show(CardPanel.cardPanel, "five");
} else if (game6.contains(e.getX(), e.getY())) {
CardPanel.layout.show(CardPanel.cardPanel, "six");
} else if (game7.contains(e.getX(), e.getY())) {
CardPanel.layout.show(CardPanel.cardPanel, "seven");
} else if (game8.contains(e.getX(), e.getY())) {
CardPanel.layout.show(CardPanel.cardPanel, "eight");
} else if (game9.contains(e.getX(), e.getY())) {
CardPanel.layout.show(CardPanel.cardPanel, "nine");
}
}
};
timer.scheduleAtFixedRate(task, 0, 1000);
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseDragged(MouseEvent e) {
System.out.println("Dragged");
}
@Override
public void mouseMoved(MouseEvent e) {
}
}
}
发生了很多事情,嗯,充其量是有问题的,例如...
public ChooseGame() {
//...
addMouseListener(handler);
addMouseMotionListener(handler);
//...
}
public void buttons() {
game1.addMouseListener(handler);
game1.addMouseMotionListener(handler);
//...
}
现在,ChooseGame
和每个单独的标签都附加了 MouseListener
,为什么?这可能会导致事件的双重触发
然后...
public void time(MouseEvent e) {
Timer timer = new Timer();
// adds new Timer
TimerTask task = new TimerTask() {
// sets new task for said timer
@Override
public void run() {
if (game1.contains(e.getX(), e.getY())) {
CardPanel.layout.show(CardPanel.cardPanel, "one");
} else if (game2.contains(e.getX(), e.getY())) {
CardPanel.layout.show(CardPanel.cardPanel, "two");
} else if (game3.contains(e.getX(), e.getY())) {
CardPanel.layout.show(CardPanel.cardPanel, "three");
} else if (game4.contains(e.getX(), e.getY())) {
CardPanel.layout.show(CardPanel.cardPanel, "four");
} else if (game5.contains(e.getX(), e.getY())) {
CardPanel.layout.show(CardPanel.cardPanel, "five");
} else if (game6.contains(e.getX(), e.getY())) {
CardPanel.layout.show(CardPanel.cardPanel, "six");
} else if (game7.contains(e.getX(), e.getY())) {
CardPanel.layout.show(CardPanel.cardPanel, "seven");
} else if (game8.contains(e.getX(), e.getY())) {
CardPanel.layout.show(CardPanel.cardPanel, "eight");
} else if (game9.contains(e.getX(), e.getY())) {
CardPanel.layout.show(CardPanel.cardPanel, "nine");
}
}
};
timer.scheduleAtFixedRate(task, 0, 1000);
}
您正在将事件点与每个标签位置进行比较,在我的测试中,每个标签 return true
用于 contains
检查。
为什么不只比较事件的source
if (e.getSource() == game1) {...}
我什至不会问你为什么需要每秒重复检查这个或者为什么你使用 static
引用 CardPanel
- 它不是 ChooseGame
'换牌的责任,相反,它应该通知 CardPanel
某些状态已经改变,并且 CardPanel
应该决定如何响应该变化。
但是,让我们关注最初的问题。
我们可以专注于创建一个“处理程序”,而不是使用单个 Handler
,它可以针对每个单独的标签进行自定义,或者最好是所需的结果,例如...
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
frame.add(new ChooseGame());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
protected BufferedImage makeImage(String text) {
int size = 50;
BufferedImage img = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
g2d.setColor(Color.LIGHT_GRAY);
Shape baseShape = new RoundRectangle2D.Double(0, 0, size - 1, size - 1, 10, 10);
g2d.fill(baseShape);
g2d.setColor(Color.DARK_GRAY);
g2d.draw(baseShape);
FontMetrics fm = g2d.getFontMetrics();
int x = (size - fm.stringWidth(text)) / 2;
int y = (size - fm.getHeight()) / 2;
g2d.setColor(Color.BLACK);
g2d.drawString(text, x, y + fm.getAscent());
g2d.dispose();
return img;
}
class ChooseGame extends JPanel {
private ImageIcon[] icons = new ImageIcon[]{
new ImageIcon(makeImage("1")),
new ImageIcon(makeImage("2")),
new ImageIcon(makeImage("3")),
new ImageIcon(makeImage("4"))
};
private JLabel[] labels = new JLabel[9];
public ChooseGame() {
setBackground(Color.RED);
setForeground(Color.BLACK);
setLayout(new GridLayout(3, 3));
createActions();
for (JLabel label : labels) {
add(label);
}
}
public void createActions() {
for (int index = 0; index < labels.length; index++) {
ImageIcon icon = null;
ActionHandler.Action action = ActionHandler.Action.from(index);
if (index == 0 || index == 4 || index == 6 || index == 8) {
icon = icons[0];
} else if (index == 1 || index == 5 || index == 7) {
icon = icons[1];
} else if (index == 2) {
icon = icons[2];
} else if (index == 3) {
icon = icons[3];
}
JLabel label = new JLabel(icon);
if (action != null) {
ActionHandler actionHandler = new ActionHandler(action);
label.addMouseListener(actionHandler);
label.addMouseMotionListener(actionHandler);
}
labels[index] = label;
}
}
protected class ActionHandler extends MouseAdapter {
enum Action {
ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE;
static Action from(int index) {
switch (index) {
case 0:
return ONE;
case 1:
return TWO;
case 2:
return THREE;
case 3:
return FOUR;
case 4:
return FIVE;
case 5:
return SIX;
case 6:
return SEVEN;
case 7:
return EIGHT;
case 8:
return NINE;
}
return null;
}
}
private Action action;
public ActionHandler(Action action) {
this.action = action;
}
public Action getAction() {
return action;
}
@Override
public void mouseClicked(MouseEvent e) {
switch (getAction()) {
case ONE:
System.out.println("Show one");
break;
case TWO:
System.out.println("Show two");
break;
case THREE:
System.out.println("Show three");
break;
case FOUR:
System.out.println("Show four");
break;
case FIVE:
System.out.println("Show five");
break;
case SIX:
System.out.println("Show six");
break;
case SEVEN:
System.out.println("Show seven");
break;
case EIGHT:
System.out.println("Show eight");
break;
case NINE:
System.out.println("Show nine");
break;
}
}
}
}
}
但是,这对使用标签的决定提出了更多问题,为什么?
JLabels have more stylistic choices
真的,在哪些方面?什么值得牺牲一个按钮的核心功能,它的唯一职责就是在用户选择它时告诉你?为什么要花费所有时间重新创建该功能?
例如,其中一个使用标签,另一个使用按钮
你能分辨出来吗?不要相信我,没关系,我不会。其中一张图片是从上面的代码生成的,另一张是从这段代码生成的...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
frame.setLayout(new GridBagLayout());
frame.add(new ChooseGame());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public interface CardPresentable {
enum Card {
ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE;
}
public void showCard(Card card);
}
public class CardPane extends JPanel implements CardPresentable {
private JLabel label;
public CardPane() {
setBorder(new EmptyBorder(32, 32, 32, 32));
setLayout(new BorderLayout());
label = new JLabel("Nothing");
add(label);
}
@Override
public void showCard(Card card) {
label.setText(card.name());
}
}
protected BufferedImage makeImage(String text) {
int size = 50;
BufferedImage img = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
g2d.setColor(Color.LIGHT_GRAY);
Shape baseShape = new RoundRectangle2D.Double(0, 0, size - 1, size - 1, 10, 10);
g2d.fill(baseShape);
g2d.setColor(Color.DARK_GRAY);
g2d.draw(baseShape);
FontMetrics fm = g2d.getFontMetrics();
int x = (size - fm.stringWidth(text)) / 2;
int y = (size - fm.getHeight()) / 2;
g2d.setColor(Color.BLACK);
g2d.drawString(text, x, y + fm.getAscent());
g2d.dispose();
return img;
}
class ChooseGame extends JPanel {
private ImageIcon[] icons = new ImageIcon[]{
new ImageIcon(makeImage("1")),
new ImageIcon(makeImage("2")),
new ImageIcon(makeImage("3")),
new ImageIcon(makeImage("4"))
};
private JButton[] buttons = new JButton[9];
public ChooseGame() {
setBackground(Color.RED);
setForeground(Color.BLACK);
setLayout(new GridLayout(3, 3));
createActions();
for (JButton button : buttons) {
add(button);
}
}
public void createActions() {
CardPresentable.Card cards[] = new CardPresentable.Card[] {
CardPresentable.Card.ONE,
CardPresentable.Card.TWO,
CardPresentable.Card.THREE,
CardPresentable.Card.FOUR,
CardPresentable.Card.FIVE,
CardPresentable.Card.SIX,
CardPresentable.Card.SEVEN,
CardPresentable.Card.EIGHT,
CardPresentable.Card.NINE
};
for (int index = 0; index < buttons.length; index++) {
ImageIcon icon = null;
if (index == 0 || index == 4 || index == 6 || index == 8) {
icon = icons[0];
} else if (index == 1 || index == 5 || index == 7) {
icon = icons[1];
} else if (index == 2) {
icon = icons[2];
} else if (index == 3) {
icon = icons[3];
}
JButton button = new JButton(icon);
button.setFocusPainted(false);
button.setContentAreaFilled(false);
button.setBorderPainted(false);
button.setBorder(null);
buttons[index] = button;
}
}
}
}
最后一件事...
static
不是您的朋友,在您尝试使用它的上下文中,它不会帮助您。相反,您想使用“依赖注入”的概念,也就是说,您向每个 class 传递完成其工作所需的信息,在这种情况下,就是 CardPanel
,但是,我会非常谨慎地传递一个复杂的对象,比如将一个组件传递给任何主体,我的意思是,它们不应该弄乱内容。在这种情况下,我们想要的是在某些状态发生变化时得到通知。这是“观察者模式”的基础(您已经使用过这个,Swing 称它们为侦听器)
例如...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
frame.setLayout(new GridBagLayout());
CardPane cardPane = new CardPane();
frame.add(new ChooseGame(cardPane));
frame.add(cardPane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public interface CardPresentable {
enum Card {
ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE;
}
public void showCard(Card card);
}
public class CardPane extends JPanel implements CardPresentable {
private JLabel label;
public CardPane() {
setBorder(new EmptyBorder(32, 32, 32, 32));
setLayout(new BorderLayout());
label = new JLabel("Nothing");
add(label);
}
@Override
public void showCard(Card card) {
label.setText(card.name());
}
}
protected BufferedImage makeImage(String text) {
int size = 50;
BufferedImage img = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
g2d.setColor(Color.LIGHT_GRAY);
Shape baseShape = new RoundRectangle2D.Double(0, 0, size - 1, size - 1, 10, 10);
g2d.fill(baseShape);
g2d.setColor(Color.DARK_GRAY);
g2d.draw(baseShape);
FontMetrics fm = g2d.getFontMetrics();
int x = (size - fm.stringWidth(text)) / 2;
int y = (size - fm.getHeight()) / 2;
g2d.setColor(Color.BLACK);
g2d.drawString(text, x, y + fm.getAscent());
g2d.dispose();
return img;
}
class ChooseGame extends JPanel {
private ImageIcon[] icons = new ImageIcon[]{
new ImageIcon(makeImage("1")),
new ImageIcon(makeImage("2")),
new ImageIcon(makeImage("3")),
new ImageIcon(makeImage("4"))
};
private JButton[] buttons = new JButton[9];
private CardPresentable cardPresentable;
public ChooseGame(CardPresentable cardPresentable) {
this.cardPresentable = cardPresentable;
setBackground(Color.RED);
setForeground(Color.BLACK);
setLayout(new GridLayout(3, 3));
createActions();
for (JButton button : buttons) {
add(button);
}
}
public CardPresentable getCardPresentable() {
return cardPresentable;
}
public void createActions() {
CardPresentable.Card cards[] = new CardPresentable.Card[]{
CardPresentable.Card.ONE,
CardPresentable.Card.TWO,
CardPresentable.Card.THREE,
CardPresentable.Card.FOUR,
CardPresentable.Card.FIVE,
CardPresentable.Card.SIX,
CardPresentable.Card.SEVEN,
CardPresentable.Card.EIGHT,
CardPresentable.Card.NINE
};
for (int index = 0; index < buttons.length; index++) {
ImageIcon icon = null;
if (index == 0 || index == 4 || index == 6 || index == 8) {
icon = icons[0];
} else if (index == 1 || index == 5 || index == 7) {
icon = icons[1];
} else if (index == 2) {
icon = icons[2];
} else if (index == 3) {
icon = icons[3];
}
JButton button = new JButton(icon);
button.setFocusPainted(false);
button.setContentAreaFilled(false);
button.setBorderPainted(false);
button.setBorder(null);
CardPresentable.Card card = cards[index];
button.addActionListener(new ActionHandler(getCardPresentable(), card));
buttons[index] = button;
}
}
protected class ActionHandler implements ActionListener {
private CardPresentable.Card card;
private CardPresentable cardPresentable;
public ActionHandler(CardPresentable cardPresentable, CardPresentable.Card card) {
this.card = card;
this.cardPresentable = cardPresentable;
}
public CardPresentable.Card getCard() {
return card;
}
public CardPresentable getCardPresentable() {
return cardPresentable;
}
@Override
public void actionPerformed(ActionEvent e) {
getCardPresentable().showCard(getCard());
}
}
}
}
我建立了一个庞大的游戏项目。我正在使用 CardLayout
来显示何时在 JLabel
上释放鼠标。我让它在其他 类' JLabels
上工作,但是当我按 JLabel
它只显示 CardLayout
的最后一个 JPanel
。我希望它显示我设置的特定 JPanel
。
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Timer;
import java.util.TimerTask;
class ChooseGame extends JPanel {
Icon imgIcon = new ImageIcon(this.getClass().getResource("gameOne.gif"));
Icon imgIcon2 = new ImageIcon(this.getClass().getResource("gameTwo.gif"));
Icon imgIcon3 = new ImageIcon(this.getClass().getResource("gameThree.gif"));
Icon imgIcon4 = new ImageIcon(this.getClass().getResource("gameFour.gif"));
JLabel game1 = new JLabel(imgIcon);
JLabel game2 = new JLabel(imgIcon2);
JLabel game3 = new JLabel(imgIcon3);
JLabel game4 = new JLabel(imgIcon4);
JLabel game5 = new JLabel(imgIcon);
JLabel game6 = new JLabel(imgIcon2);
JLabel game7 = new JLabel(imgIcon);
JLabel game8 = new JLabel(imgIcon2);
JLabel game9 = new JLabel(imgIcon);
Handler handler = new Handler();
public ChooseGame() {
setVisible(true);
setBackground(Color.RED);
setForeground(Color.BLACK);
setLayout(new GridLayout(3, 3));
addMouseListener(handler);
addMouseMotionListener(handler);
buttons();
add(game1);
add(game2);
add(game3);
add(game4);
add(game5);
add(game6);
add(game7);
add(game8);
add(game9);
}
public void buttons() {
game1.addMouseListener(handler);
game1.addMouseMotionListener(handler);
game1.setVisible(true);
game2.addMouseListener(handler);
game2.addMouseMotionListener(handler);
game2.setVisible(true);
game3.addMouseListener(handler);
game3.addMouseMotionListener(handler);
game3.setVisible(true);
game4.addMouseListener(handler);
game4.addMouseMotionListener(handler);
game4.setVisible(true);
game5.addMouseListener(handler);
game5.addMouseMotionListener(handler);
game5.setVisible(true);
game6.addMouseListener(handler);
game6.addMouseMotionListener(handler);
game6.setVisible(true);
game7.addMouseListener(handler);
game7.addMouseMotionListener(handler);
game7.setVisible(true);
game8.addMouseListener(handler);
game8.addMouseMotionListener(handler);
game8.setVisible(true);
game9.addMouseListener(handler);
game9.addMouseMotionListener(handler);
game9.setVisible(true);
}
private class Handler implements MouseListener, MouseMotionListener {
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
time(e);
}
public void time(MouseEvent e) {
Timer timer = new Timer();
// adds new Timer
TimerTask task = new TimerTask() {
// sets new task for said timer
@Override
public void run() {
if (game1.contains(e.getX(), e.getY())) {
CardPanel.layout.show(CardPanel.cardPanel, "one");
} else if (game2.contains(e.getX(), e.getY())) {
CardPanel.layout.show(CardPanel.cardPanel, "two");
} else if (game3.contains(e.getX(), e.getY())) {
CardPanel.layout.show(CardPanel.cardPanel, "three");
} else if (game4.contains(e.getX(), e.getY())) {
CardPanel.layout.show(CardPanel.cardPanel, "four");
} else if (game5.contains(e.getX(), e.getY())) {
CardPanel.layout.show(CardPanel.cardPanel, "five");
} else if (game6.contains(e.getX(), e.getY())) {
CardPanel.layout.show(CardPanel.cardPanel, "six");
} else if (game7.contains(e.getX(), e.getY())) {
CardPanel.layout.show(CardPanel.cardPanel, "seven");
} else if (game8.contains(e.getX(), e.getY())) {
CardPanel.layout.show(CardPanel.cardPanel, "eight");
} else if (game9.contains(e.getX(), e.getY())) {
CardPanel.layout.show(CardPanel.cardPanel, "nine");
}
}
};
timer.scheduleAtFixedRate(task, 0, 1000);
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseDragged(MouseEvent e) {
System.out.println("Dragged");
}
@Override
public void mouseMoved(MouseEvent e) {
}
}
}
发生了很多事情,嗯,充其量是有问题的,例如...
public ChooseGame() {
//...
addMouseListener(handler);
addMouseMotionListener(handler);
//...
}
public void buttons() {
game1.addMouseListener(handler);
game1.addMouseMotionListener(handler);
//...
}
现在,ChooseGame
和每个单独的标签都附加了 MouseListener
,为什么?这可能会导致事件的双重触发
然后...
public void time(MouseEvent e) {
Timer timer = new Timer();
// adds new Timer
TimerTask task = new TimerTask() {
// sets new task for said timer
@Override
public void run() {
if (game1.contains(e.getX(), e.getY())) {
CardPanel.layout.show(CardPanel.cardPanel, "one");
} else if (game2.contains(e.getX(), e.getY())) {
CardPanel.layout.show(CardPanel.cardPanel, "two");
} else if (game3.contains(e.getX(), e.getY())) {
CardPanel.layout.show(CardPanel.cardPanel, "three");
} else if (game4.contains(e.getX(), e.getY())) {
CardPanel.layout.show(CardPanel.cardPanel, "four");
} else if (game5.contains(e.getX(), e.getY())) {
CardPanel.layout.show(CardPanel.cardPanel, "five");
} else if (game6.contains(e.getX(), e.getY())) {
CardPanel.layout.show(CardPanel.cardPanel, "six");
} else if (game7.contains(e.getX(), e.getY())) {
CardPanel.layout.show(CardPanel.cardPanel, "seven");
} else if (game8.contains(e.getX(), e.getY())) {
CardPanel.layout.show(CardPanel.cardPanel, "eight");
} else if (game9.contains(e.getX(), e.getY())) {
CardPanel.layout.show(CardPanel.cardPanel, "nine");
}
}
};
timer.scheduleAtFixedRate(task, 0, 1000);
}
您正在将事件点与每个标签位置进行比较,在我的测试中,每个标签 return true
用于 contains
检查。
为什么不只比较事件的source
if (e.getSource() == game1) {...}
我什至不会问你为什么需要每秒重复检查这个或者为什么你使用 static
引用 CardPanel
- 它不是 ChooseGame
'换牌的责任,相反,它应该通知 CardPanel
某些状态已经改变,并且 CardPanel
应该决定如何响应该变化。
但是,让我们关注最初的问题。
我们可以专注于创建一个“处理程序”,而不是使用单个 Handler
,它可以针对每个单独的标签进行自定义,或者最好是所需的结果,例如...
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
frame.add(new ChooseGame());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
protected BufferedImage makeImage(String text) {
int size = 50;
BufferedImage img = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
g2d.setColor(Color.LIGHT_GRAY);
Shape baseShape = new RoundRectangle2D.Double(0, 0, size - 1, size - 1, 10, 10);
g2d.fill(baseShape);
g2d.setColor(Color.DARK_GRAY);
g2d.draw(baseShape);
FontMetrics fm = g2d.getFontMetrics();
int x = (size - fm.stringWidth(text)) / 2;
int y = (size - fm.getHeight()) / 2;
g2d.setColor(Color.BLACK);
g2d.drawString(text, x, y + fm.getAscent());
g2d.dispose();
return img;
}
class ChooseGame extends JPanel {
private ImageIcon[] icons = new ImageIcon[]{
new ImageIcon(makeImage("1")),
new ImageIcon(makeImage("2")),
new ImageIcon(makeImage("3")),
new ImageIcon(makeImage("4"))
};
private JLabel[] labels = new JLabel[9];
public ChooseGame() {
setBackground(Color.RED);
setForeground(Color.BLACK);
setLayout(new GridLayout(3, 3));
createActions();
for (JLabel label : labels) {
add(label);
}
}
public void createActions() {
for (int index = 0; index < labels.length; index++) {
ImageIcon icon = null;
ActionHandler.Action action = ActionHandler.Action.from(index);
if (index == 0 || index == 4 || index == 6 || index == 8) {
icon = icons[0];
} else if (index == 1 || index == 5 || index == 7) {
icon = icons[1];
} else if (index == 2) {
icon = icons[2];
} else if (index == 3) {
icon = icons[3];
}
JLabel label = new JLabel(icon);
if (action != null) {
ActionHandler actionHandler = new ActionHandler(action);
label.addMouseListener(actionHandler);
label.addMouseMotionListener(actionHandler);
}
labels[index] = label;
}
}
protected class ActionHandler extends MouseAdapter {
enum Action {
ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE;
static Action from(int index) {
switch (index) {
case 0:
return ONE;
case 1:
return TWO;
case 2:
return THREE;
case 3:
return FOUR;
case 4:
return FIVE;
case 5:
return SIX;
case 6:
return SEVEN;
case 7:
return EIGHT;
case 8:
return NINE;
}
return null;
}
}
private Action action;
public ActionHandler(Action action) {
this.action = action;
}
public Action getAction() {
return action;
}
@Override
public void mouseClicked(MouseEvent e) {
switch (getAction()) {
case ONE:
System.out.println("Show one");
break;
case TWO:
System.out.println("Show two");
break;
case THREE:
System.out.println("Show three");
break;
case FOUR:
System.out.println("Show four");
break;
case FIVE:
System.out.println("Show five");
break;
case SIX:
System.out.println("Show six");
break;
case SEVEN:
System.out.println("Show seven");
break;
case EIGHT:
System.out.println("Show eight");
break;
case NINE:
System.out.println("Show nine");
break;
}
}
}
}
}
但是,这对使用标签的决定提出了更多问题,为什么?
JLabels have more stylistic choices
真的,在哪些方面?什么值得牺牲一个按钮的核心功能,它的唯一职责就是在用户选择它时告诉你?为什么要花费所有时间重新创建该功能?
例如,其中一个使用标签,另一个使用按钮
你能分辨出来吗?不要相信我,没关系,我不会。其中一张图片是从上面的代码生成的,另一张是从这段代码生成的...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
frame.setLayout(new GridBagLayout());
frame.add(new ChooseGame());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public interface CardPresentable {
enum Card {
ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE;
}
public void showCard(Card card);
}
public class CardPane extends JPanel implements CardPresentable {
private JLabel label;
public CardPane() {
setBorder(new EmptyBorder(32, 32, 32, 32));
setLayout(new BorderLayout());
label = new JLabel("Nothing");
add(label);
}
@Override
public void showCard(Card card) {
label.setText(card.name());
}
}
protected BufferedImage makeImage(String text) {
int size = 50;
BufferedImage img = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
g2d.setColor(Color.LIGHT_GRAY);
Shape baseShape = new RoundRectangle2D.Double(0, 0, size - 1, size - 1, 10, 10);
g2d.fill(baseShape);
g2d.setColor(Color.DARK_GRAY);
g2d.draw(baseShape);
FontMetrics fm = g2d.getFontMetrics();
int x = (size - fm.stringWidth(text)) / 2;
int y = (size - fm.getHeight()) / 2;
g2d.setColor(Color.BLACK);
g2d.drawString(text, x, y + fm.getAscent());
g2d.dispose();
return img;
}
class ChooseGame extends JPanel {
private ImageIcon[] icons = new ImageIcon[]{
new ImageIcon(makeImage("1")),
new ImageIcon(makeImage("2")),
new ImageIcon(makeImage("3")),
new ImageIcon(makeImage("4"))
};
private JButton[] buttons = new JButton[9];
public ChooseGame() {
setBackground(Color.RED);
setForeground(Color.BLACK);
setLayout(new GridLayout(3, 3));
createActions();
for (JButton button : buttons) {
add(button);
}
}
public void createActions() {
CardPresentable.Card cards[] = new CardPresentable.Card[] {
CardPresentable.Card.ONE,
CardPresentable.Card.TWO,
CardPresentable.Card.THREE,
CardPresentable.Card.FOUR,
CardPresentable.Card.FIVE,
CardPresentable.Card.SIX,
CardPresentable.Card.SEVEN,
CardPresentable.Card.EIGHT,
CardPresentable.Card.NINE
};
for (int index = 0; index < buttons.length; index++) {
ImageIcon icon = null;
if (index == 0 || index == 4 || index == 6 || index == 8) {
icon = icons[0];
} else if (index == 1 || index == 5 || index == 7) {
icon = icons[1];
} else if (index == 2) {
icon = icons[2];
} else if (index == 3) {
icon = icons[3];
}
JButton button = new JButton(icon);
button.setFocusPainted(false);
button.setContentAreaFilled(false);
button.setBorderPainted(false);
button.setBorder(null);
buttons[index] = button;
}
}
}
}
最后一件事...
static
不是您的朋友,在您尝试使用它的上下文中,它不会帮助您。相反,您想使用“依赖注入”的概念,也就是说,您向每个 class 传递完成其工作所需的信息,在这种情况下,就是 CardPanel
,但是,我会非常谨慎地传递一个复杂的对象,比如将一个组件传递给任何主体,我的意思是,它们不应该弄乱内容。在这种情况下,我们想要的是在某些状态发生变化时得到通知。这是“观察者模式”的基础(您已经使用过这个,Swing 称它们为侦听器)
例如...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
frame.setLayout(new GridBagLayout());
CardPane cardPane = new CardPane();
frame.add(new ChooseGame(cardPane));
frame.add(cardPane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public interface CardPresentable {
enum Card {
ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE;
}
public void showCard(Card card);
}
public class CardPane extends JPanel implements CardPresentable {
private JLabel label;
public CardPane() {
setBorder(new EmptyBorder(32, 32, 32, 32));
setLayout(new BorderLayout());
label = new JLabel("Nothing");
add(label);
}
@Override
public void showCard(Card card) {
label.setText(card.name());
}
}
protected BufferedImage makeImage(String text) {
int size = 50;
BufferedImage img = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
g2d.setColor(Color.LIGHT_GRAY);
Shape baseShape = new RoundRectangle2D.Double(0, 0, size - 1, size - 1, 10, 10);
g2d.fill(baseShape);
g2d.setColor(Color.DARK_GRAY);
g2d.draw(baseShape);
FontMetrics fm = g2d.getFontMetrics();
int x = (size - fm.stringWidth(text)) / 2;
int y = (size - fm.getHeight()) / 2;
g2d.setColor(Color.BLACK);
g2d.drawString(text, x, y + fm.getAscent());
g2d.dispose();
return img;
}
class ChooseGame extends JPanel {
private ImageIcon[] icons = new ImageIcon[]{
new ImageIcon(makeImage("1")),
new ImageIcon(makeImage("2")),
new ImageIcon(makeImage("3")),
new ImageIcon(makeImage("4"))
};
private JButton[] buttons = new JButton[9];
private CardPresentable cardPresentable;
public ChooseGame(CardPresentable cardPresentable) {
this.cardPresentable = cardPresentable;
setBackground(Color.RED);
setForeground(Color.BLACK);
setLayout(new GridLayout(3, 3));
createActions();
for (JButton button : buttons) {
add(button);
}
}
public CardPresentable getCardPresentable() {
return cardPresentable;
}
public void createActions() {
CardPresentable.Card cards[] = new CardPresentable.Card[]{
CardPresentable.Card.ONE,
CardPresentable.Card.TWO,
CardPresentable.Card.THREE,
CardPresentable.Card.FOUR,
CardPresentable.Card.FIVE,
CardPresentable.Card.SIX,
CardPresentable.Card.SEVEN,
CardPresentable.Card.EIGHT,
CardPresentable.Card.NINE
};
for (int index = 0; index < buttons.length; index++) {
ImageIcon icon = null;
if (index == 0 || index == 4 || index == 6 || index == 8) {
icon = icons[0];
} else if (index == 1 || index == 5 || index == 7) {
icon = icons[1];
} else if (index == 2) {
icon = icons[2];
} else if (index == 3) {
icon = icons[3];
}
JButton button = new JButton(icon);
button.setFocusPainted(false);
button.setContentAreaFilled(false);
button.setBorderPainted(false);
button.setBorder(null);
CardPresentable.Card card = cards[index];
button.addActionListener(new ActionHandler(getCardPresentable(), card));
buttons[index] = button;
}
}
protected class ActionHandler implements ActionListener {
private CardPresentable.Card card;
private CardPresentable cardPresentable;
public ActionHandler(CardPresentable cardPresentable, CardPresentable.Card card) {
this.card = card;
this.cardPresentable = cardPresentable;
}
public CardPresentable.Card getCard() {
return card;
}
public CardPresentable getCardPresentable() {
return cardPresentable;
}
@Override
public void actionPerformed(ActionEvent e) {
getCardPresentable().showCard(getCard());
}
}
}
}