【问题标题】:How to layout multiple panels on a jFrame? (java)如何在 jFrame 上布局多个面板? (爪哇)
【发布时间】:2013-03-19 14:45:54
【问题描述】:

我正在制作自己的 java socket 游戏。我的游戏在全屏上画得很好(它说“在这里画图形”,但我现在画到整个jframe)。我想添加一个带有滚动条的文本框,用于显示 only 文本,不接受任何输入,另一个文本框从用户那里获取文本输入,然后添加一个按钮来发送文本,用于聊天目的。但是关于我的问题,我什至如何开始布局呢?我知道我需要一个布局,但是有人可以帮助我吗?这是我现在的代码(这段代码目前只设置了对整个屏幕的绘制,现在需要像上图那样划分屏幕):

public class Setup extends JFrame implements Runnable{
     JPanel panel;
     JFrame window;
     public Setup(Starter start, JFrame window){
         window.setSize(600,500);
         window.setLocationRelativeTo(null);
         window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
         window.setResizable(false);
         panel = new Display(start);
         this.window = window;
     }
     public void run(){
         window.getContentPane().add(panel);
         window.setBackground(Color.BLACK);
         window.setVisible(true);
     }
}

“new Display(start)” - 这扩展了 jpanel,它基本上是我绘制所有图形的地方。

此外,我看到人们在不同的面板中添加,但我不能让它们的大小相同。如图所示,“在此处绘制图形”面板是最大的,以此类推。

