【问题标题】:JButton Positioning IssuesJButton 定位问题
【发布时间】:2012-05-24 16:24:39
【问题描述】:

好的,我有一个 Jpanel,它在下图中使用覆盖布局显示为白色。它包含一个 ScrollPane,其中包含一个图像(“No Image Available”)和一个 JButton(“Comment”)。

我想将此按钮放置在 JPanel 的右下角。我尝试了多种布局方法,但似乎无法正常工作。按钮最多向东南方向移动大约 3/4,我不知道为什么。

非常感谢任何帮助..

【问题讨论】:

  • 你用的是什么布局管理器,能详细说说你试过的布局吗?
  • 容器面板使用覆盖布局,然后我添加标签(其中包含图像)和按钮。然后我尝试使用 button.setAlignmentX() 例如对齐按钮,但它不能正常工作。我也尝试使用 sprint 布局(因为这用于我的其余组件)但我又得到了奇怪的效果。就像它无法越过某个位置一样。
  • 如需尽快获得更好的帮助,请发帖SSCCE

标签: java swing layout jpanel jbutton


【解决方案1】:

您提到使用OverlayLayout;您希望按钮实际与图像重叠吗?

如果这对您不重要,请使用其他好的建议之一,因为它们更简单。但是,如果您真的希望按钮与图像重叠,这里有一个解决方案:使用JLayeredPane 将两个JPanels 分层,依次布置按钮和图像。不幸的是,JLayeredPane 没有布局管理器,因此每当调整 JLayeredPane 的大小时,都需要添加一个组件侦听器来调整 JPanels 的大小。

这是一个 SSCCE:

public class SSCCE {

    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        Container contentPane = frame.getContentPane();
        contentPane.setLayout(new BorderLayout());

        final JLayeredPane layeredPane = new JLayeredPane();
        contentPane.add(layeredPane,BorderLayout.CENTER);

        final JPanel btnPane = new JPanel(new GridBagLayout());
        btnPane.setOpaque(false);

        JButton btn = new JButton("Comment");
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.weightx = 1.0;
        gbc.weighty = 1.0;
        gbc.anchor = GridBagConstraints.SOUTHEAST;
        btnPane.add(btn,gbc);

        final JPanel lblPane = new JPanel(new GridBagLayout());
        lblPane.setBackground(Color.CYAN);

        JLabel lbl = new JLabel("No Image Available");
        gbc = new GridBagConstraints();
        gbc.weightx = 1.0;
        gbc.weighty = 1.0;
        gbc.anchor = GridBagConstraints.CENTER;
        lblPane.add(lbl,gbc);

        layeredPane.add(btnPane,0);
        layeredPane.add(lblPane,1);
        layeredPane.addComponentListener(new ComponentAdapter() {
            @Override
            public void componentResized(ComponentEvent e) {
                lblPane.setBounds(0, 0, layeredPane.getWidth(), layeredPane.getHeight());
                btnPane.setBounds(0, 0, layeredPane.getWidth(), layeredPane.getHeight());
            }
        });


        frame.setSize(300,200);
        frame.setVisible(true);
    }

}

