CardLayout (swing) с прослушивателями действий на кнопках?

Я пытался понять CardLayout с прослушивателями действий на кнопке (например, - начинается на странице загрузки - и при нажатии кнопки переключается на другую "карту"

мой код даже не запускается прямо сейчас, я не совсем уверен, почему - большинство реализаций, которые я могу найти, используют ItemListeners и Combo Boxes

Основной процесс, который я сделал, - это создать мастер-панель JPanel, но мои карты JPanel на мастер-панели JPanel, а мои разные карты - на карты JPanel, а затем добавить мастер-панель JPanel в кадр для отображения...

Кроме того, для одной из моих карт мне нужно только отобразить картинку - я ранее реализовал это, просто создав новое всплывающее окно, но было бы неплохо иметь возможность переключать рамку, чтобы показать его... Я не знаю, почему я не могу понять это

Вот мой код:

import java.awt.*;

/** 
 * Game
 * Main class that specifies the frame and widgets of the GUI
 */
public class Game implements Runnable {
public void run(){

    final String ON_OPEN = "Welcome!"; //Opening frame
    final String GAME = "Play!"; // Game Frame
    final String STATS = "Stats"; // Post-Game Stat Frame
    final String HELP = "Help"; //tutorial frame
    JPanel cards = new JPanel(); 
    JPanel master; // a panel for the card layout

    final JFrame frame = new JFrame(ON_OPEN);
    frame.setLocation(500,200);

    //Create the master layout for the program
    master = (JPanel) frame.getContentPane();
    master.setLayout(new BorderLayout()); // creating master layout

    //Create panel for all the cards in CardLayout
    final CardLayout cLay = new CardLayout();
    cards.setLayout(cLay);


    // all the cards
    final JPanel help = new JPanel();
    final JPanel stats = new JPanel();
    final JPanel game = new JPanel (new BorderLayout());
    final JPanel open = new JPanel (new FlowLayout());


    // setting up ON_OPEN layout - uses JPanel open

    final ImageIcon img = new ImageIcon("Instructions.png", "My Instructions..."); // the image I want shown under HELP card
    final JButton info = new JButton("Help");
    info.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
    //      cLay.show(help, HELP);     // WHAT I NORMALLY SHOULD BE DOING, RATHER JUST MAKE A NEW FRAME FOR THIS THOUGH
    //      frame.pack();

            final JFrame infoFrame = new JFrame("Tutorial");
            infoFrame.setLocation(500,50);
            JLabel tutorialImg = new JLabel(img);
    //      int w = img.getIconWidth();
        //  int h = img.getIconHeight();
            //infoFrame.setSize(w, h);
            infoFrame.pack();
            infoFrame.add(tutorialImg);
            infoFrame.setVisible(true);
        }
    });
    open.add(info); // the open-tutorial button



    //Add them to the cards JPanel
    cards.add(open, ON_OPEN);
    cards.add(help, HELP);
    cards.add(stats, STATS);
    cards.add(game, GAME);

    //Add the cards panel to the Master layout panel
    master.add(cards);


    // This code is all commented out because I'm not sure what I'm doing here...
//  frame.add(cards);
//  cLay.show(cards, ON_OPEN);

//  frame.add(open, BorderLayout.CENTER);

    // Main playing area - I want this to be shown in the GAME card...

    GridLayout tileGrid = new GridLayout(4,4);
    final JPanel grid = new JPanel(tileGrid);
      //    game.add(grid, BorderLayout.CENTER);

    //      grid.setLayout(tileGrid);
    //  frame.add(grid, BorderLayout.CENTER);


    // Input - holds typing box
    //        final JPanel status_panel = new JPanel();

    //  frame.add(cards, BorderLayout.CENTER);


//  frame.add(open, BorderLayout.CENTER);

    final JTextField typingArea = new JTextField();
    typingArea.setFocusTraversalKeysEnabled(false);
    typingArea.setEditable(true);
    typingArea.setFocusable(true);
    typingArea.requestFocus();


    frame.add(typingArea, BorderLayout.SOUTH);
    typingArea.addKeyListener(new KeyAdapter() {
        public void keyPressed (KeyEvent e) {
            if (e.getKeyCode() == KeyEvent.VK_ENTER) { // enter key is pressed
                String userWord = typingArea.getText().toLowerCase();
                typingArea.setText("");

            }
        }
    });


    final JLabel status = new JLabel("Running...");
    //        status_panel.add(status);

    // Reset button
    final JPanel control_panel = new JPanel();
    frame.add(control_panel, BorderLayout.NORTH);



    ]

    // Put the frame on the screen
    frame.pack();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setVisible(true);
}


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

}

person gadu    schedule 23.04.2013    source источник


Ответы (1)


