|
| 1 | +# Projeto Python |
| 2 | + |
| 3 | +### Projeto desenvolvido em [PyQt5](https://pypi.org/project/PyQt5/) e [QtDesigner](https://doc.qt.io/). |
| 4 | + |
| 5 | +- A escolha pelo PyQt como Interface Gráfica. |
| 6 | + |
| 7 | +O PyQt se destaca de outras GUI (exemplo Tkinter) pela sua aparência mais 'moderna', no entanto, a escolha pela |
| 8 | +biblioteca se deu principalmente pela possibilidade do uso da ferramenta QtDesigner que facilita e abstrai |
| 9 | +a programação, sendo uma opção mais interessante para iniciantes (meu caso) ou para quem precise aumentar a |
| 10 | +produtividade. |
| 11 | + |
| 12 | + |
| 13 | +### Descrição do Projeto |
| 14 | + |
| 15 | +- O Projeto está dividido em Módulos independentes entre si (podendo ser executados de maneira individual) |
| 16 | +porém integrados por uma interface principal (Tela Main); |
| 17 | +- No Projeto foram aplicados os principais conceitos da linguagem Python servindo de material de consulta |
| 18 | +tanto da linguagem como da ferramenta Qt e bibliotecas aqui empregadas; |
| 19 | +- O Projeto é de Nível Iniciante, sendo assim, não foram aqui utilizados conceitos avançados de programação |
| 20 | +(Expressões Regulares ou Decoradores, por exemplo), bem como não foram implementadas conexões à Banco de Dados |
| 21 | +ou Políticas de Segurança, ainda que, em ambiente de produção seriam necessárias; |
| 22 | +- O Projeto está organizado por pastas. |
| 23 | + - Pasta Arquivos - Arquivos .txt usados na aplicação; |
| 24 | + - Pasta Imagens - Imagens usadas na aplicação, ícones usados no título de cada Tela e |
| 25 | + Screenshots usados neste Readme; |
| 26 | + - Pasta Módulos - Sripts de cada tela. |
| 27 | +- O Projeto traz uma tela principal onde por ela é possivel chamar outras seis telas sendo que, cada uma traz |
| 28 | +um projeto com funcionalidades específicas. Abaixo a descrição de cada uma das telas e suas funcionalidades: |
| 29 | + |
| 30 | +### Tela Main |
| 31 | + |
| 32 | + |
| 33 | + |
| 34 | + |
| 35 | +- Todas as telas são responsivas e cada uma delas traz um ícone na parte superior esquerdo da tela: |
| 36 | +`tela_main.setWindowIcon(QtGui.QIcon('../imagens/application-icon.png'))` |
| 37 | +bem como um título para cada tela:`tela_main.setWindowTitle('Projetos Python')` |
| 38 | + |
| 39 | +- Na tela Main foram implementados seis botões. Cada um dos botões quando acionado chama uma função que |
| 40 | +por sua vez exibe uma tela: |
| 41 | +``` |
| 42 | +def chamar_calculadora(): |
| 43 | + import calculadora |
| 44 | + calculadora.tela_calculadora.show() |
| 45 | + calculadora.app.exec() |
| 46 | + tela_main.close() |
| 47 | +``` |
| 48 | +- Foi também implementado em cada tela um botão 'Voltar', ao chamar essa função a tela atual é fechada e a Tela Main |
| 49 | +é novamente exibida. |
| 50 | + |
| 51 | +### Tela Calculadora |
| 52 | + |
| 53 | + |
| 54 | + |
| 55 | +- Nesta tela foram implementados 19 botões. Ao ser pressionado o botão chama uma função que adiciona ao display o valor pré definido |
| 56 | +ao botão, exemplo sinal de '+'. |
| 57 | +``` |
| 58 | +valores = '+' |
| 59 | +tela_calculadora.label_display.setText(valores) |
| 60 | +``` |
| 61 | + |
| 62 | +- Ao ser pressionado o botão '=' este chama a função [eval](https://docs.python.org/3/library/functions.html?highlight=eval#eval) |
| 63 | +com os valores disponíveis no display. |
| 64 | +``` |
| 65 | +valores = str(eval(valores)) |
| 66 | +tela_calculadora.label_display.setText(valores) |
| 67 | +``` |
| 68 | + |
| 69 | +- Também foram tratados eventuais erros: |
| 70 | + |
| 71 | +Os valores visíveis no display foram limitados à 14: |
| 72 | +``` |
| 73 | +def botao_zero(): |
| 74 | + tela_calculadora.label_display.setText('0') |
| 75 | + if len(valores) <= 14: |
| 76 | + valores += tela_calculadora.label_display.text() |
| 77 | + tela_calculadora.label_display.setText(valores) |
| 78 | +``` |
| 79 | + |
| 80 | +Os sinais de operação ('+', '-', '*' e '/') só serão inseridos se já não houverem sido inseridos: |
| 81 | +``` |
| 82 | +if valores[-1] != '+' and valores[-1] != '-'\ |
| 83 | + and valores[-1] != '/' and valores[-1] != '*': |
| 84 | + valores += '+' |
| 85 | +tela_calculadora.label_display.setText(valores) |
| 86 | +``` |
| 87 | + |
| 88 | +Ao usar a função built-in [eval](https://docs.python.org/3/library/functions.html?highlight=eval#eval) a aplicação |
| 89 | +ficou vunerável a erros pois, a citada função avalia a expressão inserida, neste caso os valores inseridos em forma de |
| 90 | +str no display, e aplica os operadores matemáticos presentes na expressão. Assim, erros como vários pontos '.' na mesma |
| 91 | +expressão (exemplo 2.2.2 + 2.2.2) ou operações de divisão por zero (exemplo 2 dividido por zero) poderiam |
| 92 | +ocorrer. Para tratar esses erros foram usados [TRY EXECPTION](https://docs.python.org/3/reference/compound_stmts.html#try) |
| 93 | +em conjunto com o [QMessageBox do PyQt](https://doc.qt.io/qtforpython-5/PySide2/QtWidgets/QMessageBox.html). Ao acionar |
| 94 | +o botão '=' é chamada a função 'eval' que avalia a expressão e retorna o resultado. Se retornar um erro é então exibida |
| 95 | +uma caixa de alerta com uma mensagem ao usuário. |
| 96 | + |
| 97 | +``` |
| 98 | +def botao_igual(): |
| 99 | + global valores |
| 100 | + try: |
| 101 | + valores = str(eval(valores)) |
| 102 | + except: |
| 103 | + QMessageBox.about(tela_calculadora, 'Erro!', 'Revise os valores.') |
| 104 | + finally: |
| 105 | + tela_calculadora.label_display.setText(valores) |
| 106 | +``` |
| 107 | + |
| 108 | + |
| 109 | + |
| 110 | + |
| 111 | +### Tela IMC |
| 112 | + |
| 113 | + |
| 114 | + |
| 115 | +- Nesta tela o usuário insere a altura e peso. O programa então retorna o IMC baseado na fórmula: |
| 116 | + |
| 117 | +``` |
| 118 | +IMC = Peso ÷ (Altura ×ばつ Altura) |
| 119 | +``` |
| 120 | + |
| 121 | +- Foi adicionado uma sequência de condicionais para complementar as informações de retorno ao usuário: |
| 122 | + |
| 123 | +``` |
| 124 | + if imc <= 18.5: |
| 125 | + tela_imc.label_mensagem.setText(' Classificação: Magreza - Obsidade: Grau 0 ') |
| 126 | + elif 18.5 < imc <= 24.9: |
| 127 | + tela_imc.label_mensagem.setText(' Classificação: Normal - Obsidade: Grau 0') |
| 128 | + elif 25.0 < imc <= 29.9: |
| 129 | + tela_imc.label_mensagem.setText(' Classificação: Sobrepeso - Obsidade: Grau I') |
| 130 | + elif 30.0 < imc <= 39.9: |
| 131 | + tela_imc.label_mensagem.setText(' Classificação: Obesidade - Obsidade: Grau II') |
| 132 | + elif imc >= 40.0: |
| 133 | + tela_imc.label_mensagem.setText(' Classificação: Obsidade Grave - Obsidade: Grau III') |
| 134 | +``` |
| 135 | + |
| 136 | + |
| 137 | +### Tela Gerar Senhas |
| 138 | + |
| 139 | + |
| 140 | + |
| 141 | +- Nesta tela o usuário pode gerar senhas aleatórias escolhendo alguns parâmetros: |
| 142 | + - Número de Caracteres; |
| 143 | + - Letras Maiúsculas; |
| 144 | + - Letras Minúsculas; |
| 145 | + - Números; |
| 146 | + - Simbolos. |
| 147 | + |
| 148 | +- Para escolher estes parâmetros o usário faz uso de uma CheckBox. |
| 149 | +- A lógica consiste em armazenar as escolhas do usuário em uma variável e ao chamar a função exibir_senha() os |
| 150 | +valores armazenados na variável serão escolhidos de maneira aleatória (com o uso da biblioteca random) e exibidos |
| 151 | +ao usuário. |
| 152 | + |
| 153 | +``` |
| 154 | +geral = '' |
| 155 | + |
| 156 | + if tela_senha.checkBox_letrasMaius.isChecked(): |
| 157 | + geral += string.ascii_uppercase |
| 158 | + if tela_senha.checkBox_letrasMinus.isChecked(): |
| 159 | + geral += string.ascii_lowercase |
| 160 | + if tela_senha.checkBox_num.isChecked(): |
| 161 | + geral += string.digits |
| 162 | + if tela_senha.checkBox_simbolos.isChecked(): |
| 163 | + geral += '!@#$%&*._-' |
| 164 | + |
| 165 | +``` |
| 166 | + |
| 167 | +``` |
| 168 | + senha = random.choices(geral, k=quantidade_caracteres) |
| 169 | +``` |
| 170 | + |
| 171 | + |
| 172 | +### Tela Lista de Tarefas (To-Do List) |
| 173 | + |
| 174 | + |
| 175 | + |
| 176 | +- Nesta tela foram implementados: |
| 177 | + - Campo de inserção: Onde o usuário poderá escrever um texto. |
| 178 | + - Botão adicionar: O texto inserido será exibido em uma caixa. |
| 179 | + - Botão excluir: O texto selecionado é exluído da caixa. |
| 180 | + - Botão marcar: O texto selecionado é riscado. |
| 181 | + - Botão desmarcar: O risco marcado no texto é retirado. |
| 182 | + - Botão limpar: Todos os textos exibidos na caixa são excluídos. |
| 183 | + |
| 184 | + |
| 185 | +- A lógica aplicada consiste em cada botão chamar uma função e, a função chamada fará um get no texto inserido |
| 186 | +ou selecionado e sobre ele aplicar uma função do |
| 187 | +[PyQt5](https://doc.qt.io/qtforpython/PySide6/QtWidgets/QListWidget.html) específica. |
| 188 | +Exemplo: A função marcar() captura o texto selecionado pelo usuário e configura a fonte com setStrikeOut (fonte riscada). |
| 189 | + |
| 190 | +``` |
| 191 | +item = tela_lista.listWidget.takeItem(tela_lista.listWidget.currentRow()) |
| 192 | + f = item.font() |
| 193 | + f.setStrikeOut(True) |
| 194 | + item.setFont(f) |
| 195 | + texto = item |
| 196 | + tela_lista.listWidget.insertItem(tela_lista.listWidget.currentRow(), texto) |
| 197 | +``` |
| 198 | + |
| 199 | +- Na tela também foram adicionados um calendário e um campo para escrita que, apesar de funcionais, foram |
| 200 | +adiconados como elementos visuais. |
| 201 | + |
| 202 | + |
| 203 | +### Tela de Login |
| 204 | + |
| 205 | + |
| 206 | + |
| 207 | +- Sabendo que para este tipo de aplicação seria necessário a conexão com um Banco de Dados e o uso de |
| 208 | +criptografia para proteção de credenciais, para fins de treinamento e aprendizado, neste projeto os usuários serão |
| 209 | +cadastrados em um dicionário([dict](https://docs.python.org/3/library/stdtypes.html?highlight=dict#dict)) |
| 210 | +na própria aplicação: |
| 211 | + |
| 212 | +``` |
| 213 | +usuarios = {'Maria': '123456', 'João': 'abcdef', 'Rose': '1ab2c3'} |
| 214 | +``` |
| 215 | + |
| 216 | +- A página traz um campo para inserção de usuário e outro para senha. Também dois botões (funções) login e cadastrar. |
| 217 | + - Ao chamar a função cadastrar() o texto inserido pelo usuário no campo usuário é comparado ao dicionário, se não |
| 218 | + constar o valor naquele, é então inserido o novo usuário. |
| 219 | + - Ao chamar a função login() o texto inserido pelo usuário nos campos usuário e senha são comparados ao dicionário, |
| 220 | + se constar o valor naquele, é autorizado o acesso. |
| 221 | + |
| 222 | +``` |
| 223 | + if usuario in usuarios: |
| 224 | + QMessageBox.about(tela_login, 'Alerta', 'Usuário já Cadastrado.') |
| 225 | + else: |
| 226 | + usuarios.update({usuario: senha}) |
| 227 | +``` |
| 228 | + |
| 229 | +- Para indicar autorização de acesso ao sistema é mostrado uma figura de um cadeado fechado ou aberto conforme o caso. |
| 230 | + |
| 231 | +``` |
| 232 | + if not usuario_login in usuarios: |
| 233 | + QMessageBox.about(tela_login, 'Alerta', 'Usuário Inválido.') |
| 234 | + else: |
| 235 | + tela_login.widget_imagem_cadeado.setStyleSheet('image: url(../imagens/cadeado_aberto.jpg)') |
| 236 | +``` |
| 237 | + |
| 238 | +### Tela Notícias |
| 239 | + |
| 240 | + |
| 241 | + |
| 242 | +- Nesta tela são exibidas notícias, previsão do tempo e cotação de moedas em tempo real. Para isso foram usados: |
| 243 | + |
| 244 | + - Para notícias foi aplicada a técnica de [WebScraping](https://pt.wikipedia.org/wiki/Raspagem_de_dados). |
| 245 | + Neste Projeto foram utlizadas as bibliotecas [Seleniun](https://www.selenium.dev/documentation/) e |
| 246 | + [BeautifulSoup](https://www.crummy.com/software/BeautifulSoup/bs4/doc.ptbr/). |
| 247 | + - Para a previsão do tempo foi utilizada uma [API](https://aws.amazon.com/pt/what-is/api/). A API utilizada |
| 248 | + foi [open-meteo.com](https://open-meteo.com/). Esta API suporta varios parâmetros de pesquisa. Para esta aplicação |
| 249 | + optei em filtrar por capitais dos estados do Brasil. Assim, em um dicionário(dict) armazenei os requests para cada |
| 250 | + capital, esse dicionário (/arquivos/previsoes_capitais_brasil.txt) foi armazenado em um arquivo .txt. |
| 251 | + Ao usuário foi limitado por um |
| 252 | + [comboBox](https://doc.qt.io/qtforpython/PySide6/QtWidgets/QComboBox.html#qcombobox) a escolha por capital. |
| 253 | + Ao selecionar a capital é feita uma consulta ao dicionário onde retorna a linha específica da capital selecionada |
| 254 | + e esta linha é usada para fazer a request à API. |
| 255 | + - Para cotação de moedas foi utlizado a API [awesome](https://docs.awesomeapi.com.br/api-de-moedas). |
| 256 | + Neste caso a request é feita diretamente ao chamar a função buscar_cotação() e para a apresentação |
| 257 | + ao usuário foram feitas formatações básicas. |
| 258 | + |
| 259 | +- No rodapé da tela é exibido de maneira aleatória um provérbio popular. Para isso armazenei cerca de |
| 260 | +430 provérbios em um arquivo .txt (/arquivos/proverbios.txt). A cada vez que é chamada a função |
| 261 | +chamar_atualizar() um provérbio é selecionado no arquivo, com o uso da biblioteca random, e exibido ao |
| 262 | +usuário. |
| 263 | + |
| 264 | + |
| 265 | +### Conceitos aplicados no Projeto |
| 266 | + |
| 267 | +- [Tipos de Dados](https://docs.python.org/pt-br/3/library/datatypes.html) |
| 268 | +- [Listas](https://docs.python.org/pt-br/3/library/stdtypes.html?highlight=list#list) |
| 269 | +- [Dicionários](https://docs.python.org/pt-br/3/library/stdtypes.html?highlight=dict#dict) |
| 270 | +- [Condicionais](https://docs.python.org/pt-br/3/tutorial/controlflow.html?highlight=if%20else) |
| 271 | +- [Laços de Repetição](https://www.w3schools.com/python/python_for_loops.asp) |
| 272 | +- [Try Exception](https://docs.python.org/3/tutorial/errors.html?highlight=try%20exception) |
| 273 | +- [Funções](https://www.w3schools.com/python/python_functions.asp) |
| 274 | +- [Classes](https://www.w3schools.com/python/python_classes.asp) |
| 275 | + |
| 276 | +### Bibliotecas utilizadas no Projeto |
| 277 | + |
| 278 | +- [PyQt5](https://pypi.org/project/PyQt5/#description) |
| 279 | +- [Random](https://docs.python.org/3/library/random.html) |
| 280 | +- [Selenium](https://www.selenium.dev/documentation) |
| 281 | +- [BeautifulSoup](https://www.crummy.com/software/BeautifulSoup/bs4/doc.ptbr/) |
| 282 | +- [Time](https://docs.python.org/3/library/time.html?highlight=time#module-time) |
| 283 | +- [Json](https://docs.python.org/3/library/json.html?highlight=json#module-json) |
| 284 | +- [Datetime](https://docs.python.org/3/library/datetime.html) |
| 285 | +- [Requests](https://pypi.org/project/requests/) |
| 286 | + |
| 287 | +### Ferramentas |
| 288 | + |
| 289 | +- [PyCharm](https://www.jetbrains.com/pt-br/pycharm/) |
| 290 | +- [QtDesigner](https://www.qt.io/free-trial) |
0 commit comments