如何防止 GridBagLayout 改变按钮的大小

How to keep GridBagLayout from changing the size of a button

在我的 FlashCardPanel class 中,我有一个带有 Grid Bag 布局的子面板 LabelPanel。它由一个带有编辑按钮的构造函数、一个 "flip" 卡片的按钮和一个显示 term/definition 的标签组成。我的问题是,每次我单击 "Flip" 按钮来显示术语的定义时,翻转按钮都会改变大小,通常与定义的长度相匹配。

问题图片 http://postimg.org/gallery/ymww3axq/

import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;


public class FlashCardPanel extends JPanel{


    private String term;
    private String definition;

    // shows the current text whether it is a term or definition
    private JLabel currentLabel;

    private static String NO_CARDS = "This set is empty";

    //current card being displayed
    private FlashCard currentCard;

    //new card that is added to the deck
    private FlashCard newCard;

    // true = term is showing; false = definition is showing
    private boolean termShowing = true;

    private AddNewCard frame;

    private CardSet cardSet;
    private int cardIndex = 0;

    private ButtonPanel bPanel;
    private LabelPanel lPanel;

    private static JButton flipButton;
    private static JButton nextButton;
    private static JButton prevButton;
    private static JButton addCard;
    private static JButton deleteCard;
    private static JButton editButton;



    public FlashCardPanel(CardSet cardSet) {
        this.cardSet = cardSet;
        this.setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));

        term = cardSet.get(0).getTerm();
        definition = cardSet.get(0).getDefintion();
        currentCard = cardSet.get(0);

        createButtons();

        lPanel = new LabelPanel();
        bPanel = new ButtonPanel();

        add(lPanel);
        add(bPanel);


    }

    public FlashCardPanel() {
        this.setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
        add(lPanel);
        add(bPanel);
    }

    private class LabelPanel extends JPanel {

            public LabelPanel() {
                this.setLayout(new GridBagLayout());
                GridBagConstraints c = new GridBagConstraints();
                c.insets = new Insets(15,15,15,15);
                currentLabel = new JLabel(term);
                currentLabel.setText(cardSet.get(0).getTerm());


                c.fill = GridBagConstraints.HORIZONTAL;
                c.weightx = 0;
                c.gridx = 0;
                c.gridy = 0;
                add(editButton,c);



                c.fill = GridBagConstraints.HORIZONTAL;
                c.ipady = 0;
                c.gridwidth = 0;
                c.weightx = 0;
                c.gridx = 2;
                c.gridy = 0;
                add(flipButton,c);

                c.fill = GridBagConstraints.HORIZONTAL;
                c.ipady = 40;
                c.weightx = 0;
                c.gridwidth = 3;
                c.gridx = 1;
                c.gridy = 3;
                add(currentLabel,c);

            }       
    }
    private class ButtonPanel extends JPanel {

        public ButtonPanel() {
            this.setLayout(new GridLayout(2,2));
            add(prevButton);
            add(nextButton);
            add(addCard);
            add(deleteCard);
        }
    }

    /*
     * creates buttons for the panel. Should be called before
     * any subpanel is created.
     */
    private void createButtons()
    {
         flipButton = new JButton(" Flip Card ");
         flipButton.addActionListener(new ButtonListener());
         flipButton.setActionCommand("1");

         nextButton = new JButton(" Next Card ");
         nextButton.addActionListener(new ButtonListener());
         nextButton.setActionCommand("2");

         prevButton = new JButton(" Previous Card ");
         prevButton.addActionListener(new ButtonListener());
         prevButton.setActionCommand("3");

         addCard = new JButton(" Add Card ");
         addCard.addActionListener(new ButtonListener());
         addCard.setActionCommand("4");

         deleteCard = new JButton(" Delete Card ");
         deleteCard.addActionListener(new ButtonListener());
         deleteCard.setActionCommand("5");

         editButton = new JButton("Edit");
         editButton.addActionListener(new ButtonListener());
         editButton.setActionCommand("6");   
    }

    private class ButtonListener implements ActionListener
    {

        @Override
        public void actionPerformed(ActionEvent e) {


            int action = Integer.parseInt(e.getActionCommand());

            switch(action){

            case 1:
                flipCard();
                break;
            case 2:
                nextCard();
                break;
            case 3:
                previousCard();
                break;
            case 4:
                createFrame();
                break;
            case 5:
                deleteCard();
            case 6:
                createFrame(term,definition);
            }

        }

    }

    private void flipCard()
    {
        if (!cardSet.isEmpty()) {
        if (termShowing) {
            termShowing = false;
            currentLabel.setText(definition);
            }
        else {
            termShowing = true;
            currentLabel.setText(term);
            }
        }
        else {
            currentLabel.setText(NO_CARDS);
            term = "";
            definition = "";
            JOptionPane.showMessageDialog(this, "This set is empty");
        }
    }

    private void nextCard() 
    {
        if (!cardSet.isEmpty()) {
        if (cardIndex == cardSet.size()-1) 
            cardIndex = 0;
        else 
            cardIndex++;

        term = cardSet.get(cardIndex).getTerm();
        definition = cardSet.get(cardIndex).getDefintion();

        if(termShowing)
            currentLabel.setText(term);
        else 
            currentLabel.setText(definition);

        currentCard = cardSet.get(cardIndex);
        }
        else JOptionPane.showMessageDialog(this, "This set is empty");
    }

    private void previousCard()
    {
        if (!cardSet.isEmpty()) {
        if (cardIndex == 0) 
            cardIndex = cardSet.size()-1;
        else 
            cardIndex--;

        term = cardSet.get(cardIndex).getTerm();
        definition = cardSet.get(cardIndex).getDefintion();

        if(termShowing)
            currentLabel.setText(term);
        else
            currentLabel.setText(definition);

        currentCard = cardSet.get(cardIndex);
        }
        else JOptionPane.showMessageDialog(this, "This set is empty");
    }
    /*
     * adding a card
     */
    private void createFrame() {
        frame = new AddNewCard(100,100,this);
    }
    /*
     * editing an existing card
     */
    private void createFrame(String t, String d)
    {
        frame = new AddNewCard(100,100,this,t,d);
    }


    public void addNewCard(String t, String d) {
        newCard = new FlashCard(t,d);
        cardSet.add(newCard);
        if (cardSet.isEmpty()) currentLabel.setText(newCard.getTerm());
    }

    public void editCard(String t, String d) {
        currentCard.setTerm(t);
        currentCard.setDefinition(d);
        if (termShowing) currentLabel.setText(t);
        else currentLabel.setText(d);

    }

    /*
     * Deletes current card on display
     */
    private void deleteCard()
    {   

        if (!cardSet.isEmpty()) {
        // if on the last card of the set
        if (cardIndex == cardSet.size()-1) cardIndex--;

        cardSet.remove(currentCard);

        if (!cardSet.isEmpty()) {
            currentCard = cardSet.get(cardIndex);
            currentLabel.setText(cardSet.get(cardIndex).getTerm());
        }
        else currentLabel.setText(NO_CARDS);
        }
        else JOptionPane.showMessageDialog(this, "This set is empty");
    }


}

您有多种选择,包括:

  • 使用嵌套的 JPanel,每个都有自己的布局。例如,按钮可以放置在 GridLayout JPanel 中,然后放置在带有标签 BorderLayout.CENTER
  • 的 BorderLayout JPanel 中
  • 我建议将长定义文本显示在 JTextArea 中,而不是 JLabel 中。如果您使其不可编辑并删除边框,它可能看起来像 JLabel。
  • 如果你走这条路,你会想要在 JTextArea 上打开自动换行。
  • 您可以使用 CardLayout 将 JTextArea 与 JLabel(术语)交换。

请注意,对于以后的问题,请减少您的问题。例如,如果这是我的问题,我会创建类似于下面的代码,小型、独立、可运行并演示问题:

import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import javax.swing.*;

public class FlashCardPanel2 extends JPanel {
   private static final long serialVersionUID = 1L;
   private static final int PREF_W = 400;
   private static final int PREF_H = PREF_W;
   private JLabel currentLabel;
   private String term = "Term";
   private String definition = "Definition: This will be a very long String to "
         + "illustrate the problem that you are having, and to try to help you get "
         + "a solution";
   private JButton editButton = new JButton("Edit");
   private JButton flipButton = new JButton(new FlipAction("Flip"));

   public FlashCardPanel2() {
      this.setLayout(new GridBagLayout());
      GridBagConstraints c = new GridBagConstraints();
      c.insets = new Insets(15, 15, 15, 15);
      currentLabel = new JLabel(term);  

      c.fill = GridBagConstraints.HORIZONTAL;
      c.weightx = 0;
      c.gridx = 0;
      c.gridy = 0;
      add(editButton, c);

      c.fill = GridBagConstraints.HORIZONTAL;
      c.ipady = 0;
      c.gridwidth = 0;
      c.weightx = 0;
      c.gridx = 2;
      c.gridy = 0;
      add(flipButton, c);

      c.fill = GridBagConstraints.HORIZONTAL;
      c.ipady = 40;
      c.weightx = 0;
      c.gridwidth = 3;
      c.gridx = 1;
      c.gridy = 3;
      add(currentLabel, c);
   }

   @Override
   public Dimension getPreferredSize() {
      if (isPreferredSizeSet()) {
         return super.getPreferredSize();
      }
      return new Dimension(PREF_W, PREF_H);
   }

   private class FlipAction extends AbstractAction {
      public FlipAction(String name) {
         super(name);
         int mnemonic = (int) name.charAt(0);
         putValue(MNEMONIC_KEY, mnemonic);
      }

      @Override
      public void actionPerformed(ActionEvent e) {
         String text = currentLabel.getText();
         text = (text.equals(term)) ? definition : term;
         currentLabel.setText(text);
      }
   }

   private static void createAndShowGui() {
      JFrame frame = new JFrame("FlashCardPanel2");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(new FlashCardPanel2());
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

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

下面是 CardLayout、GridLayout 和 BorderLayout 的潜在解决方案:

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;

import javax.swing.*;

public class FlashCardPanel3 extends JPanel {
   private static final long serialVersionUID = 1L;
   private static final String CURRENT_LABEL = "current label";
   private static final String DEFINITION = "definition";
   private JLabel currentLabel;
   private JTextArea currentDefinitionArea = new JTextArea(6, 20);
   private CardLayout cardLayout = new CardLayout();
   private JPanel cardHolder = new JPanel(cardLayout);
   private String term = "Term";
   private String definition = "Definition: This will be a very long String to "
         + "illustrate the problem that you are having, and to try to help you get "
         + "a solution";
   private JButton editButton = new JButton("Edit");
   private JButton flipButton = new JButton(new FlipAction("Flip"));

   public FlashCardPanel3() {
      currentDefinitionArea.setOpaque(false);
      currentDefinitionArea.setText(definition);
      currentDefinitionArea.setWrapStyleWord(true);
      currentDefinitionArea.setLineWrap(true);
      currentDefinitionArea.setEditable(false);
      currentDefinitionArea.setFocusable(false);

      currentLabel = new JLabel(term, SwingConstants.CENTER);
      cardHolder.add(currentLabel, CURRENT_LABEL);
      cardHolder.add(new JScrollPane(currentDefinitionArea), DEFINITION);

      JPanel buttonPanel = new JPanel(new GridLayout(1, 2, 5, 0));

      buttonPanel.add(editButton);
      buttonPanel.add(flipButton);

      setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
      setLayout(new BorderLayout(5, 5));
      add(buttonPanel, BorderLayout.PAGE_START);
      add(cardHolder);
   }

   private class FlipAction extends AbstractAction {
      public FlipAction(String name) {
         super(name);
         int mnemonic = (int) name.charAt(0);
         putValue(MNEMONIC_KEY, mnemonic);
      }

      @Override
      public void actionPerformed(ActionEvent e) {
         // String text = currentLabel.getText();
         // text = (text.equals(term)) ? definition : term;
         // currentLabel.setText(text);
         cardLayout.next(cardHolder);
      }
   }

   private static void createAndShowGui() {
      JFrame frame = new JFrame("FlashCardPanel2");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(new FlashCardPanel3());
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

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