布局管理

by admin on 2020年1月15日

在没使用布局管理器的情况下setLayout(null),可以通过调用setSize(),setLocation(),setBounds()来修改组件的大小、位置;

总结

  1. 初识 AWT

在使用了布局管理器的情况下,只能通过调用setPreferredSize()方法来修改组件的大小(长宽)。

布局的计算过程

  • 如果设置了最小尺寸(或者最小尺寸提示)、最大尺寸,则组件获取的空间不能超过这些限制
  • 如果没有设置尺寸限制,则组件会尽可能多的占据空间。如果有多个组件,则空间分配以拉伸因子为标准
  • 如果没有设置拉升因子,则以组件的尺寸策略 QWidget :: sizePolicy()
    和尺寸提示 QWidget :: sizeHint()
    为依据,在有多余空间的情况下,尽可能的占据多的空间。这也是组件的默认尺寸

      GUI 和 AWT

组件中对布局有影响的函数

一个组件要想影响布局管理,需要使用以下任何或全部机制:

  • 重新实现 QWidget :: sizeHint() 以返回小部件的首选大小。
  • 重新实现 QWidget :: minimumSizeHint()
    以返回小部件可以具有的最小尺寸。
  • 调用 QWidget :: setSizePolicy() 来指定窗口小部件的空间要求。

在上面的任何一个操作之后,都应调用 QWidget :: updateGeometry()
,这将导致布局重新计算。即使多次连续调用 QWidget :: updateGeometry()
也只会进行一次布局重新计算。

如果 Widget
的高度依赖于其宽度(例如,具有自动断字的标签),请在窗口小部件的大小策略中设置
height-for-width 标志,并重新实现 QWidget :: heightForWidth() 函数。

即使实现 QWidget :: heightForWidth() ,提供一个合理的
sizeHint()仍然是一个好主意。

GUI:Graphics User Interface  图形用户界面

自定义布局管理器

要编写自己的布局类,必须定义以下内容:

  • 一个用于存储被管理组件的数据结构,其中项是 QLayoutItem 类型
    ,一般使用列表。
  • addItem(),如何添加项目到布局。
  • setGeometry(),如何执行布局。
  • sizeHint(),布局的首选大小。
  • itemAt(),如何迭代布局。
  • takeAt(),如何从布局中删除项目。
  • 在大多数情况下,您还将实现 minimumSize()

Qt 布局系统提供了一种简单而强大的方式,可以在 Widget
中自动排列子元素,以确保它们充分利用可用空间。

AWT:Abstract Window Toolkit  抽象窗口工具集

简介

Qt 包括一组布局管理类,用于描述在应用程序的用户界面中如何布局 Widget。
当可用的空间发生变化时,这些布局会自动定位和调整 Widget
的大小,确保它们一致地排列,并且整个用户界面保持可用。

所有 QWidget 的子类都可以使用布局来管理他们的子元素,
QWidget :: setLayout() 函数将一个 Layout 应用于 Widget,
当以这种方式在 Widget 上设置了一个 Layout 时,Layout 负责以下任务:

  • 子元素的定位。
  • 合理的窗口默尺寸。
  • 合理的的窗口最小尺寸。
  • 调整大小处理
  • 内容变化时自动更新:
    • 字体大小,文本或子元素的其他内容。
    • 隐藏或显示一个 Widget
    • 删除子元素

之前的程序输出结果均在控制台上显示,现在学习AWT后,可以编程显示图形用户界面。

Qt 的布局类

省略……

抽象窗口工具包AWT (Abstract Window Toolkit)
是 API为Java 程序提供的建立图形用户界面GUI (Graphics User
Interface)工具集,之所以叫抽象窗口工具集,是因为该图形用户界面可以与系统无关,可以跨平台AWT可用于Java的applet和applications中,它支持图形用户界面编程。

水平、竖直、网格以及表格布局

