【问题标题】:set custom location for a component in box layout在框布局中为组件设置自定义位置
【发布时间】:2016-03-25 19:57:59
【问题描述】:

我有一个框架,在这个框架内我有一个带有盒子布局的面板,在这个面板内我还有 4 个面板。

        mainFrame = new JFrame("Basket Game");
        mainPanel = new JPanel();
        mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));

        mainPanel.add(options);
        mainPanel.add(pname);
        mainPanel.add(info);
        mainPanel.add(gamearea);    

    mainFrame.setContentPane(mainPanel);
    mainFrame.pack();
    mainFrame.getContentPane().setBackground(Color.LIGHT_GRAY);
    mainFrame.setResizable(false);
    mainFrame.setVisible(true);
    mainFrame.setSize(600,600);

表格如下所示:

前 3 个面板对我来说没问题。但是对于最后一个面板(黑色),我想添加一些具有自定义坐标的组件。但是当我尝试使用自定义坐标添加它们时:

basket.setLocation(500, 500);
gamearea.add(basket);

它直接进入面板的顶部中心(坐标不影响它的位置)

当我将gameareIs 布局设置为null 时,我在面板上看不到我的标签。我想我应该为此做一些额外的事情。我该怎么做?

【问题讨论】:

  • 您的主窗口只有 600x600。带有标题栏、选项、玩家名称和信息,y=500 可能位于窗格底部。
  • 你了解布局管理器的工作原理吗?您了解布局管理器的职责吗?你了解谁重置 API 与布局管理器交互吗?如果你不这样做,那么 null 布局不是你正在寻找的选择。在几乎所有情况下,当您认为您想要一个空布局时,您可能不想要。在极少数情况下,null 布局可能有用,自定义布局会导致更少的问题和返工

标签: java swing layout-manager boxlayout


【解决方案1】:

问题不在于您的布局管理器 (null),也不在于遗漏任何内容。问题只是 500x500 超出了game area 的范围。

public class NullLayout {

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

    NullLayout() {
        JFrame frame = new JFrame("Basket Game");
        JPanel mainPanel = new JPanel();
        mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));

        for (int i = 0; i < 4; i++) {
            JPanel strip = new JPanel();
            strip.setMaximumSize(new Dimension(Integer.MAX_VALUE, 50));
            strip.setBorder(BorderFactory.createTitledBorder("Strip " + i));
            strip.add(new JLabel("Strip " + i));
            mainPanel.add(strip);
        }

        JPanel gamearea = new JPanel();
        gamearea.setLayout(null);
        mainPanel.add(gamearea);

        for (int i = 0; i < 5; i++) {
            int x = i * 100, y = i * 100;
            JPanel basket = new JPanel();
            basket.setSize(200, 50);
            basket.setLocation(x, y);
            basket.setBackground(Color.YELLOW);
            basket.add(new JLabel("x = " + x + ", y = " + y));
            gamearea.add(basket);
        }

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setContentPane(mainPanel);
        frame.pack();
        frame.setResizable(false);
        frame.setSize(600, 600);

        frame.setVisible(true);
    }
}

请注意,位于 400,400 的 Basket 未显示;它会在游戏区域的底部。

【讨论】:

    【解决方案2】:

    使用空布局几乎总是错误的。您应该使用 LayoutManager 来帮助将组件放置在您想要的位置 - 如果用户更改主框架的大小,则特别有用。使用 GridBag 或 Mig 布局。

    如果您绝对坚持使用空布局,请创建一个扩展 JPanel 的新 GameArea 类,覆盖其 paintComponent() 方法并使用 child.setBounds(...) 设置子级的位置。确保覆盖方法中的第一条语句是 super.paintComponent(g);

    【讨论】:

    • 另外,用户不能改变窗口的大小,因为mainFrame.setResizable(false);已经被调用了。
    • @AJNeufeld 它可能是“允许的”,但它非常不鼓励,任何时候你可能认为你需要它,你可能不需要它。整个 Swing API 都是围绕布局 API 编写的,丢弃会将大量责任推给开发人员,而大多数人还没有准备好处理它
    • 永远不要使用任何绘制方法的上下文更改 UI 的状态,这将设置一个无限循环的重绘请求,这将消耗您的 CPU 周期并使您的 UI 无响应
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多