使用 Java pack() 方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25754454/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 08:37:42  来源:igfitidea点击:

Using Java pack() method

javaswinglayout-managerpack

提问by user3025756

I can't make the pack() method work. I tried several things. My code looks like this at the moment:

我无法使 pack() 方法起作用。我尝试了几件事。我的代码目前看起来像这样:

Class 1:

第一类:

public static void main( String[] args )
    {
    java.awt.EventQueue.invokeLater(new Runnable() {
        public void run()
        {
         JavaGui mygui = new JavaGui();
   //       mygui.setSize(1154, 753);
            mygui.setVisible(true);
            mygui.pack();

Class 2:

第 2 类:

public class JavaGui extends javax.swing.JFrame 
    {
    public JavaGui()
        {
        getContentPane().setLayout(null);
        ..
        getContentPane().add(panelLeft);
        ...
        getContentPane().add(panelRight);

I tried putting the pack method in everywhere, but it's not going to work with this way of adding gui elements. Any suggestions why? I also tried adding everything to a JFrame instead of the getContentPane(), but I can't make that work either.

我尝试将 pack 方法放在任何地方,但它不适用于这种添加 gui 元素的方式。任何建议为什么?我还尝试将所有内容添加到 JFrame 而不是 getContentPane(),但我也无法做到这一点。

回答by Hovercraft Full Of Eels

  1. Don't use null layouts together with pack(). The pack method tells the layout managers and components to size themselves optimally, and if you instead use null layouts, then the gui risks shrinking to a minimal size, since there is no layout to hold it together.
  2. Don't use null layouts at all for the most part. Using these risk your creating rigid GUI's that are almost impossible to extend, improve, debug.
  3. Don't use setSize(...)and pack(). The layouts mostly respect the preferred sizes of components, not their sizes.
  1. 不要将空布局与pack(). pack 方法告诉布局管理器和组件以最佳方式调整自己的大小,如果您改为使用空布局,那么 gui 有缩小到最小尺寸的风险,因为没有布局将其固定在一起。
  2. 大多数情况下根本不要使用空布局。使用这些风险会导致您创建几乎不可能扩展、改进和调试的僵化 GUI。
  3. 不要使用setSize(...)pack()。布局主要尊重组件的首选大小,而不是它们的大小。

Instead:

反而:

  1. Use a pleasing and sensible combination of nested JPanels, each using its own layout manager.
  2. Let the components and the layout managers size themselves.
  3. Then pack should help.
  4. The general order that I do is to add all components to the GUI, then call pack(), then setLocationByPlatform(true)(I think), then setVisible(true).
  1. 使用令人愉悦且合理的嵌套 JPanel 组合,每个 JPanel 都使用自己的布局管理器。
  2. 让组件和布局管理器自行调整大小。
  3. 然后打包应该会有所帮助。
  4. 我所做的一般顺序是将所有组件添加到 GUI,然后调用pack(),然后setLocationByPlatform(true)(我认为),然后setVisible(true).

For better help, please check out the Swing Layout Manager Tutorials.

如需更好的帮助,请查看Swing 布局管理器教程

Here are a couple examples to other questions on this site that use various layout managers:

以下是本网站上使用各种布局管理器的其他问题的几个示例:

回答by gantners

I would recommened beginners on building up swing guis to use a good ide with a builtin gui designer like eclipse and windowbuilder or netbeans with matisse. It will help you building up a prototype of your desired gui and gives you an insight how the layouting is done in the source code. Experiment with the differenet layouts and what is happening when some values are changed.

我会建议初学者构建 Swing gui,以使用带有内置 gui 设计器的好 ide,例如 eclipse 和 windowbuilder 或 netbeans with matisse。它将帮助您构建所需 gui 的原型,并让您深入了解如何在源代码中完成布局。尝试不同的布局以及更改某些值时发生的情况。

one does not simply build up a well behaving gui without understanding how the layout works, so doing the recommended tutorials and looking at examples as already posted by Hovercraft Full Of Eels is absolutely necessary.

在不了解布局如何工作的情况下,不能简单地构建一个行为良好的 gui,因此绝对有必要按照推荐的教程并查看 Hovercraft Full Of Eels 已经发布的示例。

For your case i just guess what you were up to. Because youre mentioning left and right panels i suggest a JSplitPane which let you divide your screen in two areas which are customizable in size and orientation.

对于你的情况,我只是猜测你在做什么。因为您提到了左右面板,所以我建议使用 JSplitPane,它可以让您将屏幕分为两个区域,这些区域的大小和方向可自定义。

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSplitPane;

public class JavaGui extends JFrame {

    //SerialVersionId http://stackoverflow.com/questions/285793/what-is-a-serialversionuid-and-why-should-i-use-it
    private static final long   serialVersionUID    = 1L;

    public static void main(String[] args) {
        //Calls to Gui Code must happen on the event dispatch thread that the gui does not get stuck
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new JavaGui().setVisible(true);
            }
        });
    }       

    public JavaGui() {
        // Set the desired size of the frame to determine the maximum size of its components
        setPreferredSize(new Dimension(1024, 768));

        // Set the default close operation, if press x on frame, destroy the frame and exit the application - others are just destroy the frame or just hide the
        // frame
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        // BorderLayout because we just need a centric gui with one component, here JSplitPane in full size
        getContentPane().setLayout(new BorderLayout(0, 0));

        // JsplitPane is a bit special as it depends on the divider location between both panels, for the sake of a small example we take the default -1,
        JSplitPane splitPane = new JSplitPane();
        // 0.5 divides extra space equally to left and right component when resizing the frame - so specifiying a size for the left and right component is not
        // necessary
        // use the divider location default -1 to let the width of the left component decide where the right component begins, in that case because of the
        // resize weight half and half
        splitPane.setDividerLocation(-1);
        splitPane.setResizeWeight(0.5);
        getContentPane().add(splitPane, BorderLayout.CENTER);

        // For the panels the same layout as default as the intention is not stated in your question
        JPanel leftPanel = new JPanel();
        splitPane.setLeftComponent(leftPanel);
        leftPanel.setLayout(new BorderLayout(0, 0));

        JPanel rightPanel = new JPanel();
        splitPane.setRightComponent(rightPanel);
        rightPanel.setLayout(new BorderLayout(0, 0));

        // Add a button Panel to the south for doing something - flow layout for letting the components flow to the right side
        JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
        getContentPane().add(buttonPanel, BorderLayout.SOUTH);

        // Close Button for closing the frame
        JButton btnExit = new JButton("Destroy this frame, but let application run");
        btnExit.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                dispose();
            }
        });
        buttonPanel.add(btnExit);

        // Set every component to its preferred size
        pack();

        // Make it visible
        setVisible(true);
    }
}