为 Widget 设置布局的最简单方法是使用内置的布局管理器:QHBoxLayout
QVBoxLayoutQGridLayoutQFormLayout ,这些类继承自
QLayoutQLayout 又来自 QObject (而不是 QWidget ),
他们负责一组 Widgets 的几何管理。
要创建更复杂的布局,可以将布局管理器嵌套在一起。

  • QHBoxLayout 从左到右(或从右到左)横向排列出 Widget。

    图片 1

    img

  • QVBoxLayout 从上到下在垂直排列 Widget

    图片 2

    img

  • QGridLayout 在二维网格中显示 Widget,一个 小部件可以占用多个单元格

    图片 3

    img

  • QFormLayout 在以两列描述性的“标签-字段样式” 样式布局 Widget

    图片 4

    img

  • 功能包括:

    用户界面组件;

用代码布局 Widget

以下代码用一个 QHBoxLayout 管理五个 QPushButton
的几何特征,如上图第一个截图所示:

QWidget *window = new QWidget;

// 创建五个按钮
QPushButton *button1 = new QPushButton("One");
QPushButton *button2 = new QPushButton("Two");
QPushButton *button3 = new QPushButton("Three");
QPushButton *button4 = new QPushButton("Four");
QPushButton *button5 = new QPushButton("Five");

// 创建布局管理器
QHBoxLayout *layout = new QHBoxLayout;

// 将按钮添加到布局中
layout->addWidget(button1);
layout->addWidget(button2);
layout->addWidget(button3);
layout->addWidget(button4);
layout->addWidget(button5);

// 设置布局
window->setLayout(layout);

window->show();

除了布局类本身不同之外,QVBoxLayout 的使用方式是相同的。 QGridLayout
的代码有一些不同,因为我们需要指定 Widget 的行和列位置:

QWidget *window = new QWidget;

// 创建五个按钮
QPushButton *button1 = new QPushButton("One");
QPushButton *button2 = new QPushButton("Two");
QPushButton *button3 = new QPushButton("Three");
QPushButton *button4 = new QPushButton("Four");
QPushButton *button5 = new QPushButton("Five");

// 创建布局管理器
QGridLayout *layout = new QGridLayout;

// 将按钮添加到布局中
layout->addWidget(button1, 0, 0);
layout->addWidget(button2, 0, 1);
// 注意:这个按钮占用两个单元
layout->addWidget(button3, 1, 0, 1, 2);
layout->addWidget(button4, 2, 0);
layout->addWidget(button5, 2, 1);

// 设置布局
window->setLayout(layout);

window->show();

第三个 QPushButton 跨越两列,需要为 QGridLayout :: addWidget()
指定第四和第五个参数。

QFormLayout 在每一行上添加两个 Widget ,通常是 QLabelQLineEdit
,用来创建表单。 在同一行添加 QLabelQLineEdit 会将 QLineEdit
设置为 QLabel 的伙伴控件。 以下代码将使用 QFormLayout 在三行上放置
QPushButtons 和相应的 QLineEdit

QWidget *window = new QWidget;

QPushButton *button1 = new QPushButton("One");
QLineEdit *lineEdit1 = new QLineEdit();
QPushButton *button2 = new QPushButton("Two");
QLineEdit *lineEdit2 = new QLineEdit();
QPushButton *button3 = new QPushButton("Three");
QLineEdit *lineEdit3 = new QLineEdit();

// 创建表格布局
QFormLayout *layout = new QFormLayout;

// 一组一组的将按钮和编辑器放到布局中
layout->addRow(button1, lineEdit1);
layout->addRow(button2, lineEdit2);
layout->addRow(button3, lineEdit3);

window->setLayout(layout);
window->show();

事件处理模型;

使用布局的一些提示

使用布局时,创建 Widget 不需要传递父对象,布局管理器会自动重新设置
Widget 的父对象(使用
QWidget :: setParent()),让它们称为设置了布局管理器的那个 Widget
的子元素。

