Enviar um café pro programador

Gerenciador de Layout: Pack, Grid e Place

Neste tutorial de programação gráfica em Python, vamos aprender melhor como gerenciar o layout de nossos programas de interface gráfica.

Gerenciadores de Layout

Como já aprendemos a usar botões, caixa de entrada, caixa de diálogo, radio e checkbuttons, bem como tratar diversos eventos, chegou a hora de aprender como organizar melhor esse amontado de widgets!

Você deve ter notado que fomos adicionando botões, labels...e eles foram se encaixando em um canto, em outro...se você é dos que gosta de fuçar, certamente mexeu e viu widgets sumirem, ou ficarem desalinhados, feios etc.

Os gerenciadores de layout servem para definirmos melhor o posicionamento de nossos widgets em containers (janelas Tk() ou Frame() por exemplo), de modo a organizar e deixar eles esteticamente melhores.

Existem três principais gerenciadores de layout:
  1. pack - vai adicionando os widgets na ordem que forem sendo empacotados
  2. grid - adiciona através de posições de linhas e coluna, como uma tabela ou grade (grid)
  3. place - adiciona widgets em posições específicas, com tamanhos específicos

Gerenciador de Layout: pack


O gerenciador pack é o que vinhamos usando, no decorrer de nossos tutoriais de programação gráfica em Python, e é o mais básico.

Por padrão, ele vai adicionando os widgets na ordem quem forem empacotados (chamando o método pack() ), de cima pra baixo.

Porém, existem várias opções para empacotar os componentes:
  • side - indica de que lado você quer que seja adicionado (TOP, BOTTOM, LEFT e RIGHT). Se quer um alinhamento horizontal, use side=LEFT, por exemplo
  • fill - para preencher um espaço. Pode usar como argumneto X, Y ou BOTH, e ele vai cobrir todo o espaçamento horizontal (X), vertical (Y) ou ambos (BOTH)
  • expand - pode passar como YES ou NO, para definir se o widget vai preencher todo o espaço extra do container ou não.
  • padx e pady - preenchem o ao redor do widget com espaço em branco
  • pack_forget - retira um widget empacotado do container que foi inserido anteriormente
Estude o seguinte código, rode o script e veja o resultado você mesmo:

from tkinter import *

class PackDemo( Frame ):
 def __init__(self):
  # Inicializando o frame 
  Frame.__init__(self)
  self.master.title("Gerenciador pack")
  self.master.geometry( "600x250" )
  self.pack( expand = YES, fill = BOTH)
  
  # Botao que adiciona outros, no topo
  self.botao1 = Button(self, text = "Adicionar Botão",
         command = self.adicionarBotao)
  self.botao1.pack(side = TOP)
  
  # Botão 2, no fundo e preenche X e Y
  self.botao2 = Button(self,
           text = "expand = NO, fill = BOTH")
  self.botao2.pack( side = BOTTOM, fill = BOTH )
  
  # Botão3: na esquerda, fill só na horizontal
  self.botao3 = Button( self, text = "expand = YES, fill = X" )
  self.botao3.pack( side = LEFT, expand = YES, fill = X )
  
  # Botão4: na direita, fill só na vertical
  self.botao4 = Button( self, text = "expand = YES, fill = Y" )
  self.botao4.pack( side = RIGHT, expand = YES, fill = Y )
  
  mainloop()
  
 def adicionarBotao( self ):
  Button(self, text = "Botão novo" ).pack(pady = 5)
PackDemo()

Gerenciador de Layout: grid

Como o nome sugere, ele vai dividir o container em uma grade (grid em inglês), assim podemos posicionar os elementos dividino o Frame, por exemplo, em x linhas e y linhas.

Cada posição é chamada de célula, ou seja, cada célular é composta por um valor de linha, um valor de coluna e pode ter um widget

A primeira linha (row) é a 0, a segunda coluna é a de número 1, a terceira é de número 2...
A primeira coluna (column) é a 0, a segunda é a 1, a terceira é a 2...



Definimos a posição de cada widget com o método grid(), que recebe os parâmetros row e column, com a respectiva posição e numeração de cada linha e coluna.

Vamos, por exemplo, cria 9 labels, e exibir eles numa grid três por três, ou seja, 3 linhas e 3 colunas.
O código é o seguinte:

from tkinter import *

class Grid( Frame ):
 def __init__(self):
  # Inicializando o frame 
  Frame.__init__(self)
  self.master.title("Grid")
  self.master.geometry( "80x80" )
  
  # Criando os labels e adicionando
  # com o método grid()
  for linha in range(3):
   for coluna in range(3):
    Label(self.master, text=str(linha)+','+str(coluna)).grid(row=linha,column=coluna)
  
  mainloop()

Grid()

E o resultado:

Curso de Python

Veja, o primeiro label é o da posição 0,1
O segundo, na primeira linha e segunda coluna é 0,1
Na primeira linha e terceira coluna temos o 0,2
E assim vai...tente ver uma 'tabela', uma 'grade' ao usar o grid.

Sempre que quiser dispor seus elementos, alinhados por linhas e colunas, use o grid.
Um exemplo comum de programas que usam, são os que tem algum formulário, veja:

Apostila de Python grátis para download

Veja como fica bem alinhado e bonitinho.
O código pra fazer isso é:

from tkinter import *

class Grid( Frame ):
 def __init__(self):
  # Inicializando o frame 
  Frame.__init__(self)
  self.master.title("Grid")
  
  Label(self.master, text="Nome").grid(row=0)
  Label(self.master, text="Sobrenome").grid(row=1)

  entrada1 = Entry(self.master)
  entrada2 = Entry(self.master)

  entrada1.grid(row=0, column=1)
  entrada2.grid(row=1, column=1)

  mainloop()

Grid()

Note que quando omitimos alguma opção row ou column, é porque o valor padrão é 0.
Para se aprofundar melhor no manager grid, sugerimos pesquisar mais sobre a opção sticky, os métodos rowconfigure e columnconfigure.

Gerenciador de Layout: place

Esse gerenciador não é tão usado, mas é simples de usar, pois basta dizer onde quer inserir cada widget. Pronto.

Porém, isso complica um pouco as coisas.
Note que o pack e o grid faz muita coisa por você, automaticamente, você se estressa com pouca coisa.

O place é mais 'rigoroso', digamos assim, você precisa 'cravar' locais, saber exatamente onde vai cada coisa, até onde, até que altura, até que largura etc. Não vamos nos aprofundar nele.

Para fazer um programa com essa cara:

Curso de Python online grátis


Rode este código Python:

from tkinter import *

class Place( Frame ):
 def __init__(self):
  top = Tk()
  top.title("place")
  top.geometry("250x200")
  
  # Label e primeira entrada
  label1 = Label(top, text = "Nota 1")
  label1.place(x = 10,y = 10)
  entrada1 = Entry(top, bd = 5)
  entrada1.place(x = 60,y = 10)
  
  # Label e segunda entrada
  label2 = Label(top,text = "Nota 2")
  label2.place(x = 10,y = 50)
  entrada2 = Entry(top,bd = 5)
  entrada2.place(x = 60,y = 50)
 
  # Label e terceira entrada
  label3 = Label(top,text = "Média")
  label3.place(x = 10,y = 150)
  entrada3 = Entry(top,bd = 5)
  entrada3.place(x = 60,y = 150)

  # Botão
  botao = Button(top, text = "Calcular")
  botao.place(x = 100, y = 100)

  top.mainloop()
Place()

Um comentário: