PyQt 11 – QButtonGroup e QGroupBox: mais opções

maio 30th, 2010 by rudsonalves Leave a reply »

Este artigo é mais uma continuação do anterior, onde será tratado o uso das widgets QButtonGroup e QGroupBox. Estas widgets são containers para botões, checkbox e radiobuttons, assim como outros widgets. Essencialmente elas servem para agrupar as widgets, no entanto com habilidades diferentes.

QButtonGroup: Sinais

A QButtonGroup não possui uma representação gráfica, ela apenas cria um container abstrato para agrupar diversas widgets. Os sinais suportados são apresentados na tabela abaixo:

Sinal Descrição
buttonClicked(QAbstractButton *) Este sinal é emitido quando um botão é clicado. QAbstractButton é o botão pressionado.
buttonClicked(int) O mesmo que o anterior, onde int é um índece -2, -3, … dependedo da ordem do botão pressionado
buttonPressed(QAbstractButton *) Este sinal é emitido quando um botão é pressionado
buttonPressed(int) O mesmo que o anterior, onde int é um índece -2, -3, …
buttonReleased(QAbstractButton *) Este sinal é emitido quando um botão é liberado
buttonReleased(int) O mesmo que o anterior, onde int é um índece -2, -3, …

Em buttonClicked entende-se por clicado quando um botão é pressionado e então liberado, quando o seu caractere de shortcut é teclado, ou quando um QAbstractButton.click() ou QAbstractButton.animateClick() é chamado por linha de comando.

Um Teclado Numérico

Para demonstrar o QButtonGroup, fiz um diálogo com um teclado numérico, conforme a figura abaixo:

Neste primeiro código, os botões numéricos, QPushButtons, foram agrupados no grupo buttonGroup_numbers. O código e a ui estão no arquivo zip: pyqt-11.zip.

Para criar um grupo com o QT Designer, basta apenas marcar os botões que se deseja agrupar e clicar com o botão esquerdo do mouse que aparecerá a opção “Assign to button group -> New button group”. Em seguida basta renomear o grupo para o nome desejado, neste caso “buttonGroup_numbers”.

Via linha código, basta colocar as linhas abaixo dentro da classe principal:

14
15
16
17
18
19
20
21
22
  self.buttonGroup_numbers = QtGui.QButtonGroup(self)
  self.buttonGroup_numbers.addButton(self.pushButton_10)
  self.buttonGroup_numbers.addButton(self.pushButton)
  self.buttonGroup_numbers.addButton(self.pushButton_2)
  self.buttonGroup_numbers.addButton(self.pushButton_3)
  self.buttonGroup_numbers.addButton(self.pushButton_4)
  self.buttonGroup_numbers.addButton(self.pushButton_5)
  self.buttonGroup_numbers.addButton(self.pushButton_6)
  ...

Observe que a numeração esta um tanto desorganizada. Isto aconteceu pois não me preocupei em renomear os widgets, enquanto produzia o diálogo. No entanto isto não interfere em nada no código, pois os valores dos botões são tomados em seu texto e não em seu índice.

No código acima, a linha 14 define a grupo buttonGroup_numbers, e a atribui a classe principal (self). As demais linha adicionam os botões numéricos ao grupo buttonGroup_numbers.

O código a seguir implementa o sinal buttonClicked(QAbstractButton *) para capturar o botão clicado, no entanto o grupo buttonGroup_numbers foi implementado na Ui, via Qt Designer, e por isto não aparece na listagem a segui:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#!/bin/env python
# -*- coding: iso-8859-1 -*-
#
# por Rudson R. Alves
#
 
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from Dialogo_tecladoNumerico_1 import *
 
 
class CheckBoxDialog(QDialog, Ui_Dialog_Teclado):
  def __init__(self, parent = None):
    super(CheckBoxDialog, self).__init__(parent)
    self.setupUi(self)
 
  @pyqtSignature("QAbstractButton *")
  def on_buttonGroup_numbers_buttonClicked(self, button):
    print u'PushButton %s' % button.text()
 
 
app = QApplication(sys.argv)
dlg = CheckBoxDialog()
dlg.exec_()

Observe que o sinal “buttonClicked(QAbstractButton *)” capturado nas linhas 18 e 19, é bastante conveniente para esta tarefa, pois retorna o botão pensionado, sem a necessidade de nenhum comando adicional. A execução deste código gera a saída a seguir, quanto os botões de 0 a 9 são pressionados em ordem:

rudson@khelben:$ ./qbuttongroup-01
PushButton 0
PushButton 1
PushButton 2
PushButton 3
PushButton 4
PushButton 5
PushButton 6
PushButton 7
PushButton 8
PushButton 9

Um teclado de Botões Checkables

Para o próximo código é necessário que os botões numéricos tenham a propriedade checkable acionada, o que necessita de uma edição com o Qt Designer. A ui Dialogo_tecladoNumerico_2 possui esta alteração.

