Pessoal,
AGRADECO DE CORACAO a todos os que tentaram me ajudar.
Especialmente ao BORBA, WILLIE e JOAO BUENO.
Realmente Joao Bueno, estou trabalhando com TKinter.
Adorei o tempo gasto comigo (texto bem explicado e com outras caracteristicas do tkinter q nao sabia - simplicidade dos eventos)
Willie nao entendi o objetivo do sinal de "+" no fim da instrucao BIND. Nao consegui ver diferenca nenhuma.
O que este sinal faz?
Borba, vc tem razao... se estivesse em um terminal sua solucao seria de cara a melhor!!
Estou trabalhando nesta tela desde as 08:30h de hoje.
Somente agora consegui descobrir o que estava acontecendo.
Nao exatamente, mas acho q com meu nivel de conhecimento em Python (nivel basico) estah satisfatorio.
Vou postar duas solucoes...
A primeira eh colocando todos os controles da tela em uma unica classe e trabalhando os metodos dentro desta classe.
Nunca usando metodos globais, somente dentre desta classe.
Fiz alguns comentarios no codigo...
#!/usr/bin/python
# -*- coding: iso-8859-1 -*-
from tkinter import Toplevel, Label, Entry, Button, Frame, Text, PanedWindow, Scrollbar, StringVar
from tkinter.constants import END, SUNKEN, HORIZONTAL, VERTICAL, N, S, E, W, CENTER
from tkinter import Tk, mainloop
from datetime import date
#import SQL
#from Util import CentralizarJanela
class Filtros():
def __init__(self, parent=None, strSQL=None):
# TOPLEVEL
#self.frmFilha = Toplevel()
# Para testes somente nesta tela, ative a linha abaixo
self.frmFilha = parent
# Criar os controles de Data Inicial e Final
self.SFLT()
# PANED WINDOW -->> Lugar do FRAME B
self.pwA = PanedWindow(self.frmFilha, orient=HORIZONTAL)
self.frmC = Frame(self.frmFilha, border=1, relief=SUNKEN)
self.frmC.grid(row=2, column=0, columnspan=2, sticky=E+W)
# MEMO
self.mmoSQL = Text(self.pwA, height=10)
self.mmoSQL.insert(END, strSQL)
self.sbarV = Scrollbar(self.frmFilha, orient=VERTICAL, command=self.mmoSQL.yview)
self.mmoSQL.config(yscrollcommand=self.sbarV.set)
self.sbarV.grid(row=1, column=1, sticky=N+S)
self.pwA.add(self.mmoSQL)
# BOTOES
self.btnOK = Button(self.frmC, text='OK', width=20)
self.btnOK.grid(row=0, column=0, sticky=E+W, padx=5, pady=5)
self.btnOK.bind('<1>', self.PassarParametros)
self.btnCancelar = Button(self.frmC, text='Cancelar', width=20)
self.btnCancelar.grid(row=0, column=1, padx=5, pady=5)
self.btnCancelar.bind('<1>', self.Cancelar)
self.pwA.grid(row=1, column=0, sticky=N+S+E+W)
self.frmFilha.resizable(False, False)
# Centralizar Janela
self.frmFilha.update()
#CentralizarJanela(self.frmFilha, self.frmFilha.winfo_width(), self.frmFilha.winfo_height())
def PassarParametros(self, event=None):
print('Data Inicial: {} - Data Final: {}'.format(self.edtDataI.get(), self.edtDataF.get()))
Param = []
Param.append(self.edtDataI.get())
Param.append(self.edtDataF.get())
# Apos o DESTROY, eh executado as linhas abaixo
self.frmFilha.destroy()
print(Param)
# Apos o RETURN, nao eh executado qualqer comando
return Param
def Cancelar(self, event=None):
print('Nao retornar qualquer parametro')
self.frmFilha.destroy()
# SETOR, FAZENDA, LOTE e TALHAO
def SFLT(self):
self.frmA = Frame(self.frmFilha, border=2, height=200, relief=SUNKEN)
self.frmA.grid(row=0, column=0, sticky=N+S+E+W, columnspan=2)
# Setor
self.strSetor = StringVar();
self.lblSetor = Label(self.frmA, text='Setor:', width=20, anchor=W)
self.edtSetor = Entry(self.frmA, justify=CENTER, textvariable=self.strSetor)
self.lblSetor.grid(row=0, column=0, padx=3)
self.edtSetor.grid(row=1, column=0, padx=5, sticky=E+W) # Usar sticky para nao definir o tamanho para o edit
# O PULO-DO-GATO estah em:
# 1) Declarar uma variavel EVENT no lambda, no entanto nao precisa passar para o metodo
# Desta forma o Python nao reclama, nesta linha, que estah faltando parametro para o metodo
# 2) Usar o evento <KeyRelease>, assim, tudo que vc digitar serah convertido, pois o digito aparece ao PRESSIONAR a tecla,
# evento de "baixar" a tecla, quando soltar a tecla, o texto estarah disponivel no widget para conversao.
# 3) No metodo PASSARPARAMAIUSCULAS, declare EVENT, este serah passado junto com o SELF (linha abaixo)
self.edtSetor.bind('<KeyRelease>', lambda event:self.PassarParaMaiusculas(self, self.strSetor, self.edtSetor.get()))
self.strSetor.set('Zero')
# Fazenda
self.lblFazenda = Label(self.frmA, text='Fazenda:', width=20, anchor=W)
self.edtFazenda = Entry(self.frmA, justify=CENTER)
self.lblFazenda.grid(row=0, column=1, padx=3)
self.edtFazenda.grid(row=1, column=1, padx=5, sticky=E+W)
# Lote
self.lblLote = Label(self.frmA, text='Lote:', width=20, anchor=W)
self.edtLote = Entry(self.frmA, justify=CENTER)
self.lblLote.grid(row=0, column=2, padx=3)
self.edtLote.grid(row=1, column=2, padx=5, sticky=E+W)
# Talhao
self.lblTalhao = Label(self.frmA, text='Talhão:', width=20, anchor=W)
self.edtTalhao = Entry(self.frmA, justify=CENTER)
self.lblTalhao.grid(row=0, column=3, padx=3)
self.edtTalhao.grid(row=1, column=3, padx=5, sticky=E+W)
# Data Inicial
self.lblDataI = Label(self.frmA, text='Data inicial (aaaa-mm-dd):', width=20, anchor=W)
self.edtDataI = Entry(self.frmA, justify=CENTER)
self.edtDataI.insert(0, date.fromordinal(date.toordinal(date.today())-30))
self.lblDataI.grid(row=2, column=0, padx=3)
self.edtDataI.grid(row=3, column=0, padx=5, sticky=E+W)
# Data Inicial
self.lblDataF = Label(self.frmA, text='Data final (aaaa-mm-dd):', width=20, anchor=W)
self.edtDataF = Entry(self.frmA, justify=CENTER)
self.edtDataF.insert(0, date.today())
self.lblDataF.grid(row=2, column=1, padx=3)
self.edtDataF.grid(row=3, column=1, padx=5, sticky=E+W)
def PassarParaMaiusculas(self, event, varString, strTexto):
print('Entrei na funcao')
varString.set(strTexto.upper())
root = Tk()
Filtros(root, strSQL='SELECT...')
mainloop()
print('Encerrando aplicacao')
( mesmo codigo acima:
http://www.pastebin.com.br/601 )
A outra forma eh criar uma classe separada para a criacao de filtros opcionais...
Estes filtros serao colcados pela aplicacao principal.... aqui foi adapatada para funcionar sem a aplicacao principal!
#!/usr/bin/python
# -*- coding: iso-8859-1 -*-
from tkinter import Toplevel, Label, Entry, Button, Frame, Text, PanedWindow, Scrollbar, StringVar
from tkinter.constants import END, SUNKEN, HORIZONTAL, VERTICAL, N, S, E, W, CENTER
from tkinter import Tk, mainloop
from datetime import date
#import SQL
#from Util import CentralizarJanela
class Filtros():
def __init__(self, parent=None, strSQL=None):
# TOPLEVEL
#self.frmFilha = Toplevel()
# Para testes somente nesta tela, ative a linha abaixo
self.frmFilha = parent
# Criar os controles de Data Inicial e Final
FiltrosOpcionais.SFLT(self)
# PANED WINDOW -->> Lugar do FRAME B
self.pwA = PanedWindow(self.frmFilha, orient=HORIZONTAL)
self.frmC = Frame(self.frmFilha, border=1, relief=SUNKEN)
self.frmC.grid(row=2, column=0, columnspan=2, sticky=E+W)
# MEMO
self.mmoSQL = Text(self.pwA, height=10)
self.mmoSQL.insert(END, strSQL)
self.sbarV = Scrollbar(self.frmFilha, orient=VERTICAL, command=self.mmoSQL.yview)
self.mmoSQL.config(yscrollcommand=self.sbarV.set)
self.sbarV.grid(row=1, column=1, sticky=N+S)
self.pwA.add(self.mmoSQL)
# BOTOES
self.btnOK = Button(self.frmC, text='OK', width=20)
self.btnOK.grid(row=0, column=0, sticky=E+W, padx=5, pady=5)
self.btnOK.bind('<1>', self.PassarParametros)
self.btnCancelar = Button(self.frmC, text='Cancelar', width=20)
self.btnCancelar.grid(row=0, column=1, padx=5, pady=5)
self.btnCancelar.bind('<1>', self.Cancelar)
self.pwA.grid(row=1, column=0, sticky=N+S+E+W)
self.frmFilha.resizable(False, False)
# Centralizar Janela
self.frmFilha.update()
#CentralizarJanela(self.frmFilha, self.frmFilha.winfo_width(), self.frmFilha.winfo_height())
def PassarParametros(self, event=None):
print('Data Inicial: {} - Data Final: {}'.format(self.edtDataI.get(), self.edtDataF.get()))
Param = []
Param.append(self.edtDataI.get())
Param.append(self.edtDataF.get())
# Apos o DESTROY, eh executado as linhas abaixo
self.frmFilha.destroy()
print(Param)
# Apos o RETURN, nao eh executado qualqer comando
return Param
def Cancelar(self, event=None):
print('Nao retornar qualquer parametro')
self.frmFilha.destroy()
# SETOR, FAZENDA, LOTE e TALHAO
class FiltrosOpcionais():
def SFLT(self):
self.frmA = Frame(self.frmFilha, border=2, height=200, relief=SUNKEN)
self.frmA.grid(row=0, column=0, sticky=N+S+E+W, columnspan=2)
# Setor
self.strSetor = StringVar();
self.lblSetor = Label(self.frmA, text='Setor:', width=20, anchor=W)
self.edtSetor = Entry(self.frmA, justify=CENTER, textvariable=self.strSetor)
self.lblSetor.grid(row=0, column=0, padx=3)
self.edtSetor.grid(row=1, column=0, padx=5, sticky=E+W) # Usar sticky para nao definir o tamanho para o edit
# O PULO-DO-GATO estah em:
# 1) Declarar uma variavel EVENT no lambda (obrigatorio a criacao, mas a passagem para o metodo nao eh obrigatoria)
# Desta forma o Python nao reclama, nesta linha, que estah faltando parametro para o metodo
# 2) Usar o evento <KeyRelease>, assim, tudo que vc digitar serah convertido, pois o digito aparece ao PRESSIONAR a tecla,
# evento de "baixar" a tecla, quando soltar a tecla, o texto estarah disponivel no widget para conversao.
# 3) No metodo PASSARPARAMAIUSCULAS, nao precisa declarar EVENT (nao sei exatamente pq. Acho q o BIND envia uma tupla
# para o metodo (obrigatoriamente uma tupla) se ele nao conseguir formar esta tupla, dah erro de falta de parametro)
self.edtSetor.bind('<KeyRelease>', lambda event:FiltrosOpcionais.PassarParaMaiusculas(self, self.strSetor, self.edtSetor.get()))
self.strSetor.set('Zero')
# Fazenda
self.lblFazenda = Label(self.frmA, text='Fazenda:', width=20, anchor=W)
self.edtFazenda = Entry(self.frmA, justify=CENTER)
self.lblFazenda.grid(row=0, column=1, padx=3)
self.edtFazenda.grid(row=1, column=1, padx=5, sticky=E+W)
# Lote
self.lblLote = Label(self.frmA, text='Lote:', width=20, anchor=W)
self.edtLote = Entry(self.frmA, justify=CENTER)
self.lblLote.grid(row=0, column=2, padx=3)
self.edtLote.grid(row=1, column=2, padx=5, sticky=E+W)
# Talhao
self.lblTalhao = Label(self.frmA, text='Talhão:', width=20, anchor=W)
self.edtTalhao = Entry(self.frmA, justify=CENTER)
self.lblTalhao.grid(row=0, column=3, padx=3)
self.edtTalhao.grid(row=1, column=3, padx=5, sticky=E+W)
# Data Inicial
self.lblDataI = Label(self.frmA, text='Data inicial (aaaa-mm-dd):', width=20, anchor=W)
self.edtDataI = Entry(self.frmA, justify=CENTER)
self.edtDataI.insert(0, date.fromordinal(date.toordinal(date.today())-30))
self.lblDataI.grid(row=2, column=0, padx=3)
self.edtDataI.grid(row=3, column=0, padx=5, sticky=E+W)
# Data Inicial
self.lblDataF = Label(self.frmA, text='Data final (aaaa-mm-dd):', width=20, anchor=W)
self.edtDataF = Entry(self.frmA, justify=CENTER)
self.edtDataF.insert(0, date.today())
self.lblDataF.grid(row=2, column=1, padx=3)
self.edtDataF.grid(row=3, column=1, padx=5, sticky=E+W)
def PassarParaMaiusculas(self, varString, strTexto):
print('Entrei na funcao')
varString.set(strTexto.upper())
#StringVar(varTexto).set(str(strTexto).upper())
root = Tk()
Filtros(root, strSQL='SELECT...')
mainloop()
print('Encerrando aplicacao')
http://www.pastebin.com.br/602Divirtam-se, pessoal, com este pequeno desafio!!
E para aqueles que estao procurando uma solucao parecida com OnChange do Delphi.
Obrigado a todos
MuriloCunha
Em segunda-feira, 7 de julho de 2014 09h01min25s UTC-3, MuriloCunha escreveu: