Body zdarma Java týden
Využij podzimních slev a získej od nás až 40 % bodů zdarma! Více zde
Pouze tento týden sleva až 80 % na Java e-learning!

Lekce 4 - Layouty v Javě (podruhé)

Unicorn College Tento obsah je dostupný zdarma v rámci projektu IT lidem.
Vydávání, hosting a aktualizace umožňují jeho sponzoři.

Vítejte v pokračování minulého dílu, který popisoval první 4 layouty (FlowLayout, BoxLayout, BorderLayout a CardLayout). Dnes se podíváme jak fungují zbylé layouty a ukážeme si jejich využití.

GridBagLayout

GridBagLayout v Javě

Tento layout je jedním z nejvíce složitých layoutů, které Java poskytuje. Nebudeme se proto učit všechna nastavení, které tento layout má, ale jen ta základní, které nám budou bohatě stačit.

Tento layout používá tzv. buňky (cells), které mají vlastní stejnou výšku i šířku. Konstruktor:

Container pane = this.getContentPane();
pane.setLayout(new GridBagLayout());
GridBagConstraints g = new GridBagConstraints();

Metody:

  • gridx - určuje v kolikátém sloupci se má prvek vyskytnout
  • gridy - určuje v kolikátém řádku se má prvek vyskytnout
  • gridwidth - určuje přes kolik sloupců se má komponenta roztáhnout
  • gridheight - určuje přes kolik řádků se má komponenta roztáhnout
  • fill - určuje výplň prostoru. Má 4 parametry (NONE - výchozí, HORIZONTAL - vytvoří komponenty dostatečně široký na pokrytí plochy a nemění jeho výšku, VERTICAL - vytvoří komponenty dostatečně vysoké a nezmění jeho šířku, BOTH - zcela vyplní svou plochu)
  • anchor - definuje, na kterém místě se má komponenta zobrazit. Jako parametry můžete uvést následující možnosti:
anchor
  • ipadx - určuje vnitří odsazení(výplň). Např. pokud bude mít komponenta šířku 30px a nastavíme ipadx = 10, přidá se výplň na obou bočních stranách 10px, takže celkový prostor bude činit 50px.
  • ipady - pracuje stejně jako ipadx, akorát vertikálně.
  • weightx, weighty - nastavuje prostor mezi komponentou a okrajem kontejneru, ve kterém je komponenta (určují se čísla z rozsahu 0,0 až 1,0)
  • insets - padding. Celým zápisem - insets(botton,lef­t,right,top);

1 příklad (falešná klávesnice):

třída MyFrame:

import javax.swing.*;
import javax.swing.border.*;  // importotváno kvůli rámu
import java.awt.*;
import java.awt.event.*;     // importováno kvůli nastavení událostí
public class MyFrame extends JFrame
{
   JButton c,v,b,n,m,alt,mezernik,enter;
   public MyFrame()
   {
        this.setTitle("cardLayout");
        this.setSize(400, 200);
        this.setKomponents();
   }

   public void setKomponents(){
      Container pane = this.getContentPane();
      pane.setLayout(new GridBagLayout());
      GridBagConstraints g = new GridBagConstraints();
      c = new JButton("c");
      g.fill = GridBagConstraints.HORIZONTAL;
      g.gridx = 0;
      g.gridy = 0;
      pane.add(c, g);
      v = new JButton("v");
      g.fill = GridBagConstraints.HORIZONTAL;
      g.gridx = 1;
      g.gridy = 0;
      pane.add(v, g);
      b = new JButton("b");
      g.fill = GridBagConstraints.HORIZONTAL;
      g.gridx = 2;
      g.gridy = 0;
      pane.add(b, g);
      n = new JButton("n");
      g.fill = GridBagConstraints.HORIZONTAL;
      g.gridx = 3;
      g.gridy = 0;
      pane.add(n, g);
      m = new JButton("m");
      g.fill = GridBagConstraints.HORIZONTAL;
      g.gridx = 4;
      g.gridy = 0;
      pane.add(m, g);

      enter = new JButton("ENTER");
      g.fill = GridBagConstraints.HORIZONTAL;
      g.gridx = 5;
      g.gridy = 0;
      g.gridwidth = 2;
      g.gridheight = 2;
      g.ipadx = 30;
      g.ipady = 30;
      g.insets = new Insets(0,20,0,0);
      pane.add(enter, g);

      alt = new JButton("alt");
      g.fill = GridBagConstraints.HORIZONTAL;
      g.gridx = 0;
      g.gridy = 1;
      g.insets = new Insets(0,0,0,0);
      g.gridheight = 1;
      g.gridwidth = 1;
       g.ipadx = 0;
      g.ipady = 0;
      pane.add(alt, g);
      mezernik = new JButton("mezernik");
      g.fill = GridBagConstraints.HORIZONTAL;
      g.gridx = 1;
      g.gridy = 1;
      g.gridwidth = 5;
      pane.add(mezernik, g);
  }