注意:布局中的管理的 Widget 是设置布局的 Widget
的子节点,而不是布局本身的子节点, Widget 只能将其他 Widget
作为父类而不是布局。

可以在布局上使用 addLayout() 嵌套布局,内部布局外部布局的子元素

图形和图像工具,包括形状、颜色和字体类;

将 Widget 添加到布局中

当您将 Widget 添加到布局中时,过程如下:

  1. 所有的 Widget 最初将根据其 QWidget :: sizePolicy()
    QWidget :: sizeHint() 分配一定的空间。
  2. 如果 Widget
    设置了大于零的拉伸因子,则按照其拉伸因子的比例分配空间(如下所述)。
  3. 如果 Widget 的拉伸因子设置为零,则只有在其他 Widget
    不需要空间的情况下才会获得更多的空间。其中,首先将空间分配给具有
    Expanding 策略的小部件。
  4. 分配的空间小于其最小尺寸的
    Widget(如果没有指定最小尺寸,则为最小尺寸提示)将分配其所需的最小尺寸。
    (Widget
    不一定非要设置最小尺寸或最小尺寸提示,在这种情况下,拉伸因子是其决定因素。)
  5. 分配的空间大于其最大尺寸的 Widget 都将分配其所需的最大尺寸。
    (小部件不一定非要设置最大尺寸,在这种情况下,拉伸因子是其决定因素。)

布局管理器,可以进行灵活的窗口布局而与特定窗口的尺寸和屏幕分辨率无关;

拉伸因子

Widget 创建的时候一般没有设置拉伸因子。
当它们被放到布局管理器中时,Widget 将根据其 QWidget :: sizePolicy()
或其最小大小提示给予一定的空间份额,以较大者为准。
拉伸因子用于改变彼此占据空间的比例

如果将三个没有设置拉伸因子的 Widget 放到 QHBoxLayout
布局中,我们将得到如下布局:

图片 5

img

如果我们对每个 Widget
设置拉伸因子,它们将按比例(但不得小于其最小大小提示)布局。

图片 6

img

数据传送类,可以通过本地平台的剪贴板来进行剪切和粘贴。

自定义组件的布局

当您创建自己的 Widget 类时,还应该处理其布局属性。如果 Widget 使用 Qt
的布局之一,这已经被处理了。如果 Widget
没有任何子部件,也没有使用手动布局,则可以使用以下任何或全部机制更改窗口小部件的行为:

  • 重新实现 QWidget :: sizeHint() 以返回小部件的首选大小。
  • 重新实现 QWidget :: minimumSizeHint()
    以返回小部件可以具有的最小尺寸。
  • 调用 QWidget :: setSizePolicy() 来指定窗口小部件的空间要求。

每当大小提示、最小大小提示或大小策略更改时,都应调用
QWidget :: updateGeometry() ,这将导致布局重新计算。即使多次连续调用
QWidget :: updateGeometry() 也只会进行一次布局重新计算。

如果您的小部件的首选高度依赖于其实际宽度(例如,具有自动断字的标签),请在窗口小部件的大小策略中设置
height-for-width 标志,并重新实现 QWidget :: heightForWidth() 函数。

即使实现 QWidget :: heightForWidth() ,提供一个合理的
sizeHint()仍然是一个好主意。

有关实施这些功能的进一步指导,请参阅Qt季刊文章 《宽度的交易高度》。

  • java.awt包

布局可能出现问题

在 Label 组件中使用富文本可能会在其父窗口的布局中引入一些问题,当 Label
设置了 “word wrapped” 时,布局管理器会发生问题。

在某些情况下,布局被设置为 QLayout :: FreeResize
模式,这意味着它不会调整其内容的布局以适合较小尺寸的窗口,甚至会阻止用户将窗口变小。
这个问题可以通过对有问题的小部件进行子类化,并实现适当的 sizeHint()
minimumSizeHint() 函数来克服。