【讨论】:

    【解决方案2】:

    使用不同的布局管理器有很多可能的解决方案。我不知道 OverlayLayout,但我喜欢 WindowBuilder Pro(免费):https://developers.google.com/java-dev-tools/wbpro/ 寻求 Swing 设计方面的帮助。

    使用它,我为您的问题编写了 SpringLayout 实现(如果没有 GUI 构建器,SpringLayout 似乎很难处理)。

    JPanel panel = new JPanel();
    SpringLayout sl_panel = new SpringLayout();
    panel.setLayout(sl_panel);
    
    JButton button = new JButton("Comments");
    sl_panel.putConstraint(SpringLayout.SOUTH, button, 0, SpringLayout.SOUTH, panel);
    sl_panel.putConstraint(SpringLayout.EAST, button, 0, SpringLayout.EAST, panel);
    panel.add(button);
    
    JScrollPane scrollPane = new JScrollPane();
    sl_panel.putConstraint(SpringLayout.NORTH, scrollPane, 5, SpringLayout.NORTH, panel);
    sl_panel.putConstraint(SpringLayout.WEST, scrollPane, 3, SpringLayout.WEST, panel);
    sl_panel.putConstraint(SpringLayout.SOUTH, scrollPane, 3, SpringLayout.SOUTH, panel);
    sl_panel.putConstraint(SpringLayout.EAST, scrollPane, 3, SpringLayout.EAST, panel);
    panel.add(scrollPane);
    
    JLabel lblNewLabel = new JLabel();
    lblNewLabel.setIcon(new ImageIcon(foo.class.getResource("sSdA3.png")));
    scrollPane.setViewportView(lblNewLabel);
    

    这是运行代码的图片:

    您可以看到按钮(我的,不是您的图片...)浮动在底部的滚动窗格上方。我们可以调整上面的边距,这样按钮就不会浮在滚动条的顶部,但这只是为了向您展示它在 z 轴上的位置。

    【讨论】:

    • 感谢您修复图片链接,@Bart。我不喜欢无图像用户限制。 :-)
    • 感谢 Nathaniel,使用 SpringLayout 我已成功定位按钮:Screenshot 但是我现在遇到了另一个问题。当我使用下一个/上一个按钮查看图像队列中的下一个/上一个图像时,我使用以下命令重绘标签:codepicLabel.setIcon(new ImageIcon(path));code 发生这种情况时,图标为正确更改为新图像,但按钮消失。我猜新图像是在按钮上绘制的。我该如何解决这个问题??
    • 没关系,我通过调用 button.repaint(); 解决了这个问题;谢谢
    【解决方案3】:

    在内容窗格的CENTER 位置添加第一个带有图像的JPanel 并将JPanel 的布局设置为FlowLayout.RIGHT 并将JButton 添加到其中,现在将此JPanel 添加到@内容窗格中BorderLayout 的 987654327@ 位置。看看这个例子

    import java.awt.*;
    import java.awt.event.*;
    import javax.imageio.ImageIO;
    import javax.swing.*;
    
    public class ApplicationCloseExample
    {   
        private Image image;
        private static final String HTML =
            "<html>" +
            "<style type'text/css'>" +
            "body, html { padding: 0px; margin: 0px; }" +
            "</style>" +
            "<body>" +
            "<img src='http://pscode.org/media/starzoom-thumb.gif'" +
            " width=320 height=240>" +
            "";
    
        private void displayGUI()
        {
            final JFrame frame = new JFrame("Application Close Example");
    
            frame.addWindowListener(new WindowAdapter()
            {
                public void windowClosing(WindowEvent we)
                {
                    int result = JOptionPane.showConfirmDialog(
                                    frame, "Do you want to Exit ?"
                                    , "Exit Confirmation : ", JOptionPane.YES_NO_OPTION);
                    if (result == JOptionPane.YES_OPTION)               
                        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    else if (result == JOptionPane.NO_OPTION)   
                        frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
                }
            });
    
            JPanel contentPane = new JPanel();
            contentPane.setOpaque(true);
            JLabel label = new JLabel(HTML);
            contentPane.add(label);
    
            JPanel bottomPanel = new JPanel();
            bottomPanel.setLayout(new FlowLayout(FlowLayout.RIGHT, 5, 5));
            JButton button = new JButton("Comment");
            bottomPanel.add(button);
    
            frame.getContentPane().add(contentPane, BorderLayout.CENTER);
            frame.getContentPane().add(bottomPanel, BorderLayout.PAGE_END);
    
            frame.pack();
            frame.setVisible(true);
        }
    
        public static void main(String... args)
        {
            SwingUtilities.invokeLater(new Runnable()
            {
                public void run()
                {
                    new ApplicationCloseExample().displayGUI();
                }
            });
        }
    }
    

    这是输出:

    【讨论】:

      【解决方案4】:

      我会建议您使用GridBagLayout 而不是默认布局。使用 GridBagLayout,您可以控制一切。
      这里有一个链接可以帮助你:how to use GridBagLayout

      【讨论】:

      • 谢谢,我会看看并报告。
      【解决方案5】:

      我会说一个JPanel 和一个BorderLayout,并在EAST 位置添加按钮,然后将该面板放在主容器中(带有BorderLayout)的SOUTH 位置。

      所以你得到:

      -------------
      |           |
      |           |
      |   Image   |
      |           |
      |-----------|
      |______Button
      

      【讨论】:

        【解决方案6】:

        检查SpringLayout。它允许您将元素定位到距组件的 NORTH、WEST、EAST 或 SOUTH 一定距离。您的代码将如下所示:

        SpringLayout layout = new SpringLayout();
        setLayout(layout);
        ...
        add(_button);
        ...
        layout.putConstraint(SpringLayout.EAST, _button, -20, SpringLayout.EAST, this);
        layout.putConstraint(SpringLayout.SOUTH, _button, -20, SpringLayout.SOUTH, this);
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-10-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-10-01
          • 1970-01-01
          • 1970-01-01
          • 2015-07-28
          相关资源
          最近更新 更多