回答by Santiago Benoit

If you want your JFrameto work with a null layout, rearrange your code so that it looks like this:

如果您希望JFrame使用空布局,请重新排列您的代码,使其看起来像这样:

public class JavaGui extends javax.swing.JFrame 
{
public JavaGui()
{
    setMinimumSize(1154, 753); // Make sure you do setMinimumSize() instead of setSize() when using pack() so that the JFrame does not shrink to 0 size
    setLayout(null);
    add(panelLeft);
    add(panelRight);
    pack();
}
// Next is main method

Main:

主要的:

public static void main(String[] args)
{
java.awt.EventQueue.invokeLater(new Runnable() {
    public void run()
    {
        new JavaGui().setVisible(true);
        // Do not do any formatting for your JFrame here
    }
});

Before, you were modifying the JFrameafterit was set visible, so that usually does not work, except for pack(). All components and settings for your JFrameshould not be in the main method if you are using an anonymous inner class.

之前,您正在修改它设置为可见JFrame之后的内容,因此通常不起作用,除了 pack()。JFrame如果您使用匿名内部类,则您的所有组件和设置都不应该在 main 方法中。

You can also use other layouts. Null layouts are for getting pixels in precise locations, which is used for advanced GUI design such as creating a custom GUI, but it seems that you are making a generic GUI with JPanels. For this, I would recommend using a GridBagLayout, which keeps everything centered if the frame is resized and is easy to use. To use a GridBagLayout, you have to replace setLayout(null);with setLayout(new GridBagLayout());and set GridBagConstraints. Here is some example code of making a panel with a component and a GridBagLayout:

您也可以使用其他布局。空布局用于在精确位置获取像素,用于高级 GUI 设计,例如创建自定义 GUI,但似乎您正在使用 JPanel 制作通用 GUI。为此,我建议使用GridBagLayout,如果框架调整大小并且易于使用,它会使所有内容保持居中。要使用 a GridBagLayout,您必须替换setLayout(null);setLayout(new GridBagLayout());并设置GridBagConstraints。这是使用组件和 a 制作面板的一些示例代码GridBagLayout

JPanel pane = new JPanel(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
if (shouldFill) {
            //natural height, maximum width
            c.fill = GridBagConstraints.HORIZONTAL;
}
//For each component to be added to this container:
//...Create the component...
//...Set instance variables in the GridBagConstraints instance...
pane.add(theComponent, c);
// Source: Oracle Docs