在某些情况下,Widget 必须有布局才能被使用。 当您为 QDockWidget
QScrollArea (使用 QDockWidget :: setWidget()
QScrollArea :: setWidget() )设置 Widget 时,必须已在 Widget
上设置布局。 如果没有,该 Widget 将不可见。

java.awt包中提供了GUI设计所使用的类和接口。
java.awt包提供了基本的java程序的GUI设计工具。主要包括下述三个概念:

手动布局

如果您正在制作独一无二的特殊布局,可以按照上述方式制作自定义 Widget 。
QWidget :: resizeEvent() 中计算所需的空间,并调用每个子元素上调用
setGeometry()

当需要重新计算布局时,Widget 将接收到一个 QEvent :: LayoutRequest
的事件对象。 可以在 QWidget :: event() 中处理
QEvent :: LayoutRequest 事件。

组件–Component
容器–Container
布局管理器–LayoutManager

如何编写自定义布局管理器

手动布局的替代方法是通过对 QLayout 进行子类化来编写自己的布局管理器。
边框布局和流程布局示例显示了如何做到这一点。

我们在这里详细介绍一个例子。 CardLayout 类收到来自同名的 Java
布局管理器的启发。 它将 Widget 放在彼此之上,每个 Item 偏移
QLayout :: spacing() 距离

要编写自己的布局类,您必须定义以下内容:

  • 用于存储被布局处理的组件的数据结构。 每个组件都是一个QLayoutItem
    , 在这个例子中我们将使用一个 QList
  • addItem(),如何添加项目到布局。
  • setGeometry(),如何执行布局。
  • sizeHint(),布局的首选大小。
  • itemAt(),如何迭代布局。
  • takeAt(),如何从布局中删除项目。
  • 在大多数情况下,您还将实现 minimumSize()

#ifndef CARD_H
#define CARD_H

#include <QtWidgets>
#include <QList>

class CardLayout : public QLayout
{
public:
    CardLayout(QWidget *parent, int dist): QLayout(parent, 0, dist) {}
    CardLayout(QLayout *parent, int dist): QLayout(parent, dist) {}
    CardLayout(int dist): QLayout(dist) {}
    ~CardLayout();

    void addItem(QLayoutItem *item);
    QSize sizeHint() const;
    QSize minimumSize() const;
    int count() const;
    QLayoutItem *itemAt(int) const;
    QLayoutItem *takeAt(int);
    void setGeometry(const QRect &rect);

private:
    QList<QLayoutItem*> list;
};

#endif

实现文件 card.cpp

//#include "card.h"

首先得定义一个 count() 函数来获得列表中的项数

int CardLayout::count() const
{
    // QList::size() returns the number of QLayoutItems in the list
    return list.size();
}

然后重写 itemAt()takeAt()
这两个函数,这些函数在布局系统内部用于处理 Widget
的删除,当然,程序员也可以直接使用它们。

itemAt() 返回给定索引处的 Item 。 takeAt() 删除给定索引处的 Item
,并返回它。 这里,我们使用列表索引作为布局索引。
在其他情况下,我们有一个更复杂的数据结构,我们可能需要花费更多的精力为
Item 定义线性顺序。

QLayoutItem *CardLayout::itemAt(int idx) const
{
    // QList::value() performs index checking, and returns 0 if we are
    // outside the valid range
    return list.value(idx);
}

QLayoutItem *CardLayout::takeAt(int idx)
{
    // QList::take does not do index checking
    return idx >= 0 && idx < list.size() ? list.takeAt(idx) : 0;
}

addItem() 为布局 Item 实现了默认放置策略,这个函数必须被实现,他会被
QLayout :: add() 使用。
如果您的布局具有需要参数的高级放置选项,则必须提供额外的访问函数,例如还来间距
QGridLayout :: addItem()QGridLayout :: addWidget()
QGridLayout :: addLayout() 的重载