  public static Frame nastav(){
     MyFrame i = new MyFrame();
     i.setVisible(true);
     i.setLocationRelativeTo(null);
     i.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     return i;
  }
}

třída Start:

public class Start
{
   public static void main(String args[]) {
       MyFrame.nastav();
   }
}

Ještě jedna poznámka: Pokud nastavíte nějaké komponentě nějakou vlastnost (např. g.gridwidth = 5), musíte u další komponenty tuto vlastnost zase zrušit (pokud tedy chcete) g.gridwidth = 5. Jinak by se všechny komponenty roztáhly přes 5 sloupců.

Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!

Tak to by bylo k tomuto těžkému layoutu všechno. Myslím, že jste rádi. Naučit se tento layout dá hodně zabrat, ale pokud s ním umíte, dokážete perfektně umístit své komponenty.

GridLayout

Díky tomuto layoutu rozdělíme panel na několik vždy stejně velkých částí, které dostanou maximální možnou velikost. Jednoduše velikost okna se vydělí počtem buněk, které vytvoříme. Rozhodně je tento layout jednoduchý a příjemný k použití.

GridLayout v Javě

Konstruktor:

Container pane = this.getContentPane();
pane.setLayout(new GridLayout(řádky, sloupce));

Jednoduchý příklad:

Container pane = this.getContentPane();
pane.setLayout(new GridLayout(2, 2));
JButton a = new JButton("a");
JButton b = new JButton("b");
JButton c = new JButton("c");
JButton d = new JButton("d");
pane.add(a);
pane.add(b);
pane.add(c);
pane.add(d);

GroupLayout

GroupLayout v Javě

Tento layout pracuje odděleně s vertikálním a horizontálním rozložení. Je definován pro každou dimenzi samostatně. To znamená, že každá komponenta musí být definována 2x.

Dále tento layout používá dva parametry: sequential (sekvenční) - komponenty jsou uspořádané jedna po druhé. Poloha jednotlivých komponent je definována jako relativní vzhledem k předchozí komponentě. parallel (paralelní) - komponenty jsou uspořádány pod sebe ve stejném prostoru. Může nabývat hodnou:

  • baseline: výchozí
  • top: od shora
  • bottom: od zdola

Podél vodorovné osy mohou být zarovnány:

  • left: vlevo
  • right: vpravo
  • center: na střed

Gaps(mezery) - Pomocí mezer lze řídit vzdálenost mezi jednotlivými komponentami. Můžeme nastavit i automatické mezery. Velikosti těchto mezer se vypočítají dynamicky na základě celkové velikosti. Slouží k tomu následující příkazy:

  • layout.setAuto­CreateGaps(tru­e);
  • layout.setAuto­CreateContainer­Gaps(true);

Tyto metody musíte vždy zavolat, aby jste mohli nastavit následující funkce: addPreferredGap(La­youtStyle.Com­ponentPlacemen­t.param); param:

  • RELATED - použití u vodorovného nastavení
  • UNRELATED - vzdálenost je o něco málo větčí než u RELATED
  • INDENT - používá se u horizontálního nastavení, kdy je buďto horní nebo spodní komponenta umístěná s odsazením.

Zarovnání - slouží k tomu příkaz Alignment.param:

  • LEADING - nahoru
  • TRAILING - dolů
  • CENTER - doprostřed
  • BASELINE - základní nastavení

Pro úplnost a snadné pochopení přikládám jednoduchý příklad i s popisky.

třída MyFrame:

import java.awt.*;
import javax.swing.*;

public class MyFrame extends JFrame
{
  JButton a,s,d,f,g,h;
  public MyFrame()
  {
       this.setSize(400,400);
       this.setTitle("GroupLayout");
       this.setKomponents();
  }

