【问题标题】:unwanted space between jpanelsjpanels之间不需要的空间
【发布时间】:2012-10-12 06:04:14
【问题描述】:

我正在尝试创建一个 JPanel,它有 3 个组件排列成一行。它应该有一个彩色框、一个标签和一个删除按钮。

我将 JPanel 设置为 GridLayout,其中存储了一个用于彩色框的 JPanel、一个用于标签的 JLabel 和一个带有自定义 ImageIcon 的 JButton。

问题是彩色框和标签之间有一个空格。我已经突出显示了每个组件的边框,并且似乎没有任何组件被过度拉伸。

这是我的意思的截图:

这是我正在使用的代码: 标签类:

public class Label extends JPanel {

    JButton btnDeleteObject;
    // Delete icon
    ImageIcon delIcon = new ImageIcon("Delete.png"); 
    Image img = delIcon.getImage();
    Image newimg = img.getScaledInstance(28, 28,  java.awt.Image.SCALE_SMOOTH);  
    ImageIcon scaledDelIcon = new ImageIcon(newimg);

    Color labelColour;

    public Label(String labelName, Color labelColour) {
        this.labelColour = labelColour;

        setLayout(new BoxLayout(this, BoxLayout.X_AXIS));

        addComponents(labelName);

    }   

    private void addComponents(String labelName) {

        JPanel innerContainer = new JPanel(new GridLayout(1, 3));
        JLabel name = new JLabel(labelName);

        LabelColourBox cBox = new LabelColourBox();

        name.setMaximumSize(new Dimension(80, 40));
        name.setPreferredSize(new Dimension(80, 40));
        name.setSize(new Dimension(80, 40));

        name.setBorder(BorderFactory.createLineBorder(Color.blue));

        setBorder(BorderFactory.createLineBorder(Color.black));

//      name.setBorder(new EmptyBorder(5, 5, 5, 5));

        // Add action to delete button for Icon
        Action action = new AbstractAction("Button Label", scaledDelIcon) {
            // This method is called when the button is pressed
            public void actionPerformed(ActionEvent evt) {
                System.out.println("delete");
            }
        };

        btnDeleteObject = new JButton(action);

        // Remove label, background
        btnDeleteObject.setText("");
        btnDeleteObject.setContentAreaFilled(false);

        setAlignmentX(LEFT_ALIGNMENT);

        innerContainer.add(cBox);
        innerContainer.add(name);
        innerContainer.add(btnDeleteObject);

        add(innerContainer);

    }
}

这是LabelColourBox:

public class LabelColourBox extends JPanel{

    public LabelColourBox() {
        setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
    }


    @Override
    protected void paintComponent(Graphics g) {

        super.paintComponent(g);
        setBorder(BorderFactory.createLineBorder(Color.green));

        setMaximumSize(new Dimension(40, 40));
        setPreferredSize(new Dimension(40, 40));
        setSize(new Dimension(40, 40));

        g.setColor(Color.RED);
        g.fillRect(0, 0, 40, 40);
    }


}

