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());
            }
        }
    }
}