  public void setKomponents(){
        /**
         * nastavení tlačítek
         */
        a = new JButton("a");
        s = new JButton("s");
        d = new JButton("d");
        f = new JButton("f");
        g = new JButton("g");
        h = new JButton("h");

           /**
         * konstruktor GroupLayoutu
         */
        Container layout = this.getContentPane();
        GroupLayout gl = new GroupLayout (layout);
        layout.setLayout(gl);
        /**
         * nastavení automatických mezer
         */
        gl.setAutoCreateGaps(true);
        gl.setAutoCreateContainerGaps(true);
        /**
         * rozvržení komponent
         */
        gl.setHorizontalGroup(  // horizontální nastavení
         gl.createSequentialGroup()
         // vytvorení sekvenční skupiny, kterou jmse si již popsali
         .addComponent(a)
         .addComponent(s)
         .addComponent(d)
         .addGroup(gl.createParallelGroup(GroupLayout.Alignment.LEADING))
         // přidání paralelních skupin, o kterýcg jsme si již také říkali
         .addComponent(f)
         .addComponent(g)
         .addGroup(gl.createParallelGroup(GroupLayout.Alignment.TRAILING))
         .addComponent(h)
         );
         gl.setVerticalGroup(  // vertikální nastavení
          gl.createSequentialGroup()
          .addGroup(gl.createParallelGroup(GroupLayout.Alignment.BASELINE)
           .addComponent(a)
           .addComponent(s)
           .addComponent(d))
           .addGroup(gl.createParallelGroup(GroupLayout.Alignment.BASELINE)
           .addComponent(f)
           .addComponent(g))
           .addComponent(h)
         );
    }

    public static Frame nastav(){
        MyFrame m = new MyFrame();
        m.setLocationRelativeTo(null);
        m.setVisible(true);
        return m;
    }
}

Vše spustíme přes třídu Start:

public class Start
{
    public static void main(String args[]){
        MyFrame.nastav();
    }
}

Jak se tedy tento layout tvoří máte popsáno. Ještě uvedu celý příkaz, kterým můžeme komponenty přidat. Vypadá takto:

addComponent(Com­ponent comp, int min, int pref, int max);

Nakonec jen uvedu metody které nám vrátí nastavené velikosti:

  • getMinimumSize() - vrátí minimální velikost komponenty
  • getPreferredSize() - vrátí preferovanou velikost komponenty
  • getMaximumSize() - vrátí maximální velikost komponenty

 

 

Článek pro vás napsal Milan Gallas
Avatar
Jak se ti líbí článek?
3 hlasů
Autor se věnuje programování, hardwaru a počítačovým sítím.
Předchozí článek
Layouty v Java Swing
Všechny články v sekci
Java Swing bez grafického návrháře
Miniatura
Následující článek
JComboBox a dialogy v Java Swing
Aktivity (1)

 

 

Komentáře

Avatar
Milan Gallas
Redaktor
Avatar
Milan Gallas:24.7.2013 19:58

jo a obrázky pochází ze stránky: http://docs.oracle.com/…/visual.html

 
Odpovědět 24.7.2013 19:58
Avatar
BLADE
Člen
Avatar
BLADE:22.8.2013 18:47

Ten GridBagLayout je super, no nedá sa tam nejako nadstaviť aby sa mi to vždy nedávalo do stredu okna ?

 
Odpovědět 22.8.2013 18:47
Avatar
Milan Gallas
Redaktor
Avatar
Odpovídá na BLADE
Milan Gallas:22.8.2013 21:00

stačí když použiješ příkazy:
g.weightx = 0.5;
g.weighty = 0.5;
a popřípadě pokud budeš chtít tak si přepiš
tohle

g.fill = GridBagConstraints.HORIZONTAL;

na tohle

g.fill = GridBagConstraints.BOTH;

efekt uvidíš sám.

Editováno 22.8.2013 21:01
 
Odpovědět 22.8.2013 21:00
Avatar
BLADE
Člen
Avatar
Odpovídá na Milan Gallas
BLADE:23.8.2013 17:43