void CardLayout::addItem(QLayoutItem *item)
{
  list.append(item);
}

注意:QLayoutItem 不是继承自 QObject 因此,必须手动销毁

 CardLayout::~CardLayout()
  {
       QLayoutItem *item;
       while ((item = takeAt(0)))
           delete item;
  }

setGeometry() 实际计算各个组件的位置和尺寸,如果需要,计算的时候可以将
spacing() 考虑进去,但是不考虑 margin()

void CardLayout::setGeometry(const QRect &r)
{
  QLayout::setGeometry(r);

  if (list.size() == 0)
      return;

  int w = r.width() - (list.count() - 1) * spacing();
  int h = r.height() - (list.count() - 1) * spacing();
  int i = 0;
  while (i < list.size()) {
      QLayoutItem *o = list.at(i);
      QRect geom(r.x() + i * spacing(), r.y() + i * spacing(), w, h);
      o->setGeometry(geom);
      ++i;
  }
}

sizeHint()minimumSize() 的实现非常类似,他们都可以考虑
spacing() 但是不考虑 margin()

QSize CardLayout::sizeHint() const
{
  QSize s(0,0);
  int n = list.count();
  if (n > 0)
          s = QSize(100,70); //start with a nice default size
      int i = 0;
      while (i < n) {
          QLayoutItem *o = list.at(i);
          s = s.expandedTo(o->sizeHint());
          ++i;
      }
      return s + n*QSize(spacing(), spacing());
  }

  QSize CardLayout::minimumSize() const
  {
      QSize s(0,0);
      int n = list.count();
      int i = 0;
      while (i < n) {
          QLayoutItem *o = list.at(i);
          s = s.expandedTo(o->minimumSize());
          ++i;
      }
      return s + n*QSize(spacing(), spacing());
  }
  • 组件、容器和布局管理器

其他注意事项

  • 此自定义布局不处理宽度的高度。
  • 我们忽略了 QLayoutItem :: isEmpty()
    这意味着布局会将隐藏的小部件视为可见的。
  • 对于复杂的布局,通过缓存计算值可以大大提高速度。 在这种情况下,实现
    QLayoutItem :: invalidate() 来标记缓存的数据是脏的。
  • 调用 QLayoutItem :: sizeHint() 等可能是昂贵的。
    因此,如果您稍后在同一功能中再次需要,您应该将该值存储在局部变量中。
  • 你不应该在同一个函数的同一个项目上调用
    QLayoutItem :: setGeometry() 两次。
    如果该项目具有多个子窗口小部件,则此调用可能非常昂贵,因为布局管理器必须每次执行完整的布局。
    而是计算几何体,然后进行设置。
    (这不仅适用于布局,如果您实现自己的resizeEvent()
    ,则应该这样做)。

 组件    

     
Java的图形用户界面的最基本组成部分是组件(Component),组件是一个可以以图形化的方式显示在屏幕上并能与用户进行交互的对象,例如一个按钮,一个标签等。组件不能独立地显示出来,必须将组件放在一定的容器中才可以显示出来。

常用组件:

      Button 按钮:

      label 标签
:显示文字内容

      TextField 文本框
:接受用户输入

     
这些组件都被封装成类,编程时进行实例化被直接调用。

  类java.awt.Component是许多组件类的父类,Component类中封装了组件通用的方法和属性,如图形的组件对象、大小、显示位置、前景色和背景色、边界、可见性等,因此许多组件类也就继承了Component类的成员方法和成员变量,相应的成员方法包括:

       
getComponentAt(int x, int y)
   getFont()
   getForeground()
   getName()
   getSize()
   paint(Graphics g)
   repaint()
   update()
   setVisible(boolean b)
   setSize(Dimension d)
   setName(String name)等

容器

 

     
容器(Container)也是一个类,实际上是Component的子类,因此容器本身也是一个组件,具有组件的所有性质,但是它的主要功能是容纳其它组件和容器。

