Java Swing:宽度问题 [英] Java Swing: problems with width

查看:241
本文介绍了Java Swing:宽度问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在理解我的应用程序的行为时遇到了问题.我想创建一个简单的窗口( 1000x700px ),分为两个部分(分别为 250px 750px 宽度).我尝试了以下代码:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;

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

public class Example extends JFrame
{
    private static final long serialVersionUID = 1L;

    public Example()
    {
        this.setSize(1000, 700);
        this.setTitle("Example");
        this.setResizable(false);
        this.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));

        JPanel navigation_panel_wrap = new JPanel();
        JPanel content_panel_wrap = new JPanel();
        navigation_panel_wrap.setPreferredSize(new Dimension(250, 700));
        content_panel_wrap.setPreferredSize(new Dimension(750, 700));
        content_panel_wrap.setBackground(Color.green);
        navigation_panel_wrap.setBackground(Color.red);
        this.getContentPane().add(navigation_panel_wrap);
        this.getContentPane().add(content_panel_wrap);
    }

    public static void main(String[] args)
    {
        Example example = new Example();
        example.setVisible(true);
    }
}

如您所见,我手动为JFrame(FlowLayout而不是BorderLayout具有水平和垂直间隙为零)设置布局管理器.当然,我只能使用BorderLayout,而不是将add()方法与BorderLayout.EASTBorderLayout.WEST参数一起使用,但是我想了解FlowLayout的问题. 运行我的应用程序时,得到以下内容(没有绿色JPanel):

如果我减小例如content_panel_wrap的宽度并使其变为 744px 而不是 750px ,则一切正常. 所以问题是-这些奇怪的6像素是什么?我不确定该值是否在所有操作系统上都恒定,因此我想了解其来源.

解决方案

至于您的代码问题(+1到@Reimeus),调用pack()是解决方案. 根据文档:

使此窗口的大小适合所需的大小和布局 它的子组件.如果窗口和/或其所有者还没有 可显示的,在计算 首选大小. Window将在preferredSize之后验证 是计算出来的.

提示:

  • 不要不必要地扩展JFrame.
  • 在创建时使用事件调度线程并更改UI组件:

    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
          // create UI components etc here
        }
      });
    

  • 不要调用setPreferredSize()而不是覆盖组件的getPrefferedSize().
  • 不要在JFrame上调用setSize(...),而是在将其设置为可见之前调用JFrame#pack().
  • 别忘了调用JFrame#defaultCloseOperation(..),否则当JFrame关闭时,您的初始/EDT线程将不会终止.

以下是结合我的建议和您的代码的示例:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class Example {

    private final JFrame frame;

    public Example() {
        frame = new JFrame();
        frame.setTitle("Example");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//app exited when frame closes
        frame.setResizable(false);
        frame.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));

        JPanel navigation_panel_wrap = new JPanel() {
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(250, 700);
            }
        };
        JPanel content_panel_wrap = new JPanel() {
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(750, 700);
            }
        };

        content_panel_wrap.setBackground(Color.green);
        navigation_panel_wrap.setBackground(Color.red);

        frame.add(navigation_panel_wrap);
        frame.add(content_panel_wrap);
        //pack frame (size components to preferred size)
        frame.pack();
        frame.setVisible(true);//make frame visible
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new Example();
            }
        });
    }
}

I have problems with understanding the behavior of my application. I want to create a simple window (1000x700px), divided into two parts (250px and 750px width respectively). I tried the following code:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;

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

public class Example extends JFrame
{
    private static final long serialVersionUID = 1L;

    public Example()
    {
        this.setSize(1000, 700);
        this.setTitle("Example");
        this.setResizable(false);
        this.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));

        JPanel navigation_panel_wrap = new JPanel();
        JPanel content_panel_wrap = new JPanel();
        navigation_panel_wrap.setPreferredSize(new Dimension(250, 700));
        content_panel_wrap.setPreferredSize(new Dimension(750, 700));
        content_panel_wrap.setBackground(Color.green);
        navigation_panel_wrap.setBackground(Color.red);
        this.getContentPane().add(navigation_panel_wrap);
        this.getContentPane().add(content_panel_wrap);
    }

    public static void main(String[] args)
    {
        Example example = new Example();
        example.setVisible(true);
    }
}

As you can see I manually set layout manager for JFrame (FlowLayout instead of BorderLayout with zero horizontal and vertical gaps). Of course, I can just use BorderLayout and than use add() method with BorderLayout.EAST and BorderLayout.WEST parameters, but I want to understand what's wrong with FlowLayout. When I run my application, I get the following (no green JPanel):

If I decrease width of, for example, content_panel_wrap and make it 744px instead of 750px, everything works correctly. So the question is - what are these strange 6 pixels? I'm not sure this value is constant for all operating systems, so I want to understand its origin.

解决方案

As for your codes problem (+1 to @Reimeus) calling pack() is the solution. as per docs:

Causes this Window to be sized to fit the preferred size and layouts of its subcomponents. If the window and/or its owner are not yet displayable, both are made displayable before calculating the preferred size. The Window will be validated after the preferredSize is calculated.

Tips:

  • Dont extend JFrame unnecessarily.
  • Use Event Dispatch Thread when creating and changing UI components:

    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
          // create UI components etc here
        }
      });
    

  • Dont call setPreferredSize() rather override getPrefferedSize() of component.
  • Dont call setSize(...) on JFrame rather call JFrame#pack() before setting it visible.
  • Dont forget to call JFrame#defaultCloseOperation(..) or your initial/EDT thread will not be terminated when JFrame is closed.

Here is an example combining my advice and your code:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class Example {

    private final JFrame frame;

    public Example() {
        frame = new JFrame();
        frame.setTitle("Example");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//app exited when frame closes
        frame.setResizable(false);
        frame.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));

        JPanel navigation_panel_wrap = new JPanel() {
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(250, 700);
            }
        };
        JPanel content_panel_wrap = new JPanel() {
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(750, 700);
            }
        };

        content_panel_wrap.setBackground(Color.green);
        navigation_panel_wrap.setBackground(Color.red);

        frame.add(navigation_panel_wrap);
        frame.add(content_panel_wrap);
        //pack frame (size components to preferred size)
        frame.pack();
        frame.setVisible(true);//make frame visible
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new Example();
            }
        });
    }
}

这篇关于Java Swing:宽度问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