Проблемы:

  • Ваш код не компилируется для нас, так как у нас нет класса JLetterField.
  • Вы пытаетесь добавить панель содержимого JFrame обратно к себе, что вызывает исключение и не имеет смысла.

Редактировать 1:

  • Ваш последний код показывает, что вы помещаете все в один очень большой run() метод, но при этом вы много теряете и ничего не получаете.
  • Я предлагаю избавиться от интерфейса Runnable, в нем нет необходимости, и создать настоящий класс, совместимый с ООП, с приватными полями и публичными и приватными методами.
  • Ваш метод actionPerformed не показывает попытки изменить отображаемую карту CardLayout.
  • Я предлагаю вам избавиться от кода, чтобы показать новое окно, и попробовать разместить код замены карты там.
  • Сделайте свой CardLayout и отображающие карты поля JPanel класса, чтобы другие методы могли получить к ним доступ и вызвать их методы.

Редактировать 2:

Например, следующий код показывает замену карт с помощью 3 кнопок JButton. Один, чтобы получить предыдущую карту, один, чтобы получить следующую карту, и один, чтобы показать, как получить конкретную карту (здесь 2-я):

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;

import javax.swing.*;

@SuppressWarnings("serial")
public class CardLayoutEg extends JPanel {
   private static final String[] CARD_LABELS = { "one", "two", "three", "four",
         "five", "six", "seven", "eight", "nine", "ten" };
   private static final int PREF_W = 400;
   private static final int PREF_H = PREF_W;
   private CardLayout cardlayout = new CardLayout();
   private JPanel cardHolder = new JPanel(cardlayout);
   private Action[] actions = { new ShowPreviousAction(), new ShowNextAction(),
         new ShowTwoCardAction() };

   public CardLayoutEg() {
      for (String cardLabelText : CARD_LABELS) {
         JLabel cardLabel = new JLabel(cardLabelText, SwingConstants.CENTER);
         cardHolder.add(cardLabel, cardLabelText);
      }

      JPanel btnPanel = new JPanel(new GridLayout(1, 0, 5, 0));
      for (Action action : actions) {
         btnPanel.add(new JButton(action));
      }

      setLayout(new BorderLayout());
      add(cardHolder, BorderLayout.CENTER);
      add(btnPanel, BorderLayout.SOUTH);
   }

   @Override
   public Dimension getPreferredSize() {
      return new Dimension(PREF_W, PREF_H);
   }

   private class ShowPreviousAction extends AbstractAction {
      public ShowPreviousAction() {
         super("Previous");
      }

      @Override
      public void actionPerformed(ActionEvent e) {
         cardlayout.previous(cardHolder);
      }
   }

   private class ShowNextAction extends AbstractAction {
      public ShowNextAction() {
         super("Next");
      }

      @Override
      public void actionPerformed(ActionEvent e) {
         cardlayout.next(cardHolder);
      }
   }

   private class ShowTwoCardAction extends AbstractAction {
      public ShowTwoCardAction() {
         super("Show Two");
      }

      @Override
      public void actionPerformed(ActionEvent e) {
         cardlayout.show(cardHolder, CARD_LABELS[1]);
      }
   }

   private static void createAndShowGui() {
      CardLayoutEg mainPanel = new CardLayoutEg();

      JFrame frame = new JFrame("CardLayout Example");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}
person Hovercraft Full Of Eels    schedule 23.04.2013
comment
Добавлен класс JLetterField - также где я пытаюсь добавить панель содержимого обратно в себя, где я говорю frame.add(master, BorderLayout.CENTER)? Я пытаюсь сделать так, чтобы при открытии отображались только две кнопки: информационная кнопка с надписью «Справка» и изменение макета для отображения изображения «Instructions.png», а затем под этой кнопкой кнопка с надписью «Воспроизвести» (которую я не еще не сделано), что изменит макет карты GAME.. - person gadu; 24.04.2013
comment
@ user2310306: вместо того, чтобы давать нам этот класс, для целей форума вы должны просто использовать JTextField. Класс не имеет ничего общего с вашей проблемой, поэтому ваша задача — упростить код, чтобы он все еще компилировался, но показывал вашу проблему. Пожалуйста, сделайте это сейчас. Что касается contentPane, основная панель JPanel является панелью содержимого JFrame. Опять же, почему вы пытаетесь добавить его обратно? Без разницы. Это уже есть! Я предлагаю вам отказаться от приведенного выше кода и просто попытаться решить проблему с помощью самого простого возможного кода. - person Hovercraft Full Of Eels; 24.04.2013
comment
отредактировано .. спасибо, я новичок в java, и этот сайт, спасибо за терпение - person gadu; 24.04.2013
comment
@user2310306 user2310306: см. 2-е редактирование, чтобы ответить на пример кода. Пожалуйста, прочтите также учебник по CardLayout. - person Hovercraft Full Of Eels; 24.04.2013