常用容器
  容器java.awt.Container是Component的子类,一个容器可以容纳多个组件,并使它们成为一个整体。容器可以简化图形化界面的设计,以整体结构来布置界面。所有的容器都可以通过add()方法向容器中添加组件。

  有三种类型的容器:Window、Panel、ScrollPane,常用的有Panel, Frame,
Applet。

 1.Frame 窗口
     继承关系

  

图片 7

  • 程序实现

    public class Demo01 {

    public static void main(String[] args) {
        Frame frame = new Frame("我的第一个窗口");
        frame.setBounds(50, 50, 300, 200);//设置Frame 的大小,距离windows界面上左均为50,宽和高分别为300 200
        frame.setBackground(Color.PINK);
        frame.setVisible(true);//设置Frame为可见
    
    }
    

    }

Output:

图片 8

 

     
一般我们要生成一个窗口,通常是用Window的子类Frame来进行实例化,而不是直接用到Window类。Frame的外观就像我们平常在windows系统下见到的窗口,有标题、边框、菜单、大小等等。每个Frame的对象实例化以后,都是没有大小和不可见的,因此必须调用setSize(
)来设置大小,调用setVisible(true)来设置该窗口为可见的。

  另外,AWT在实际的运行过程中是调用所在平台的图形系统,因此同样一段AWT程序在不同的操作系统平台下运行所看到的图形系统是不一样的。例如在windows下运行,则显示的窗口是windows风格的窗口;而在UNIX下运行时,则显示的是UNIX风格的窗口。

  1. Panel 面板

  图片 9

 

  • 程序实现

    public class Demo02 {

    public static void main(String[] args) {
        Frame frame = new Frame("我的panel 界面");
        frame.setBounds(50, 50, 500, 300);
        Panel panel = new Panel();
        panel.setBackground(Color.pink);
        //panel.setBounds(0, 0, 200, 100); 如果要用 panel将整个窗口分块,则要用到布局管理器,不可直接调用实现
    
        frame.add(panel);
        frame.setVisible(true);
    
    }
    

    }

Output:

图片 10

 

Panel 可以作为容器容纳其他组件,但不可以像Frame
一样独立存在,必须将其添加到其他容器其中。

  • 简单的用户登陆界面的代码实现

    public class Demo03 {

    public static void main(String[] args) {
        Frame frame = new Frame("用户登入窗口");
        frame.setBounds(50, 50, 400, 100);
    
        Panel panel = new Panel();
        panel.setBackground(Color.pink);
        frame.add(panel);
    
        Label lable = new Label("用户名");
        TextField textField = new TextField("请输入用户名",20);//20为文本框长度
        Button loginbtn = new Button("确定");
    
        panel.add(lable);
        panel.add(textField);
        panel.add(loginbtn);
    
        frame.setVisible(true);
    }
    

    }

Output:

图片 11

 

      需要注意的是,Lebel 、TextField、
Button这些组件的添加是有顺序的,以上是一个简单的界面,比较复杂的情况则要使用布局管理器来实现。
并且以上的代码比较简单,实现的只是最基本的显示功能,并不能进行实际的登陆与关闭操作。

  布局管理器(LayoutManager):每个容器都有一个布局管理器,当容器需要对某个组件进行定位或判断其大小尺寸时,就会调用其对应的布局管理器。

为了使我们生成的图形用户界面具有良好的平台无关性,Java语言中,提供了布局管理器这个工具来管理组件在容器中的布局,而不使用直接设置组件位置和大小的方式。

     
布局管理器主要包括:FlowLayout,BorderLayout,GridLayout,CardLayout,GridBagLayout

1.
FlowLayout(流布局)

  FlowLayout