【问题讨论】:

    标签: java swing layout jframe jpanel


    【解决方案1】:

    JPanel 实际上只是一个容器,您可以在其中放入不同的元素(甚至是其他的JPanels)。因此,在您的情况下,我建议将一个大的JPanel 作为您窗口的某种主容器主面板您分配了一个适合您需要的Layout (here is an introduction to the layouts)。

    将布局设置到您的主面板后,您可以添加绘画面板和您想要的其他JPanel(例如其中包含文本的那些..)。

      JPanel mainPanel = new JPanel();
      mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
    
      JPanel paintPanel = new JPanel();
      JPanel textPanel = new JPanel();
    
      mainPanel.add(paintPanel);
      mainPanel.add(textPanel);
    

    这只是对所有子面板进行垂直(Y 轴)排序的示例。因此,如果您想要在 mainPanel 底部的其他一些东西(可能是一些图标或按钮)应该与另一个布局(如水平布局)一起组织,只需再次创建一个新的 JPanel 作为容器对于所有其他东西并设置setLayout(new BoxLayout(mainPanel, BoxLayout.X_AXIS)

    您会发现,布局非常严格,可能很难为您的面板找到最佳布局。所以不要放弃,阅读介绍(上面的链接)并查看图片 - 这就是我的做法:)

    或者您可以只使用 NetBeans 来编写您的程序。你有一个非常简单的可视化编辑器(拖放)来创建各种窗口和框架。 (事后才理解代码……有时很棘手。)

    编辑

    由于有很多人对这个问题感兴趣,我想提供一个完整的示例,说明如何布局 JFrame 以使其看起来像 OP 想要的那样。

    该类名为 MyFrame 并扩展了 swings JFrame

    public class MyFrame extends javax.swing.JFrame{
    
        // these are the components we need.
        private final JSplitPane splitPane;  // split the window in top and bottom
        private final JPanel topPanel;       // container panel for the top
        private final JPanel bottomPanel;    // container panel for the bottom
        private final JScrollPane scrollPane; // makes the text scrollable
        private final JTextArea textArea;     // the text
        private final JPanel inputPanel;      // under the text a container for all the input elements
        private final JTextField textField;   // a textField for the text the user inputs
        private final JButton button;         // and a "send" button
    
        public MyFrame(){
    
            // first, lets create the containers:
            // the splitPane devides the window in two components (here: top and bottom)
            // users can then move the devider and decide how much of the top component
            // and how much of the bottom component they want to see.
            splitPane = new JSplitPane();
    
            topPanel = new JPanel();         // our top component
            bottomPanel = new JPanel();      // our bottom component
    
            // in our bottom panel we want the text area and the input components
            scrollPane = new JScrollPane();  // this scrollPane is used to make the text area scrollable
            textArea = new JTextArea();      // this text area will be put inside the scrollPane
    
            // the input components will be put in a separate panel
            inputPanel = new JPanel();
            textField = new JTextField();    // first the input field where the user can type his text
            button = new JButton("send");    // and a button at the right, to send the text
    
            // now lets define the default size of our window and its layout:
            setPreferredSize(new Dimension(400, 400));     // let's open the window with a default size of 400x400 pixels
            // the contentPane is the container that holds all our components
            getContentPane().setLayout(new GridLayout());  // the default GridLayout is like a grid with 1 column and 1 row,
            // we only add one element to the window itself
            getContentPane().add(splitPane);               // due to the GridLayout, our splitPane will now fill the whole window
    
            // let's configure our splitPane:
            splitPane.setOrientation(JSplitPane.VERTICAL_SPLIT);  // we want it to split the window verticaly
            splitPane.setDividerLocation(200);                    // the initial position of the divider is 200 (our window is 400 pixels high)
            splitPane.setTopComponent(topPanel);                  // at the top we want our "topPanel"
            splitPane.setBottomComponent(bottomPanel);            // and at the bottom we want our "bottomPanel"
    
            // our topPanel doesn't need anymore for this example. Whatever you want it to contain, you can add it here
            bottomPanel.setLayout(new BoxLayout(bottomPanel, BoxLayout.Y_AXIS)); // BoxLayout.Y_AXIS will arrange the content vertically
    
            bottomPanel.add(scrollPane);                // first we add the scrollPane to the bottomPanel, so it is at the top
            scrollPane.setViewportView(textArea);       // the scrollPane should make the textArea scrollable, so we define the viewport
            bottomPanel.add(inputPanel);                // then we add the inputPanel to the bottomPanel, so it under the scrollPane / textArea
    
            // let's set the maximum size of the inputPanel, so it doesn't get too big when the user resizes the window
            inputPanel.setMaximumSize(new Dimension(Integer.MAX_VALUE, 75));     // we set the max height to 75 and the max width to (almost) unlimited
            inputPanel.setLayout(new BoxLayout(inputPanel, BoxLayout.X_AXIS));   // X_Axis will arrange the content horizontally
    
            inputPanel.add(textField);        // left will be the textField
            inputPanel.add(button);           // and right the "send" button
    
            pack();   // calling pack() at the end, will ensure that every layout and size we just defined gets applied before the stuff becomes visible
        }
    
        public static void main(String args[]){
            EventQueue.invokeLater(new Runnable(){
                @Override
                public void run(){
                    new MyFrame().setVisible(true);
                }
            });
        }
    }
    

    请注意,这只是一个示例,有多种布局窗口的方法。这完全取决于您的需求以及您是否希望内容可调整大小/响应。另一个非常好的方法是GridBagLayout,它可以处理相当复杂的布局,但学习起来也相当复杂。

    【讨论】:

    • 为什么需要EventQueue.invokeLater(...)new Example3().setVisible(true) 似乎可以自己正常工作。
    • 如果您想要一个全面的简短答案,请看这里:stackoverflow.com/a/22534931/896249
    【解决方案2】:

    您将需要使用许多布局管理器来帮助您实现所需的基本结果。

    查看A Visual Guide to Layout Managers 进行比较。

    您可以使用 GridBagLayout,但这是 JDK 中可用的最复杂(也是最强大)的布局​​管理器之一。

    您可以改用一系列复合布局管理器。

    我会将图形组件和文本区域放在一个 JPanel 上,使用 BorderLayout,图形组件位于 CENTER,文本区域位于 SOUTH 位置。

    我会使用 GridBagLayout 将文本字段和按钮放在单独的 JPanel 上(因为这是我能想到的最简单的实现您想要的结果的方法)

    我会将这两个面板放在第三个主面板上,使用BorderLayout,第一个面板位于CENTER,第二个位于SOUTH 位置。

    这就是我

    【讨论】:

    • 任何人都希望阐明投反对票的原因,我很想了解如何改进答案
    猜你喜欢
    • 2020-09-02
    • 1970-01-01
    • 2023-03-04
    • 1970-01-01
    • 2011-05-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多