No tak som to skúsil s tým wightx a y + som tam pridal anchor na NORTHWEST. A išlo mi to pekne doľava a hore no potom som chcel dať pod to 2 tlačítka a to už je problém pretože mi ich dá zas do stredu a ešte kvôli tomu weight dosť ďaleko od seba :(

z = new JLabel("Vyberte si 1. jazyk: ");
        gbc.anchor = GridBagConstraints.NORTHWEST;

        gbc.weightx = 0.5;
        gbc.weighty = 0.5;
        gbc.gridx = 0;
        gbc.gridy = 0;
        hlava.add(z, gbc);

        EN = new JButton("EN");
        gbc.gridx = 0;
        gbc.gridy = 1;
        hlava.add(EN, gbc);

        SK = new JButton("SK");
        gbc.gridx = 1;
        gbc.gridy = 1;
        hlava.add(SK, gbc);

hlava je container

Asi som to celé zle pochopil, no už som s toho jeleň.
Výsledok vyzerá takto :

 
Odpovědět 23.8.2013 17:43
Avatar
Kit
Redaktor
Avatar
Odpovídá na BLADE
Kit:23.8.2013 17:48

Proč tam dáváš na začátku skoro každého řádku "gbc."? Mně to funguje i bez toho.

Odpovědět 23.8.2013 17:48
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
BLADE
Člen
Avatar
Odpovídá na Kit
BLADE:23.8.2013 19:27

ale gbc je ten GridBagConstraints bez toho mi to predsa nerozmiestni tak ako si žiadam.

 
Odpovědět 23.8.2013 19:27
Avatar
Kit
Redaktor
Avatar
Odpovídá na BLADE
Kit:23.8.2013 20:25

Dal jsem ty příkazy dovnitř GridBagConstraints (kam patří) a funguje to.

Vypadá to potom takto:

JLabel z = new JLabel("Vyberte si 1. jazyk: ");
JButton EN = new JButton("EN");
JButton SK = new JButton("SK");

// konstruktor
{
anchor = NORTHWEST;

weightx = 0.5;
weighty = 0.5;
gridx = 0;
gridy = 0;
hlava.add(z, this);

gridx = 0;
gridy = 1;
hlava.add(EN, this);

gridx = 1;
gridy = 1;
hlava.add(SK, this);

Hlavně přitom nesahám na atributy jiného objektu.

Možná by se to dalo udělat ještě lépe.

Odpovědět 23.8.2013 20:25
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Milan Gallas
Redaktor
Avatar
Milan Gallas:23.8.2013 20:55

Jednoduše sem vykódil tohle:

Container hlava = this.getContentPane();
    hlava.setLayout(new GridBagLayout());

    GridBagConstraints gbc = new GridBagConstraints();
    gbc.anchor = GridBagConstraints.FIRST_LINE_START;

   z = new JLabel("Vyberte si 1. jazyk: ");
     gbc.insets = new Insets(5,5,5,5);
     gbc.fill = GridBagConstraints.HORIZONTAL;
     gbc.gridwidth = 2;
     gbc.gridx = 0;
     gbc.gridy = 0;
     hlava.add(z, gbc);

     EN = new JButton("EN");
     gbc.fill = GridBagConstraints.NONE;
     gbc.gridwidth = 1;
     gbc.gridx = 0;
     gbc.gridy = 1;
     hlava.add(EN, gbc);

     SK = new JButton("SK");
     gbc.gridx = 1;
     gbc.gridy = 1;
     gbc.weightx = 0.5;
     gbc.weighty = 0.5;
     hlava.add(SK, gbc);

Je to to co si potřeboval?

Editováno 23.8.2013 20:55
 
Odpovědět 23.8.2013 20:55
Avatar
Milan Gallas
Redaktor
Avatar
Odpovídá na BLADE
Milan Gallas:23.8.2013 20:56

zarovná ti to doleva a nahoru ať to roztáhneš jakkoliv.

 
Odpovědět 23.8.2013 20:56
Avatar
Kit
Redaktor
Avatar
Odpovídá na BLADE
Kit:23.8.2013 21:07

Tady to mám kompletní, kdybys měl zájem. Je to funkční.

http://www.itnetwork.cz/dev-lighter/183

Odpovědět 23.8.2013 21:07
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Milan Gallas
Redaktor
Avatar
Odpovídá na Kit
Milan Gallas:23.8.2013 21:14

Tvůj kód ale neřeší jeho problém. On to nechce mít zarovnané na středu při zvětšení okna.

 
Odpovědět 23.8.2013 21:14
Avatar
Kit
Redaktor
Avatar
Odpovídá na Milan Gallas
Kit:23.8.2013 21:23

Řešil jsem něco jiného. Jak odstranit tu hromadu zbytečných "gbc.". Je totiž nesmyslné z jednoho objektu manipulovat s atributy jiného objektu.

Odpovědět 23.8.2013 21:23
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
BLADE
Člen
Avatar
BLADE:23.8.2013 22:51

Díky že ste si našli čas ,presne ako si to napísal fullL som si to predstavoval ,hlavne mi tam pomohlo to Insets. No keď potom chcem dať ďalší riadok v ktorom má byť text tak mi to 2. tlačítko v 2.riadku posunie :(. Pošlem aj screen :

 
Odpovědět 23.8.2013 22:51
Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!
Avatar
BLADE
Člen
Avatar
BLADE:25.8.2013 14:21

Tak už som chytil nervy na celý za*raný Layout a spravil som si to pekne bez nich cez setBounts :D

 
Odpovědět 25.8.2013 14:21
Avatar
Odpovídá na BLADE
Michal Žůrek - misaz:25.8.2013 14:23

to je nejlepší, taky to tak dělám. :) Nevidím jediný důvod se rozčilovat.

 
Odpovědět 25.8.2013 14:23
Avatar
Kit
Redaktor
Avatar
Odpovídá na BLADE
Kit:25.8.2013 14:30

Ten layout v článku je chybně udělaný, proto se v tom nemůžeš zorientovat.

Odpovědět  -1 25.8.2013 14:30
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Milan Gallas
Redaktor
Avatar
Odpovídá na Kit
Milan Gallas:25.8.2013 15:14

fakt co přesně je udělané špatně? Kromě jiného stylu zápisu, který se prostě s tvým stylem neschoduje. To ale neznamená že je to špatně.

Editováno 25.8.2013 15:15
 
Odpovědět 25.8.2013 15:14
Avatar
Kit
Redaktor
Avatar
Odpovídá na Milan Gallas
Kit:25.8.2013 15:16

Od základu je špatně, že z jednoho objektu měníš atributy jiného objektu. To se v OOP prostě nedělá. Je to nejen méně přehledné, ale i pomalejší.

Editováno 25.8.2013 15:17
Odpovědět 25.8.2013 15:16
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Milan Gallas
Redaktor
Avatar
Odpovídá na BLADE
Milan Gallas:25.8.2013 15:36

Jediné co tam máš špatně je že příkazy:

gbc.weightx = 0.5;
       gbc.weighty = 0.5;

musíš přiřadit až poslednímu tlačítku.
celý kód najdeš zde:
http://www.itnetwork.cz/dev-lighter/188

 
Odpovědět 25.8.2013 15:36
Avatar
Tomhaus
Člen
Avatar
Tomhaus:5.12.2014 17:58

Cs, mam problém s vybráním správného layoutu.
Chci si komponenty umisťovat podle pozic a libovolně měnit jejich velikost.
Nevíte jakej by byl nejlepší layout?

Odpovědět 5.12.2014 17:58
Být lepší a chytřejší je důležité, ale někdy se musíme spokojit s tím, co máme.
Avatar
Tomhaus
Člen
Avatar
Tomhaus:5.12.2014 18:10

A chtěl bych ještě aby se mi to skládalo od horního levého rohu :)

Odpovědět 5.12.2014 18:10
Být lepší a chytřejší je důležité, ale někdy se musíme spokojit s tím, co máme.
Avatar
Milan Gallas
Redaktor
Avatar
Odpovídá na Tomhaus
Milan Gallas:6.12.2014 15:29

grigBagLayout. Layouty můžeš do sebe i zanořit. Takže můžeš mít BorderLayout a v něm třeba ve BorderLayout.CENTER můžeš mít gridBagLayout.

Pokud chceš s objekty manipulovat za běhu programu, tak si pročti http://www.itnetwork.cz/…java-menubar .

 
Odpovědět 6.12.2014 15:29
Avatar
Tomhaus
Člen
Avatar
Odpovídá na Milan Gallas
Tomhaus:7.12.2014 16:15

A dal by se třeba nastavit JPanelu nějakej layout?
A dá se v GridBagLayoutu nastavit aby nevyplňoval celou plochu?
Nechci aby se mi roztahovaly tlačítka do šířky.

Editováno 7.12.2014 16:19
Odpovědět 7.12.2014 16:15
Být lepší a chytřejší je důležité, ale někdy se musíme spokojit s tím, co máme.
Avatar
forcabarca
Člen
Avatar
forcabarca:17.11.2015 0:04

Těch Layoutů prý má být 8 ale v obou dílech jsem jich našel jen 7, tak co ten osmý?

 
Odpovědět 17.11.2015 0:04
Avatar
vajkuba1234
Člen
Avatar
Odpovídá na forcabarca
vajkuba1234:17.11.2015 4:51

Zkoušel jsi hledat na internetu? Já tam toho našel celkem dost.

Odpovědět 17.11.2015 4:51
No hope, no future, JUST WAR! For world peace Israel must be DESTROYED!
Avatar
forcabarca
Člen
Avatar
Odpovídá na vajkuba1234
forcabarca:27.11.2015 18:01

Spíš jsem čekal že mi autor napíše proč ten jeden díl vynechal, nebo jestli jsem ho někde přehlédl. Na začátku čtu 8 layoutů a v článku jich najdu jen 7, tak mě zajímal důvod, nic víc.

 
Odpovědět 27.11.2015 18:01
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 26 zpráv z 26.