java - 从其他类获取 JComponent 会改变帧大小

标签 java swing actionlistener jcombobox

您好,我尝试从其他类获取 jcomponent。组件正在显示,但我的框架大小发生了变化。

示例.java

public class Example extends JFrame{

  static JPanel panel = new JPanel();
  static A a = new A();
  static B b = new B();
  static JComboBox<String> combo = new JComboBox<>();   
  static String value;

     Example(){
        setSize(400, 400);
        combo.setBounds(450, 140, 50, 20);
        combo.addItem("");
        combo.addItem("a");
        combo.addItem("b");
        combo.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                value = (String) combo.getSelectedItem().toString();
                if(value.equals("a")){
                    panel.add(a.getLabel());
                    panel.remove(b.getLabel());
                    add(panel);
                    pack(); 
                }else if(value.equals("b")){
                    panel.add(b.getLabel());
                    panel.remove(a.getLabel());
                    add(panel);
                    pack();
                }
            }
        });
        panel.add(combo);
        this.add(panel);
        setVisible(true);
        }
}

A.java

public class A extends JFrame{

  JPanel panel = new JPanel();
  JLabel lab = new JLabel("Text");

  A(){
      lab.setBounds(280, 25, 150, 50);
      lab.setVisible(true);
      panel.add(lab);
      add(panel);
  }
  public  JLabel getLabel(){
    return lab;
  }
}

B.java

public class B extends JFrame{

    JPanel panel = new JPanel();
    JButton lab = new JButton("Hello");

    B(){
       lab.setBounds(380, 25, 250, 50);
       lab.setVisible(true);
       panel.add(lab);
       add(panel);
    }
    public JButton getLabel(){
       return lab;  
    }
}

Main.java

public class Main {
  public static void main(String [] agrs) {
    Example ex = new Example();
    ex.setVisible(true);
  }
}

当我按照定义的尺寸运行框架打开但当我从组合框中选择a时,框架尺寸会减少任何建议,以便屏幕尺寸保持不变。

最佳答案

解决这个问题的快速而肮脏的方法是摆脱 pack() 并替换 revalidate()repaint:

add(panel);
revalidate();
repaint();
// pack();
  • revalidate 告诉布局管理器重新布局其组件。
  • repaint 请求重新绘制组件,尤其是“脏”区域
  • pack 告诉窗口重新布局所有组件并将大小调整到最佳大小。

使用 CardLayout 会更好,窗口和组件大小将保持不变,足够大以适合最大的组件。 ...并避免使用空布局。

<小时/>

例如:

import java.awt.CardLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;

public class Example2 extends JPanel {
   public static final String[] COMBO_TEXTS = {"", "a", "b"};
   private static final int PREF_W = 400;
   private static final int PREF_H = PREF_W;
   private DefaultComboBoxModel<String > comboModel = new DefaultComboBoxModel<>(COMBO_TEXTS);
   private CardLayout cardLayout = new CardLayout();

   public Example2() {
      setLayout(cardLayout);
      ComboListener comboListener = new ComboListener();

      JComboBox<String> combo = new JComboBox<>(comboModel);
      combo.addActionListener(comboListener);;
      JPanel panelBlank = new JPanel();
      panelBlank.add(combo);

      JPanel panelWithText = new JPanel();
      combo = new JComboBox<>(comboModel);
      combo.addActionListener(comboListener);;
      panelWithText = new JPanel();
      panelWithText.add(combo);
      panelWithText.add(new JLabel("Text"));

      JPanel panelWithButton = new JPanel();
      combo = new JComboBox<>(comboModel);
      combo.addActionListener(comboListener);;
      panelWithButton = new JPanel();
      panelWithButton.add(combo);
      panelWithButton.add(new JButton("Hello"));

      add(panelBlank, COMBO_TEXTS[0]);
      add(panelWithText, COMBO_TEXTS[1]);
      add(panelWithButton, COMBO_TEXTS[2]);
   }

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

   private class ComboListener implements ActionListener {
      @Override
      public void actionPerformed(ActionEvent e) {
         JComboBox<String> combo = (JComboBox<String>)e.getSource();
         String item = combo.getSelectedItem().toString();
         cardLayout.show(Example2.this, item);
      }
   }

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

      JFrame frame = new JFrame("Example2");
      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();
         }
      });
   }
}

这让事情变得简单,也更难搬起石头砸自己的脚。所以而不是这个:

        public void actionPerformed(ActionEvent e) {
            value = (String) combo.getSelectedItem().toString();
            if(value.equals("a")){
                panel.add(a.getLabel());
                panel.remove(b.getLabel());
                // add(panel);
                // pack();
            }else if(value.equals("b")){
                panel.add(b.getLabel());
                panel.remove(a.getLabel());
                // add(panel);
                // pack();
            }
            add(panel);
            revalidate();
            repaint();
        }

你的ActionListener的actionPerformed方法就是这样的:

  public void actionPerformed(ActionEvent e) {
     JComboBox<String> combo = (JComboBox<String>)e.getSource();
     String item = combo.getSelectedItem().toString();
     cardLayout.show(Example2.this, item);
  }
<小时/>

有关 CardLayout、其用途和功能的更多信息,请查看 CardLayout Tutorial 。但简而言之,它自动化了 GUI 中交换“ View ”的过程,让你更难搬起石头砸自己的脚。

关于java - 从其他类获取 JComponent 会改变帧大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22436631/

相关文章:

java - 将一个类的字段变量作为参数传递给另一个类对象的创建?

java - Gradle 构建未完成

java - jvm异常捕获

java - 更改 Swing GUI 的边界和 JButton 的命名

Java JProgressBar 不通过 setVisible(true) 显示

java - 将 Action 监听器添加到在 java 循环中创建并从另一个类调用的新 jbutton

java - InetAddress 对象在调用 isAnyLocalAddress() 时如何返回 true?

java - JTree - 无法转换为 javax.swing.tree.MutableTreeNode

java - ActionListener 的语法错误

java - 如何将变量/对象从 Action 监听器传递到驱动程序类?