Olá programadores e programadoras! Tudo bem com vocês? Espero que sim! Na aula de hoje veremos como criar widgets interativos para o nosso app.
No Qt widget é o nome dado a um componente da UI com o qual o usuário pode interagir. As interfaces do usuário são compostas por vários widgets, organizados na janela. Qt vem com uma grande seleção de widgets disponíveis e ainda permite que você crie seus próprios widgets personalizados. A tabela a seguir mostra alguns widgets utilizados comuns:
Tabela 1: Widgets e suas funções.
Existem muito mais widgets do que isso. Para uma lista completa veja a documentação do Qt. Aqui vamos dar uma olhada em alguns dos mais úteis.
Começaremos o tour com QLabel, sem dúvida um dos widgets mais simples disponíveis na caixa de ferramentas do Qt. Este é um texto simples de uma linha que você pode posicionar em seu aplicativo. Você pode definir o texto passando uma string ao criá-lo:
widget = QLabel('Olá')
Ou, usando o método .setText():
widget = QLabel('1') # a label é criada com o texto '1'
widget.setText('2') # a label agora mostra o texto '2'
Você também pode ajustar os parâmetros da fonte, como tamanho ou alinhamento do texto no widget:
# --- Importar as bibliotecas --- #
import sys
from PySide2.QtCore import Qt
from PySide2.QtWidgets import QApplication, QLabel, QMainWindow
# --- Criar a classe do app --- #
class TelaPrincipal(QMainWindow):
"""Classe que cria a tela principal do app."""
def __init__(self):
"""Função responsável por inicializar a classe."""
# --- Herdar a classe QMainWindow --- #
super().__init__()
# --- Colocar o títlo do app --- #
self.setWindowTitle('Meu app')
# --- Criar o widget QLabel --- #
widget = QLabel('Olá')
# --- Fonte de QLabel --- #
fonte = widget.font() # 1
# --- Mudar o tamanho da fonte --- #
fonte.setFont(30)
# --- Configurar as novas informações da fonte --- #
widget.setFonte(fonte)
# --- Alinhar o widget na tela --- #
widget.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter) # 2
# --- Colocar o widget no centro da tela --- #
self.setCentralWidget(widget)
# --- Criar a instância do app --- #
app = QApplication(sys.argv)
# --- Criar a janela do app --- #
janela = TelaPrincipal()
janela.show()
# --- Executar o loop de eventos --- #
app.exec_()
Obtemos a fonte atual, usando widget.font(), modificamos e aplicamos novamente. Isso garante que a fonte permaneça de acordo com as convenções da área de trabalho e;
O alinhamento é especificado usando um sinalizador do Qt.
Ajuste os parâmetros da fonte e veja o efeito:
Os sinalizadores disponíveis para alinhamento horizontal são:
Tabela 2: Funções de alinhamento horizontal e seus comportamentos.
Os sinalizadores disponíveis para alinhamento vertical são:
Tabela 3: Funções de alinhamento vertical e seus comportamentos.
Você pode combinar sinalizadores usando barras verticais, mas observe que você só pode usar um sinalizador de alinhamento vertical ou horizontal por vez.
Finalmente, há também uma bandeira abreviada que centraliza em ambas as direções simultaneamente: Qt.AlignCenter, que centraliza horizontalmente E verticalmente.
Estranhamente, você também pode usar QLabel para exibir uma imagem usando o método .setPixmap(). Isso aceita um pixmap (uma matriz de pixels), que você pode criar passando um nome de arquivo de imagem para QPixmap:
# --- Importar as bibliotecas --- #
import sys
from PySide2.QtGui import QPixmap
from PySide2.QtWidgets import QApplication, QLabel, QMainWindow
# --- Criar a classe do app --- #
class TelaPrincipal(QMainWindow):
"""Classe que cria a tela principal do app."""
def __init__(self):
"""Função responsável por inicializar a classe."""
# --- Herdar a classe QMainWindow --- #
super().__init__()
# --- Colocar o títlo do app --- #
self.setWindowTitle('Meu app')
# --- Criar o widget QLabel --- #
widget = QLabel('Olá')
# --- Colocar a imagem no QLabel --- #
widget.setPixmap(QPixmap('imagem.png')) # 1
# --- Colocar o widget no centro da tela --- #
self.setCentralWidget(widget)
# --- Criar a instância do app --- #
app = QApplication(sys.argv)
# --- Criar a janela do app --- #
janela = TelaPrincipal()
janela.show()
# --- Executar o loop de eventos --- #
app.exec_()
Forma de colocar uma imagem em QLabel.
Redimensione a janela e a imagem será cercada por um espaço vazio.
Por padrão, a imagem é dimensionada enquanto mantém sua proporção. Se você quiser que ele seja ampliado e dimensionado para caber completamente na janela, você pode definir .setScaledContents(True) no QLabel, por exemplo:
widget.setScaledContents(True)
Redimensione a janela e a imagem será deformada para caber no app.
O próximo widget a ser observado é QCheckBox que, como o nome sugere, apresenta uma caixa de seleção para o usuário. No entanto, como acontece com todos os widgets Qt, existem várias opções configuráveis para alterar o comportamento do widget:
# --- Importar as bibliotecas --- #
import sys
from PySide2.QtCore import Qt
from PySide2.QtWidgets import QApplication, QCheckBox, QMainWindow
# --- Criar a classe do app --- #
class TelaPrincipal(QMainWindow):
"""Classe que cria a tela principal do app."""
def __init__(self):
"""Função responsável por inicializar a classe."""
# --- Herdar a classe QMainWindow --- #
super().__init__()
# --- Colocar o títlo do app --- #
self.setWindowTitle('Meu app')
# --- Criar o widget QCheckBox --- #
widget = QCheckBox('Isso é uma checkbox')
# --- Deixar a chekcbox já selecionada --- #
widget.setCheckState(Qt.Checked)
# --- Conectar a checkbox com a função --- #
widget.stateChanged.connect(self.mostrar_estado)
# --- Colocar o widget no centro da tela --- #
self.setCentralWidget(widget)
def mostar_estado(self, estado):
"""
Função responsável por mostrar o estado da checkbox.
:param estado: Estado da checkbox.
"""
print(estado=Qt.Checked)
print(estado)
# --- Criar a instância do app --- #
app = QApplication(sys.argv)
# --- Criar a janela do app --- #
janela = TelaPrincipal()
janela.show()
# --- Executar o loop de eventos --- #
app.exec_()
Você verá uma caixa de seleção com o texto:
Você pode definir um estado de caixa de seleção programaticamente usando .setChecked ou .setCheckState. O primeiro aceita True ou False representando marcado ou desmarcado respectivamente. No entanto, com .setCheckState você também especifica um estado parcialmente verificado usando o módulo Qt:
Tabela 4: Sinalizadores e comportamentos de QCheckBox.
Uma caixa de seleção que suporta um estado parcialmente verificado (Qt.PartiallyChecked) é comumente chamada de "estado triplo", que não está nem ativado nem desativado. Uma caixa de seleção neste estado é comumente mostrada como uma caixa de seleção acinzentada e é comumente usada em arranjos hierárquicos de caixas de seleção onde os subitens estão vinculados às caixas de seleção principais.
Se você definir o valor como Qt.PartiallyChecked a caixa de seleção ficará em um estado triplo- ou seja, terá três estados possíveis. Você também pode definir uma caixa de seleção como estado triplo sem definir o estado atual como parcialmente verificado usando .setTriState(True).
O QComboBox é uma lista suspensa, fechada por padrão com uma seta para abri-la. Você pode selecionar um único item da lista, com o item atualmente selecionado sendo mostrado como um rótulo no widget. A combobox é adequada para a seleção de uma escolha em uma longa lista de opções.
Você provavelmente já viu a caixa de combinação usada para seleção de fontes ou tamanhos de fontes em aplicativos de processamento de texto. Embora o Qt na verdade forneça uma caixa de combinação específica para seleção de fontes como QFontComboBox.
Você pode adicionar itens a um QComboBox passando uma lista de strings para .addItems(). Os itens serão adicionados na ordem em que são fornecidos:
# --- Importar as bibliotecas --- #
import sys
from PySide2.QtWidgets import QApplication, QComboBox, QMainWindow
# --- Criar a classe do app --- #
class TelaPrincipal(QMainWindow):
"""Classe que cria a tela principal do app."""
def __init__(self):
"""Função responsável por inicializar a classe."""
# --- Herdar a classe QMainWindow --- #
super().__init__()
# --- Colocar o títlo do app --- #
self.setWindowTitle('Meu app')
# --- Criar o widget QComboBox --- #
widget = QComboBox()
# --- Adicionar os itens ao combobox --- #
widget.addItems(['Um', 'Dois', 'Três'])
# --- Conectar a combobox com a função --- #
widget.currentIndexChanged.connect(self.index)
widget.currentTextChanged(self.texto)
# --- Colocar o widget no centro da tela --- #
self.setCentralWidget(widget)
def index(self, i):
"""
Função responsável por mostrar o índice do item no combobox.
:param estado: Índice do item.
"""
print(i)
def text(self, t):
"""
Função responsável por mostrar o texto do item no combobox.
:param t: Texto do item.
"""
print(t)
# --- Criar a instância do app --- #
app = QApplication(sys.argv)
# --- Criar a janela do app --- #
janela = TelaPrincipal()
janela.show()
# --- Executar o loop de eventos --- #
app.exec_()
Você verá um combobox com 3 entradas. Selecione um e ele será mostrado.
O sinal .currentIndexChanged é acionado quando o item atualmente selecionado é atualizado, passando por padrão o índice do item selecionado na lista. No entanto, ao conectar-se ao sinal, você também pode solicitar uma versão alternativa do sinal anexando [str] (pense no sinal como um dict). Em vez disso, essa interface alternativa fornece o rótulo do item atualmente selecionado, o que geralmente é mais útil.
QComboBox também pode ser editável, permitindo aos usuários inserir valores que não estão atualmente na lista e inseri-los ou simplesmente usá-los como um valor. Para tornar o combobox editável:
widget.setEditable(True)
Você também pode definir um sinalizador para determinar como a inserção será tratada. Esses flags são armazenados na própria classe QComboBox e estão listados abaixo:
Tabela 5: Sinalizadores e comportamento de QComboBox.
Para usá-los, aplique o sinalizador da seguinte maneira:
widget.setInsertPolicy(QComboBox.InsertAlphabetically)
Você também pode limitar o número de itens permitidos na caixa usando .setMaxCount, por exemplo:
widget.setMaxCount(10)
O próximo é QListBox. Este widget é semelhante ao QComboBox, exceto que as opções são apresentadas como uma lista rolável de itens. Ele também suporta a seleção de vários itens de uma só vez. Um QListBox oferece um sinal currentItemChanged que envia o QListItem (o elemento da caixa de listagem) e um sinal currentTextChanged que envia o texto do item atual:
# --- Importar as bibliotecas --- #
import sys
from PySide2.QtWidgets import QApplication, QListWidget, QMainWindow
# --- Criar a classe do app --- #
class TelaPrincipal(QMainWindow):
"""Classe que cria a tela principal do app."""
def __init__(self):
"""Função responsável por inicializar a classe."""
# --- Herdar a classe QMainWindow --- #
super().__init__()
# --- Colocar o títlo do app --- #
self.setWindowTitle('Meu app')
# --- Criar o widget QListWidget --- #
widget = QListWidget()
# --- Adicionar os itens a list --- #
widget.addItems(['Um', 'Dois', 'Três'])
# --- Conectar a lista com a função --- #
widget.currentIndexChanged.connect(self.index)
widget.urrentIndexChanged(self.texto)
# --- Colocar o widget no centro da tela --- #
self.setCentralWidget(widget)
def index(self, i):
"""
Função responsável por mostrar o item na lista.
:param estado: Item da lista.
"""
print(i.text())
def text(self, t):
"""
Função responsável por mostrar o texto do item no combobox.
:param t: Texto do item.
"""
print(t)
# --- Criar a instância do app --- #
app = QApplication(sys.argv)
# --- Criar a janela do app --- #
janela = TelaPrincipal()
janela.show()
# --- Executar o loop de eventos --- #
app.exec_()
Você verá os mesmos três itens, agora em uma lista. O item selecionado (se houver) é destacado:
O widget QLineEdit é uma caixa simples de edição de texto de linha única, na qual os usuários podem digitar informações. Eles são usados para campos de formulário ou configurações onde não há lista restrita de entradas válidas. Por exemplo, ao inserir um endereço de e-mail ou nome de computador:
# --- Importar as bibliotecas --- #
import sys
from PySide2.QtWidgets import QApplication, QLineEdit, QMainWindow
# --- Criar a classe do app --- #
class TelaPrincipal(QMainWindow):
"""Classe que cria a tela principal do app."""
def __init__(self):
"""Função responsável por inicializar a classe."""
# --- Herdar a classe QMainWindow --- #
super().__init__()
# --- Colocar o títlo do app --- #
self.setWindowTitle('Meu app')
# --- Criar a linha --- #
widget = QLineEdit()
# --- Tamanho máximo de entrada --- #
widget.setMaxLength(10)
# --- Colocar um texto padrão de fundo --- #
widget.setPlaceholderText('Escreva o seu texto')
# --- Conectar as funções ao widget --- #
widget.returnPressed.connect(self.pressionado)
widget.selectionChanged.connect(self.selecao)
widget.textChanged.connect(self.texto)
widget.textEdited.connect(self.edicao)
# --- Colocar o widget no centro da tela --- #
self.setCentralWidget(widget)
def pressionado(self):
"""Função responsável por mudar o texto quando o ENTER for pressionado."""
print('ENTER pressionado')
self.centralWidget().setText('BOOM')
def selecao(self):
"""Função responsável por retornar o texto selecionado."""
print('Texto selecionado')
print(self.centralWidget().selectedText())
def texto(self, t):
"""
Função responsável por mostrar o que está sendo escrito em tempo real.
:param t: String escrita no campo.
"""
print('Escrevendo...')
print(t)
def edicao(self, t):
"""
Função responsável por mostrar a edição da string no campo.
:param t: String editada no campo.
"""
print('Editando...')
print(t)
# --- Criar a instância do app --- #
app = QApplication(sys.argv)
# --- Criar a janela do app --- #
janela = TelaPrincipal()
janela.show()
# --- Executar o loop de eventos --- #
app.exec_()
Você verá uma caixa de entrada de texto simples, com uma dica:
Conforme demonstrado no código acima, você pode definir um comprimento máximo para o campo de texto usando .setMaxLength. O texto do espaço reservado, que é o texto mostrado até que algo seja inserido pelo usuário, pode ser adicionado usando .setPlaceholderText.
O QLineEdit tem vários sinais disponíveis para diferentes eventos de edição, incluindo quando o ENTER é pressionado (pelo usuário), quando a seleção do usuário é alterada. Há também dois sinais de edição, um para quando o texto na caixa foi editado e um para quando foi alterado. A distinção aqui é entre edições do usuário e alterações programáticas. O sinal textEdited é enviado somente quando o usuário edita o texto.
Além disso, é possível realizar validação de entrada usando uma máscara de entrada para definir quais caracteres são suportados e onde. Isso pode ser aplicado ao campo da seguinte forma:
widget.setInputMask('000.000.000-00')
O código acima cria uma máscara de entrada para um CPF.
QSpinBox fornece uma pequena caixa de entrada numérica com setas para aumentar e diminuir o valor. QSpinBox oferece suporte a números inteiros, enquanto o widget relacionado QDoubleSpinBox oferece suporte a números flutuantes:
# --- Importar as bibliotecas --- #
import sys
from PySide2.QtWidgets import QApplication, QMainWindow, QSpinBox
# --- Criar a classe do app --- #
class TelaPrincipal(QMainWindow):
"""Classe que cria a tela principal do app."""
def __init__(self):
"""Função responsável por inicializar a classe."""
# --- Herdar a classe QMainWindow --- #
super().__init__()
# --- Colocar o títlo do app --- #
self.setWindowTitle('Meu app')
# --- Criar o widget --- #
widget = QSpinBox()
# --- Configurar o valor mínimo e máximo --- #
widget.setMinimum(-10)
widget.setMaximum(3)
# --- Criar um prefixo e um sufixo --- #
widget.setPrefix('$')
widget.setSuffix('c')
# --- De quanto em quanto o widget andará --- #
widget.setSingleStep(3)
# --- Conectar as funções ao widget --- #
widget.valueChanged.connect(self.valor)
widgwt.valueChanged[str].connect(self.valor_str)
# --- Colocar o widget no centro da tela --- #
self.setCentralWidget(widget)
def valor(self, v):
"""
Função responsável por retornar o valor int mostrado no widget.
:param v: Valor int mostrado no widget.
"""
print(v)
def valor_str(self, v):
"""
Função responsável por retornar o valor str mostrado no widget.
:param v: Valor str mostrado no widget.
"""
print(v)
# --- Criar a instância do app --- #
app = QApplication(sys.argv)
# --- Criar a janela do app --- #
janela = TelaPrincipal()
janela.show()
# --- Executar o loop de eventos --- #
app.exec_()
Você verá uma caixa de entrada numérica. O valor mostra unidades pré e pós-fixadas e está limitado ao intervalo de +3 a -10:
O código de demonstração acima mostra os vários recursos disponíveis para o widget.
Para definir o intervalo de valores aceitáveis, você pode usar setMinimum e setMaximum ou, alternativamente, usar setRange para definir ambos simultaneamente. A anotação de tipos de valor é suportada com prefixos e sufixos que podem ser adicionados ao número, por exemplo. para marcadores ou unidades de moeda usando .setPrefix e .setSuffix respectivamente.
Clicar nas setas para cima e para baixo no widget aumentará ou diminuirá o valor no widget em um valor, que pode ser definido usando .setSingleStep. Observe que isso não afeta os valores aceitáveis para o widget.
Tanto QSpinBox quanto QDoubleSpinBox possuem um sinal .valueChanged que é acionado sempre que seu valor é alterado. O sinal .valueChanged bruto envia o valor numérico (um int ou um float) enquanto o sinal alternativo str, acessível via .valueChanged[str] envia o valor como uma string, incluindo os caracteres de prefixo e sufixo.
QSlider fornece um widget de barra deslizante, que funciona internamente como um QDoubleSpinBox. Em vez de exibir o valor atual numericamente, ele é representado pela posição do botão de controle deslizante ao longo do comprimento do widget. Isto é frequentemente útil quando se fornece ajuste entre dois extremos, mas onde a precisão absoluta não é necessária. O uso mais comum desse tipo de widget é para controles de volume.
Há um sinal .sliderMoved adicional que é acionado sempre que o controle deslizante move a posição e um sinal .sliderPressed que é emitido sempre que o controle deslizante é clicado:
# --- Importar as bibliotecas --- #
import sys
from PySide2.QtWidgets import QApplication, QMainWindow, QSlider
# --- Criar a classe do app --- #
class TelaPrincipal(QMainWindow):
"""Classe que cria a tela principal do app."""
def __init__(self):
"""Função responsável por inicializar a classe."""
# --- Herdar a classe QMainWindow --- #
super().__init__()
# --- Colocar o títlo do app --- #
self.setWindowTitle('Meu app')
# --- Criar o widget --- #
widget = QSlider()
# --- Configurar o valor mínimo e máximo --- #
widget.setMinimum(-10)
widget.setMaximum(3)
# --- De quanto em quanto o widget andará --- #
widget.setSingleStep(3)
# --- Conectar as funções ao widget --- #
widget.valueChanged.connect(self.valor)
widget.sliderMoved.connect(self.posicao)
widget.sliderPressed.connect(self.pressionar)
widget.slider.Released.connect(self.soltar)
# --- Colocar o widget no centro da tela --- #
self.setCentralWidget(widget)
def valor(self, v):
"""
Função responsável por retornar o valor do slider.
:param v: Valor do slide.
"""
print(v)
def posicao(self, p):
"""
Função responsável por mostrar a posição onde o slider parou.
:param p: Posição do slider.
"""
print('Posição', p)
def pressionar(self):
"""Função responsável por mostrar que o slider foi clicado."""
print('Pressionado')
def soltar(self):
"""Função responsável por mostrar que o slider foi solto."""
print('Solto')
# --- Criar a instância do app --- #
app = QApplication(sys.argv)
# --- Criar a janela do app --- #
janela = TelaPrincipal()
janela.show()
# --- Executar o loop de eventos --- #
app.exec_()
Você verá um widget deslizante. Arraste o controle deslizante para alterar o valor:
Você também pode construir um controle deslizante com orientação vertical ou horizontal, passando a orientação conforme você o cria. Os sinalizadores de orientação são definidos no Qt. Por exemplo:
widget.QSlider(Qt.Vertical)
# Ou
widget.QSlider(Qt.Horizontal)
Por fim, o QDial é um widget giratório que funciona exatamente como o controle deslizante, mas aparece como um mostrador analógico. Parece bom, mas do ponto de vista da interface do usuário não é particularmente amigável. No entanto, eles são frequentemente usados em aplicações de áudio como representação de mostradores analógicos do mundo real:
# --- Importar as bibliotecas --- #
import sys
from PySide2.QtWidgets import QApplication, QDial, QMainWindow
# --- Criar a classe do app --- #
class TelaPrincipal(QMainWindow):
"""Classe que cria a tela principal do app."""
def __init__(self):
"""Função responsável por inicializar a classe."""
# --- Herdar a classe QMainWindow --- #
super().__init__()
# --- Colocar o títlo do app --- #
self.setWindowTitle('Meu app')
# --- Criar o widget --- #
widget = QDial()
# --- Configurar o intervalo --- #
widget.setRange(-10, 100)
# --- Configurar quanto o widget andará --- #
widget.setSingleStep(0.5)
# --- Conectar as funções ao widget --- #
widget.valueChanged.connect(self.valor)
widget.sliderMoved.connect(self.posicao)
widget.sliderPressed.connect(self.pressionar)
widget.slider.Released.connect(self.soltar)
# --- Colocar o widget no centro da tela --- #
self.setCentralWidget(widget)
def valor(self, v):
"""
Função responsável por retornar o valor do slider.
:param v: Valor do slide.
"""
print(v)
def posicao(self, p):
"""
Função responsável por mostrar a posição onde o slider parou.
:param p: Posição do slider.
"""
print('Posição', p)
def pressionar(self):
"""Função responsável por mostrar que o slider foi clicado."""
print('Pressionado')
def soltar(self):
"""Função responsável por mostrar que o slider foi solto."""
print('Solto')
# --- Criar a instância do app --- #
app = QApplication(sys.argv)
# --- Criar a janela do app --- #
janela = TelaPrincipal()
janela.show()
# --- Executar o loop de eventos --- #
app.exec_()
Você verá um mostrador, gire-o para selecionar um número do intervalo:
Os sinais são iguais aos de QSlider e mantêm os mesmos nomes (por exemplo, .sliderMoved).
Isso conclui nosso breve tour pelos widgets Qt disponíveis no PySide2. Para ver a lista completa de widgets disponíveis, incluindo todos os seus sinais e atributos, dê uma olhada na documentação do Qt.
Anteriormente, usamos QWidget em nosso primeiro exemplo para criar uma janela vazia. Mas QWidget também pode ser usado como um contêiner para outros widgets, junto com layouts, para construir janelas ou widgets compostos. Abordaremos a criação de widgets personalizados com mais detalhes posteriormente.
Lembre-se do QWidget, pois você verá muito dele!