是Panel,Applet的缺省布局管理器(默认布局管理器)。其组件的放置规律是从上到下、从左到右进行放置,如果容器足够宽,第一个组件先添加到容器中第一行的最左边,后续的组件依次添加到上一个组件的右边,如果当前行已放置不下该组件,则放置到下一行的最左边。

      FlowLayout(FlowLayout.RIGHT,20,40);
  /*第一个参数表示组件的对齐方式,指组件在这一行中的位置是居中对齐、居右对齐还是居左对齐,第二个参数是组件之间的横向间隔,第三个参数是组件之间的纵向间隔,单位是象素。*/
  FlowLayout(FlowLayout.LEFT);
  //居左对齐,横向间隔和纵向间隔都是缺省值5个象素
  FlowLayout();
  //缺省的对齐方式居中对齐,横向间隔和纵向间隔都是缺省值5个象素

  • 代码实现

    public static void main(String[] args) {
        Frame frame = new Frame("FlowLayout");
        frame.setBounds(100, 100, 400, 300);
        frame.setLayout(new FlowLayout());
    
        Button but1 = new Button("button1");
        Button but2 = new Button("button2");
        Button but3 = new Button("button3");
        Button but4 = new Button("button4");
        Button but5 = new Button("button5");
    
        but1.setBackground(Color.blue);
        but2.setBackground(Color.yellow);
        but3.setBackground(Color.red);
        but4.setBackground(Color.green);
        but5.setBackground(Color.pink);
    
        frame.add(but1);
        frame.add(but2);
        frame.add(but3);
        frame.add(but4);
        frame.add(but5);
    
        frame.setVisible(true);
    
    }
    

    }

Output:

图片 12

     
流布局与麻将布局的不同在于麻将布局要自己设置东西南北中的位置布局,而流布局则是按照按钮的调用先后顺序依次排列。默认居中排列,如果要设置为居左或居右排列,只需实例化FlowLayout
,用其实例对象 fl 调用设置队列的方法,将其设置为居左。

即FlowLayout fl = new FlowLayout();
   fl.setAlignment(FlowLayout.LEFT);
   frame.setLayout(fl);

图片 13

上图为居左放置。

2.
BorderLayout(麻将布局)

  BorderLayout
是Window,Frame和Dialog的缺省(默认)布局管理器。BorderLayout布局管理器把容器分成5个区域:North,South,East,West和Center,每个区域只能放置一个组件。各个区域的位置及大小如下图所示:

    图片 14

  • 代码实现

    public class Demo04 {

    public static void main(String[] args) {
        Frame frame = new Frame("BorderLayt");
        frame.setBounds(100, 100, 400, 300);
        //设置 frame 的布局为BorderLayout
        frame.setLayout(new BorderLayout());
    
        Button btn1 = new Button("button1");
        Button btn2 = new Button("button2");
        Button btn3 = new Button("button3");
        Button btn4 = new Button("button4");    
        Button btn5 = new Button("button5");
    
        btn1.setBackground(Color.blue);
        btn2.setBackground(Color.yellow);
        btn3.setBackground(Color.pink);
        btn4.setBackground(Color.green);
        btn5.setBackground(Color.red);
    
        frame.add(btn1,BorderLayout.EAST);
        frame.add(btn2,BorderLayout.NORTH);
        frame.add(btn3,BorderLayout.SOUTH);
        frame.add(btn4,BorderLayout.WEST);
        frame.add(btn5);
    
        frame.setVisible(true);
    }
    

    }

Output:

图片 15

 

3.
GridLayout(表格布局)

  使容器中各个组件呈网格状布局,平均占据容器的空间。

  在程序中安排组件的位置和大小时,应该注意以下两点:

  • 容器中的布局管理器负责各个组件的大小和位置,因此用户无法在这种情况下设置组件的这些属性。如果试图使用Java
    语言提供的setLocation(),setSize(),setBounds()
    等方法,则都会被布局管理器覆盖。
  • 如果用户确实需要亲自设置组件大小或位置,则应取消该容器的布局管理器,方法为:setLayout(null);

 

  •  代码实现

    public class Demo06 {

    public static void main(String[] args) {
        Frame frame = new Frame("FlowLayout");
        frame.setBounds(100, 100, 400, 300);
    
        GridLayout gl = new GridLayout(3,2,5,5); //设置表格为3行两列排列,表格横向间距为5个像素,纵向间距为5个像素
        frame.setLayout(gl);
    
        Button but1 = new Button("button1");
        Button but2 = new Button("button2");
        Button but3 = new Button("button3");
        Button but4 = new Button("button4");
        Button but5 = new Button("button5");

        but1.setBackground(Color.blue);
        but2.setBackground(Color.yellow);
        but3.setBackground(Color.red);
        but4.setBackground(Color.green);
        but5.setBackground(Color.pink);

        frame.add(but1);
        frame.add(but2);
        frame.add(but3);
        frame.add(but4);
        frame.add(but5);

        frame.setVisible(true);

    }

}

Output:

图片 16

  • 综合运用—— 实现一个简单的4*4 计算器界面

    public class Demo07 {

    public static void main(String[] args) {
        Frame frame = new Frame("计算器");
        frame.setBounds(100, 100, 300, 420);
        /*因为Frame 的默认布局为BorderLayout 所以这两句代码可以省略。
        BorderLayout bl = new BorderLayout();
        frame.setLayout(bl);
        */
    
        //创建一个文本输入框,然后将其添加到 North 位置
        TextField tf = new TextField();
        frame.add(tf, BorderLayout.NORTH);
    
        //创建一个Panel 面板,并设置布局为 GridLayout
        Panel panel = new Panel();
        GridLayout gl = new GridLayout(4,4,1,1);//创建Panel 面板,大小为4*4,行距与列距均为1 个像素点
        panel.setLayout(gl);
    
        //将 panel 添加到 frame 的 Center 位置
        frame.add(panel, BorderLayout.CENTER);
        Button btn1 = new Button (" 7");
        Button btn2 = new Button (" 8");
        Button btn3 = new Button (" 9");
        Button btn4 = new Button (" +");
        Button btn5 = new Button (" 4");
        Button btn6 = new Button (" 5");
        Button btn7 = new Button (" 6");
        Button btn8 = new Button (" -");
        Button btn9 = new Button (" 1");
        Button btn10 = new Button ("2");
        Button btn11 = new Button ("3 ");
        Button btn12 = new Button ("*");
        Button btn13 = new Button ("0 ");
        Button btn14 = new Button (" .");
        Button btn15 = new Button (" =");
        Button btn16 = new Button (" /");
    
        //将按钮添加到 Panel 面板
        panel.add(btn1);
        panel.add(btn2);
        panel.add(btn3);
        panel.add(btn4);
        panel.add(btn5);
        panel.add(btn6);
        panel.add(btn7);
        panel.add(btn8);
        panel.add(btn9);
        panel.add(btn10);
        panel.add(btn11);
        panel.add(btn12);
        panel.add(btn13);
        panel.add(btn14);
        panel.add(btn15);
        panel.add(btn16);
    
        frame.setVisible( true);
    
    }
    

    }

Output:

图片 17

  • 总结

   1.Frame是一个顶级窗口。Frame的缺省布局管理器为BorderLayout。

   2.Panel 无法单独显示,必须添加到某个容器中。 Panel
的缺省布局管理器为FlowLayout。

   3.当把Panel 作为一个组件添加到某个容器中后,该Panel
仍然可以有自己的布局管理器。因此,可以利用Panel 使得BorderLayout
中某个区域显示多个组件,达到设计复杂用户界面的目的 。

   4.如果采用无布局管理器
setLayout(null),则必须使用setLocation(),setSize(),setBounds()等方法手工设置组件的大小和位置,此方法会导致平台相关,不鼓励使用。

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图