O código a segui faz algo semelhante ao anterior, com uma pequena diferença, ele usa o sinal “buttonClicked(int)”. O botão checado é retornado na variável button, através do uso do método checkedButton() do grupo buttonGroup_numbers, que retorna o QAbstractButton checado. Isto é feito na 20, do código abaixo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#!/bin/env python
# -*- coding: iso-8859-1 -*-
#
# por Rudson R. Alves
#
 
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from Dialogo_tecladoNumerico import *
 
 
class CheckBoxDialog(QDialog, Ui_Dialog_Teclado):
  def __init__(self, parent = None):
    super(CheckBoxDialog, self).__init__(parent)
    self.setupUi(self)
 
  @pyqtSignature("int")
  def on_buttonGroup_numbers_buttonClicked(self, index):
    button = self.buttonGroup_numbers.checkedButton()
    print u'PushButton %s status é %s, seu index -e: %d' % \
                                (button.text(), button.isChecked(), index)
 
 
app = QApplication(sys.argv)
dlg = CheckBoxDialog()
dlg.exec_()

Trabalhando com dois Grupos

O próximo código implementa o diálogo usado no artigo anterior, com o emprego de dois grupos de QCheckBoxs. Isto é fundamental para se fazer diferentes grupos em um mesmo diálogo.

Os grupos usados serão:

  • buttonGroup_browsers, para agrupar os QCheckBox dos navegadores;
  • e buttonGroup_messages, para agrupar os QCheckBox dos aplicativos de mensagem

O diálogo é mostrado na figura seguinte e o código, na sequência.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#!/bin/env python
# -*- coding: iso-8859-1 -*-
#
# por Rudson R. Alves
#
 
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from Dialogo_Navegador import *
 
 
class CheckBoxDialog(QDialog, Ui_Dialog_Navegador):
  def __init__(self, parent = None):
    super(CheckBoxDialog, self).__init__(parent)
    self.setupUi(self)
 
  @pyqtSignature("QAbstractButton *")
  def on_buttonGroup_browsers_buttonClicked(self, button):
    print u'Navegador selecionado: %s' % button.text()
 
  @pyqtSignature("QAbstractButton *")
  def on_buttonGroup_messages_buttonClicked(self, button):
    print u'Message selecionado: %s' % button.text()
 
app = QApplication(sys.argv)
dlg = CheckBoxDialog()
dlg.exec_()

Neste caso, os sinais dos dois grupos são capturados e tratados independentemente no diálogo, nas linhas 18 (buttonGroup_browsers) e 23 (buttonGroup_messages).

QGroupBox: Sinais

Diferente da QButtonGroup, a widget QGroupBox possui uma representação gráfica, criando um frame onde os botões, checkbox, … são arrumados. Uma QGroupBox também possui um título e uma caixa de checagem (normalmente desabilitada). Embora uma QGroupBox separe os grupos de botões, checkbox, …, ela não possui as mesmas propriedades de uma QButtonGroup, ou seja, ela não identifica qualquer alteração nas widgets internas ao frame. Isto significa que mesmo usando uma QGroupBox, ainda será necessário usar a QButtonGroup para gerenciar nas alterações nas widgets internas.

A tabela a seguir apresenta os sinais suportados pela widget QGroupBox:

Sinal Descrição
clicked(bool) Este sinal é meitido quando o checkbox é ativado
toggled(bool) Se o grupo é checkable, este sinal é emitido quando o checkbox é alterado

No sinal clicked, acima, entende-se por ativado aqui, quando o mouse é pressionado e liberado sobre o botão, ou quando o caractere de shortcut é teclado. Este sinal também é emitido quando o método setChecked() é chamado.

Adicionando Frames

Adicionei duas QGroupBox para organizar o diálogo, deixando-o como mostra a figura abaixo:

O código a seguir mostra o diálogo em ação:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#!/bin/env python
# -*- coding: iso-8859-1 -*-
#
# por Rudson R. Alves
#
 
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from Dialogo_Navegador_2 import *
 
 
class CheckBoxDialog(QDialog, Ui_Dialog_Navegador):
  def __init__(self, parent = None):
    super(CheckBoxDialog, self).__init__(parent)
    self.setupUi(self)
 
  @pyqtSignature("QAbstractButton *")
  def on_buttonGroup_browsers_buttonClicked(self, button):
    print u'Navegador selecionado: %s' % button.text()
 
  @pyqtSignature("QAbstractButton *")
  def on_buttonGroup_messages_buttonClicked(self, button):
    print u'Message selecionado: %s' % button.text()
 
  @pyqtSignature("bool")
  def on_groupBox_msg_clicked(self, status):
    print u'Message GroupBox está: %s' % status
 
app = QApplication(sys.argv)
dlg = CheckBoxDialog()
dlg.exec_()

Essencialmente ele é o mesmo código anterior, apenas inseri as linhas 26 a 28 para tratar a checkbox do QGroupBox groupBox_msg.

Considerações Finais

Sempre achei que o GroupBox fizesse algo semelhante ao ButtonGroup, ou seja, que criasse um ButtonGroup ao seu conjunto de botões definidos internamente. No entanto não é bem isto o que ocorre como pode ser visto acima.

Isto é apenas mais um dos papeis fundamentais destes textos, me obrigar a conhecer melhor as widgets da lib Qt, e com isto melhorar o uso deste código.

Advertisement

Deixe uma resposta