【问题讨论】:

    标签: java swing jpanel


    【解决方案1】:
    1. 不要调用 setSize/setPreferredSize/setMaximumSize/setMinimumSize/setBounds/setLocation,使用适当的LayoutManager,这就是工作。
    2. 不要在paintComponent 中调用这些方法。 paintComponent() = 绘制组件,因此您应该只执行绘制操作(drawLine、drawRect、...)。
    3. GridLayout 通常不是一个非常灵活的布局,因为它根据最大的首选尺寸以相同的尺寸布置所有子组件。因此,在这种简单的情况下,看看 BorderLayout、GridBagLayout,甚至是 BoxLayout 和 FlowLayout。如果您可以使用第三方库,那么 MigLayout 就是您的朋友。

    【讨论】:

      【解决方案2】:

      正如 Guillaume 所指出的,您的代码存在一些严重问题。

      切勿在任何 paintXxx 方法中对任何 UI 组件进行任何更改

      protected void paintComponent(Graphics g) {
          super.paintComponent(g);
      
          // This is INCREDIBLY bad
          setBorder(BorderFactory.createLineBorder(Color.green));
          setMaximumSize(new Dimension(40, 40));
          setPreferredSize(new Dimension(40, 40));
          setSize(new Dimension(40, 40));
          //------------
      
          g.setColor(Color.RED);
          g.fillRect(0, 0, 40, 40);
      }
      

      这样做会导致重绘请求被发送到重绘管理器,该管理器最终将调用您的paintComponent,这将触发重绘请求......并与您的 CPU 说再见,因为它循环到 100% 并且您的程序变得无响应。

      您应尽可能避免致电setPreferred/Minimum/MaximumSize。让各个组件解决它。如果您正在自定义组件,请覆盖这些方法,它将阻止一些任性的开发人员更改您下面的组件的大小。

      您应该避免使用绝对值,尤其是在绘画时。

      g.fillRect(0, 0, 40, 40);
      

      这是非常危险的。如果这个组件被添加到BorderLayout 怎么办?它只会在组件的左上角绘制一个正方形...并不是很有用,而是使用getWidthgetHeight 作为您需要影响的区域的基础。您还需要考虑组件 Insets 以确保您的内容被绘制在可用的视觉范围内。

      这也意味着您可以更改组件的大小而无需重写整个代码段:P

      关于你的程序。使用更灵活的布局管理器。 GridLayout 创建一个统一的网格,在其中布局其组件...

      public class Main {
      
          public static void main(String[] args) {
              new Main();
          }
      
          public Main() {
              EventQueue.invokeLater(new Runnable() {
                  @Override
                  public void run() {
                      try {
                          UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                      } catch (ClassNotFoundException ex) {
                      } catch (InstantiationException ex) {
                      } catch (IllegalAccessException ex) {
                      } catch (UnsupportedLookAndFeelException ex) {
                      }
      
                      JFrame frame = new JFrame();
                      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                      frame.setLayout(new GridLayout(3, 1));
                      frame.add(new Label("One", Color.BLACK));
                      frame.add(new Label("Two", Color.BLACK));
                      frame.add(new Label("Three", Color.BLACK));
                      frame.pack();
                      frame.setVisible(true);
                  }
              });
          }
      
          public class Label extends JPanel {
      
              JButton btnDeleteObject;
              // Delete icon
              ImageIcon delIcon = new ImageIcon("Delete.png");
              Image img = delIcon.getImage();
              Image newimg = img.getScaledInstance(28, 28, java.awt.Image.SCALE_SMOOTH);
              ImageIcon scaledDelIcon = new ImageIcon(newimg);
              Color labelColour;
      
              public Label(String labelName, Color labelColour) {
                  this.labelColour = labelColour;
      
      //            setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
                  // Not sure why you want to do this, but this would
                  // be a more useful layout manager in the this context
                  // Personally, I would just layout the components directly onto
                  // this container...
                  setLayout(new BorderLayout());
      
                  addComponents(labelName);
      
              }
      
              private void addComponents(String labelName) {
      
      //            JPanel innerContainer = new JPanel(new GridLayout(1, 3));
                  JPanel innerContainer = new JPanel(new GridBagLayout());
                  JLabel name = new JLabel(labelName);
      
                  LabelColourBox cBox = new LabelColourBox();
      
      //            name.setMaximumSize(new Dimension(80, 40));
      //            name.setPreferredSize(new Dimension(80, 40));
      //            name.setSize(new Dimension(80, 40));
      
                  name.setBorder(BorderFactory.createLineBorder(Color.blue));
      
                  setBorder(BorderFactory.createLineBorder(Color.black));
      
      //      name.setBorder(new EmptyBorder(5, 5, 5, 5));
      
                  // Add action to delete button for Icon
                  Action action = new AbstractAction("Button Label", scaledDelIcon) {
                      // This method is called when the button is pressed
                      public void actionPerformed(ActionEvent evt) {
                          System.out.println("delete");
                      }
                  };
      
                  btnDeleteObject = new JButton(action);
      
                  // Remove label, background
                  btnDeleteObject.setText("");
                  btnDeleteObject.setContentAreaFilled(false);
      
                  setAlignmentX(LEFT_ALIGNMENT);
      
                  GridBagConstraints gbc = new GridBagConstraints();
                  gbc.gridx = 0;
                  gbc.gridy = 0;
                  gbc.fill = GridBagConstraints.BOTH;
      
                  innerContainer.add(cBox, gbc);
                  gbc.gridx++;
                  gbc.weightx = 1;
                  gbc.anchor = GridBagConstraints.WEST;
                  innerContainer.add(name, gbc);
                  gbc.gridx++;
                  gbc.weightx = 0;
                  innerContainer.add(btnDeleteObject, gbc);
      
                  add(innerContainer);
      
              }
      
              public class LabelColourBox extends JPanel {
      
                  public LabelColourBox() {
                      setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
                  }
      
                  @Override
                  public Dimension getPreferredSize() {
                      return new Dimension(40, 40);
                  }
      
                  @Override
                  public Dimension getMinimumSize() {
                      return getPreferredSize();
                  }
      
                  @Override
                  public Dimension getMaximumSize() {
                      return getPreferredSize();
                  }
      
                  @Override
                  protected void paintComponent(Graphics g) {
      
                      super.paintComponent(g);
      
                      // DON'T DO THIS, THIS IS A VERY BAD IDEA, THIS WILL RESULT
                      // IN A NEW REPAINT REQUEST BEING SENT TO THE REPAINT MANAGER
                      // CAUSE THIS METHOD TO BE CALLED AND NEW REPAINT REQUEST BEING...
                      // you get the idea..
                      //setBorder(BorderFactory.createLineBorder(Color.green));
                      //setMaximumSize(new Dimension(40, 40));
                      //setPreferredSize(new Dimension(40, 40));
                      //setSize(new Dimension(40, 40));
      
                      g.setColor(Color.RED);
                      g.fillRect(0, 0, getWidth() - 1, getHeight() - 1);
                      g.setColor(Color.GREEN);
                      g.drawRect(0, 0, getWidth() - 1, getHeight() - 1);
                  }
              }
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-10-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-05-06
        • 2014-01-27
        • 2020-08-20
        • 2011-06-28
        相关资源
        最近更新 更多