- PyQt 01 – O Primeiro Programa
- PyQt 02 – Criando uma caixa de mensagem
- PyQt 03 – Diálogos com QMessageBox
- PyQt 04 – Diálogos com QInputDialog
- PyQt 05 – Diálogo QFileDialog
- PyQt 06 – Mais diálogos
- PyQt 07 – QLabel e Qt Designer
- PyQt 08 – QLineEdit e mais Qt Designer
- PyQt 09 – QPushButton, apertando os botões
- PyQt 10 – QCheckBox e QRadioButton: checando as opções
- PyQt 11 – QButtonGroup e QGroupBox: mais opções
- PyQt 12 – QComboBox
- PyQt 13 – QSpinBox, QProgressBar e + sinais
A próxima widget a ser apresentada é a QLineEdit, uma entrada de texto simples, em uma única linha, que permite alguns comandos de edição simples como paste, copy, drag, drop, undo e redo, além de aceitar as mais usuais combinações de teclas de atalho. Para uma descrição mais aprofundada, veja o manual da QLineEdit
Neste texto vou montar um pequeno diálogo para o cadastro de usuários, utilizando os widgets QLineEdit e QLabel, manualmente e depois usando o Qt Designer. A partir deste artigo, todos os diálogos serão criados apenas com o uso do Qt Designer.
Construindo o diálogo de cadastro manualmente
Como no artigo anterior, inicie o aplicativo com as linhas gerais, abaixo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #!/bin/env python # -*- coding: iso-8859-1 -*- # # Diálogo para cadastro por Rudson R. Alves # import sys from PyQt4.QtCore import * from PyQt4.QtGui import * class cadastro_Dialog(QDialog): def __init__(self, parent = None): super(cadastro_Dialog, self).__init__(parent) # ... definir o diálogo aqui ... app = QApplication(sys.argv) dlg = cadastro_Dialog() dlg.exec_() |
Isto cria a estrutura geral do aplicativo. Se executar o código acima, ele irá gerar um diálogo vazio. Para este texto, será criado um diálogo com a aparência da figura a seguir:
O código para gerar este diálogo é apresentado a seguir:
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 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | #!/bin/env python #-*- coding: iso-8859-1 -*- # # Diálogo para cadastro por Rudson R. Alves # import sys from PyQt4.QtCore import * from PyQt4.QtGui import * class cadastro_Dialog(QDialog): def __init__(self, parent = None): super(cadastro_Dialog, self).__init__(parent) # cria uma vbox para o diálogo inteiro e o aplica ao diálogo vbox = QVBoxLayout() self.setLayout(vbox) # cria label e nome_lineEdit do nome label = QLabel("Nome:") self.nome_lineEdit = QLineEdit("") # cria uma hbox para adicionar label e nome_lineEdit hbox = QHBoxLayout() # povoa a hbox hbox.addWidget(label) hbox.addWidget(self.nome_lineEdit) # adiciona a hbox ao vbox vbox.addLayout(hbox) # cria label, senha_lineEdit e senha_check_lineEdit label = QLabel("Senha:") self.senha_lineEdit = QLineEdit() self.senha_check_lineEdit = QLineEdit() # cria uma nova hbox hbox = QHBoxLayout() # povoa a hbox hbox.addWidget(label) hbox.addWidget(self.senha_lineEdit) hbox.addWidget(self.senha_check_lineEdit) # adiciona a hbox ao vbox vbox.addLayout(hbox) # cria label e foto_lineEdit label = QLabel("Foto:") self.foto_lineEdit = QLineEdit() # cria uma nova hbox hbox = QHBoxLayout() # povoa a hbox hbox.addWidget(label) hbox.addWidget(self.foto_lineEdit) # adiciona a hbox ao vbox vbox.addLayout(hbox) # cria foto_label e image self.foto_label = QLabel() self.foto_label.setAlignment(Qt.AlignCenter) self.foto_label.setPixmap(QPixmap('qlineedit-01.jpeg')) # adiciona a foto_label a vbox vbox.addWidget(self.foto_label) app = QApplication(sys.argv) dlg = cadastro_Dialog() dlg.exec_() |
o código está todo comentado, mas ainda cabe algumas adições aqui. Observe que o widgets nomeados label, definido na linha 20 e redefinido nas linhas 31 e 44 não foram definidas com o prefixo ‘self.‘, como nas variáveis nome_lineEdit, senha_lineEdit, senha_check_lineEdit, foto_lineEdit e foto_label.
Isto se deve ao fato de não haver a necessidade de acessar estes objetos durante a execução do programa. Os widgets nomeados hbox e vbox seguem o mesmo princípio da widget label. Num diálogo criado no Qt Designer, todos os widgets serão definidos com o prefixo ‘self.’, mesmo que não venham a ser acessados posteriormente. Isto em si não interfere no funcionamento ou eficiência do diálogo.
A figura a seguir enfatizam as hbox e vbox criadas para organizarem o diálogo.
Os quadros em vermelho são as hbox criadas nas linhas 23, 35 e 47, respectivamente. A vbox está em verde e ela contem as três hbox criadas e o elemento foto_label
A classe QPixmap, linha 57, cria uma representação da imagem jpeg que pode ser compreendido pelo QLabel.setPixmap, para desenhar a imagem.
Construindo o diálogo de cadastro pelo Qt Designer
A construção do diálogo pelo Qt Designer segue o mesmo princípio das linhas apresentadas acima. Em princípio crie um diálogo com todos os elementos disposto aproximadamente nas posições desejadas.
As propriedades editadas em cada widget são apresentadas na tabela abaixo:
Tab 01: Propriedades das widgets. A coluna # contém o número do widget, representado na figura anterior.
| # | Propriedade | Valor |
|---|---|---|
| 1 | objectName | nome_lineEdit |
| 2 | objectName | senha_lineEdit |
| 3 | objectName | senha_check_lineEdit |
| 4 | objectName | foto_lineEdit |
| 5 | objectName | foto_label |
| 5 | pixmap | qlineedit-01.jpeg |
| 5 | alignment-> Horizontal | AlignHCenter |
Em seguida selecione o QLabel ‘Nome:’ e o QLineEdit nome_lineEdit e clique no botão Lay out Horizontally. Isto fará o primeiro hbox da linha 23, do código anterior.
Repita o processo para os QLabel ‘Senha:’ e os QLineEdit senha_lineEdit e senha_check_lineEdit. Faça isto mais uma vez para o QLabel ‘Foto:’ e o QLineEdit foto_lineEdit. Isto deve deixar o diálogo com a aparência abaixo:
Para terminar o diálogo, desmarque todos os widgets, conforme a figura acima, e clique no botão Lay out Vertically. Isto irá arranjar os hbox e o foto_lineEdit em uma lista vertical. O diálogo pronto fica com a aparência abaixo:
Troque o objectName do diálogo para ‘cadastro_Dialog‘ e salve com o nome ‘cadastro.ui‘. Depois gere o diálogo com o comando pyuic4:
O código básico, para gerar o diálogo deve carregar o módulo cadastro.py (linha 10, no código abaixo), herdar a classe Ui_cadastro_Dialog (linha 12) e executar o método setupUi (linha 15) para criar os elementos do diálogo. As linhas abaixo fazem o serviço.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #!/bin/env python #-*- coding: iso-8859-1 -*- # # Diálogo para cadastro por Rudson R. Alves # import sys from PyQt4.QtCore import * from PyQt4.QtGui import * from cadastro import * class cadastro_Dialog(QDialog, Ui_cadastro_Dialog): def __init__(self, parent = None): super(cadastro_Dialog, self).__init__(parent) self.setupUi(self) app = QApplication(sys.argv) dlg = cadastro_Dialog() dlg.exec_() |
Explorando os sinais do QLineEdit
A implementação deste diálogo será em cima dos sinais emitidos pelo widget QLineEdit. Estes sinais são listados na tabela a segui:
Tab 02: Sinais do QLineEdit
| Sinal | Descrição |
|---|---|
| cursorPositionChanged(int old_pos, int new_pos) | este sinal é emitido sempre que o cursor se move de uma posição antiga para uma posição nova |
| editingFinished() | este sinal é emitido quando as teclas Return ou Enter são pressionadas, ou a linha perde o foco |
| returnPressed() | este sinal é emitido quando as teclas Return ou Enter são pressionadas |
| selectionChanged() | este sinal é emitido quando a seleção é alterada |
| textChanged(QString text) | este sinal é emitido quanto o texto é alterado. text é o texto alterado |
| textEdited(QString text) | este sinal é emitido quando o texto é editado. text é o texto editado. Diferentemente do textChanged, este sinal não é enitido quanto o texto é alterado via comando como o setText |
As linhas a seguir permite explorar cada sinal descrito na tabela acima. As três linhas abaixo capturam o sinal cursorPositionChanged, que retorna a posição anterior e atual do cursor na linha em edição, nas variáveis old_pos e new_pos.
17 18 19 | @pyqtSignature("int, int") def on_nome_lineEdit_cursorPositionChanged(self, old_pos, new_pos): print 'cursorPositionChanged: cursor movido de %d para %d' % (old_pos, new_pos) |
Observe que para recuperar os dois inteiros, é necessário passar como argumento ao pyqtSignature os tipos em uma única string, “int, int”. Execute o diálogo, escreva algo no QLineEdit e mova o cursor ao longo do texto. As mudanças na posição do cursor serão impressos no terminal.
Para facilitar a visualização dos diferentes sinais, comente as linhas acima e adicione as próximas linhas para implementar a captura dos sinais editingFinished e returnPressed no QLineEdit nome_lineEdit.
21 22 23 24 25 26 27 | @pyqtSignature("") def on_nome_lineEdit_editingFinished(self): print 'editingFinished...' @pyqtSignature("") def on_nome_lineEdit_returnPressed(self): print 'returnPressed...' |
Com estas linhas, um editingFinished… será impresso sempre que um return ou enter for pressionado em nome_lineEdit, ou este widget perder o foco. Já um returnPressed será emitido apenas quando um return for pressionado em nome_lineEdit.
Para as próximas linhas não é necessário comentar as linhas anteriores. Apenas adicione as próximas linhas para implementar o sinal selectionChanged.
29 30 31 | @pyqtSignature("") def on_nome_lineEdit_selectionChanged(self): print 'selectionChanged...' |
Execute novamente o diálogo e insira algum texto no widget nome_lineEdit. Selecione partes do texto e altere a seleção algumas vezes para que o sinal selectionChanged seja capturado.
Os dois últimos sinais são implementados com as linhas abaixo:
33 34 35 36 37 38 39 40 41 42 43 | @pyqtSignature("QString") def on_nome_lineEdit_textChanged(self, text): print 'textChanged: >%s<' % text @pyqtSignature("QString") def on_nome_lineEdit_textEdited(self, text): print ' textEdited: >%s<' % text @pyqtSignature("") def on_foto_lineEdit_returnPressed(self): self.nome_lineEdit.setText(self.foto_lineEdit.text()) |
Este código é apenas para teste, por isto ainda não tem o objetivo de ser funcional. As linhas acima capturam os dois sinais textChanged e textEdited em nome_lineEdit.
As três últimas linhas, 41 à 43, implementam a captura do sinal returnPressed em foto_lineEdit. Quando um return é pressionado, durante a edição deste widget, foto_lineEdit, o texto contido nele é copiado para o nome_lineEdit, linha 44. Observe que neste caso apenas um sinal textChanged é emitido por nome_lineEdit, neste momento, já que textEdited não é sensível a edições via comando.
Implementando o Diálogo
Este diálogo irá pegar o nome do usuário, uma senha e o caminho de uma foto e retornar. A senha deve ser omitida e conferida antes de ser aceita. O código a seguir faz esta implementaçã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 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | #!/bin/env python #-*- coding: iso-8859-1 -*- # # Diálogo para cadastro por Rudson R. Alves # import sys, os from PyQt4.QtCore import * from PyQt4.QtGui import * from cadastro import * class cadastro_Dialog(QDialog, Ui_cadastro_Dialog): def __init__(self, parent = None): super(cadastro_Dialog, self).__init__(parent) self.setupUi(self) self.senha_lineEdit.setEchoMode(QLineEdit.PasswordEchoOnEdit) self.senha_check_lineEdit.setEchoMode(QLineEdit.Password) self.nome = self.nome_lineEdit.text() self.senha = self.senha_lineEdit.text() self.foto = self.foto_lineEdit.text() @pyqtSignature("") def on_nome_lineEdit_editingFinished(self): #print 'Nome editado...' self.nome = self.nome_lineEdit.text() @pyqtSignature("") def on_nome_lineEdit_returnPressed(self): self.senha_lineEdit.setFocus() @pyqtSignature("") def on_senha_lineEdit_editingFinished(self): #print 'Senha editada...' self.senha = self.senha_lineEdit.text() @pyqtSignature("") def on_senha_lineEdit_returnPressed(self): self.senha_check_lineEdit.setFocus() @pyqtSignature("") def on_senha_check_lineEdit_editingFinished(self): #print 'Senha check editada...' if self.senha != self.senha_check_lineEdit.text() or self.senha == "": QMessageBox.question(None, "Senha erro", \ "As senhas digitadas não conferrem ou senha em branco.\nReentre com a senha.") self.senha_lineEdit.setText("") self.senha_check_lineEdit.setText("") self.senha = "" self.senha_lineEdit.setFocus() @pyqtSignature("") def on_senha_check_lineEdit_returnPressed(self): self.foto_lineEdit.setFocus() @pyqtSignature("") def on_foto_lineEdit_editingFinished(self): #print 'Foto editada...' self.foto = self.foto_lineEdit.text() if self.foto != "": if os.path.isfile(self.foto): self.foto_label.setPixmap(QPixmap(self.foto)) else: self.foto = "" app = QApplication(sys.argv) dlg = cadastro_Dialog() dlg.exec_() print 'Nome: %s' % dlg.nome print 'Senha: %s' % dlg.senha print 'Imagem: %s' % dlg.foto |
As linhas 17 e 18 alteram o atributo EchoMode dos widgets QLineEdit senha_lineEdit e senha_check_lineEdit. Observe que estas alterações podem muito bem serem feitas com a edição do diálogo no Qt Designer, sem a necessidade da adição destas linhas.
Os EchoModes aceitos pelo QLineEdit são apresentados na tabela abaixo.
Tab 03: Modos do echo de caracteres no QLineEdit
| Constante | Valor | Descrição |
|---|---|---|
| QLineEdit.Normal | 0 | Apresenta os caracteres como eles são digitados. Padrão. |
| QLineEdit.NoEcho | 1 | Não mostra nada.. Este modo é apropriado para passwords onde o números de caracteres digitados também deve ser permanecer em segredo |
| QLineEdit.Password | 2 | Mostra asteriscos, ou uma bolinha, no lugar dos caracteres pressionados |
| QLineEdit.PasswordEchoOnEdit | 3 | Apresenta os caracteres digitados durante a edição e mostra asteriscos terminar |
Para este diálogo utilizei os modos QLineEdit.Password e QLineEdit.PasswordEchoOnEdit, apenas a título de demonstração.
As linhas com o comando print, comentadas, (26, 35, 44 e 59) são apenas para rastreio do código em tempo de execução. Isto pode ser de muita ajuda, caso não se tenha um debug para acompanhar a execução do código.
Como o evento returnPressed não muda o foco para a widget seguinte, implementei esta mudança para cada QLineEdit, nas linhas 30 (nome_lineEdit), 39 (senha_lineEdit) e 54 (senha_check_lineEdit).
As variáveis nome, senha e foto, definidas nas linhas 20 a 22, em princípio não são necessárias, uma vez que seus valores podem ser lidos das widgets nome_lineEdit), senha_lineEdit e foto_lineEdit. No entanto, dá um controle melhor sobre as variáveis editadas, além de um acesso mais simples, como feito nas linhas 71 a 73, quando imprime os resultados capturados pelo diálogo.
A linha 45 avalia se as senhas em senha_lineEdit e senha_check_lineEdit são equivalentes, além de recusar uma senha em branco.
A linha 61 verifica se o nome do arquivo passado existe, no entanto não checa se ele é uma imagem.
O código é apenas para demonstra o diálogo em funcionamento, carecendo de comentários e melhor tratamento de possíveis exceções. Mas espero que tenha atingido o objetivo de apresentar a widget QLineEdit.
O código e diálogo apresentados neste texto podem ser baixados do link: pyqt-08.zip.
<< PyQt 07 – QLabel e Qt Designer PyQt 09 – QPushButton, apertando os botões >>
You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.
One Trackback/Ping
-
Resolução de Sistemas Matriciais – PyQt4 « Diário de um programador Jun 04 2010 at 8pm:
[...] um caso viu!! Incrementei um pouco as coisas a partir do código do Post anterior, coloquei algumas QLineEdits, misturei mais um monde de outras coisas e “VUA-LÁ”. [...]






4 comments so far
Rodrigo
renatopolimeno
rudsonalves
Eduardo Carvalho