Receita: Sorteador de Elementos
Na empresa onde trabalho temos o hábito de promover sorteios para a distribuição de brindes que ganhamos em feiras, congressos e coisas do tipo. Recentemente ganhei um convite do Gmail e resolvi sortear entre o pessoal aqui da empresa. Para isso fiz o programinha abaixo... Sintam-se à vontade para melhorar ele
Código
1 #!/usr/bin/env python
2 # -*- coding: ISO-8859-1 -*-
3
4
5 from inscritos import inscritos
6
7 from Tkinter import *
8 from Dialog import Dialog
9 import time
10 import random
11
12 class MainFrame(Frame):
13 def __init__(self, parent=None):
14 Frame.__init__(self, parent)
15 self.master.title("Sorteia")
16 self.text = StringVar()
17 self.nome = StringVar()
18 self.createWidgets()
19 self.pack(padx=10, pady=10)
20
21
22 def createWidgets(self):
23 panel1 = Frame(self)
24 nomeL = Label(panel1, text="Nome:")
25 nomeL.pack(side=LEFT)
26 self.nomeE = Entry(panel1, \
27 textvariable=self.nome, width=50)
28 self.nomeE.pack(side=LEFT)
29 self.nomeE.bind("<Return>", self.addEnter)
30 addB = Button(panel1, text=" + ", \
31 command=self.adicionar)
32 addB.pack(side=LEFT)
33 subB = Button(panel1, text=" - ", \
34 command=self.remover)
35 subB.pack(side=LEFT)
36 panel1.pack(side=TOP)
37
38 panel2 = Frame(self)
39
40 scrollbar = Scrollbar(panel2, orient=VERTICAL)
41 self.listbox = Listbox(panel2, \
42 yscrollcommand=scrollbar.set, \
43 font=("Tahoma", 10, "bold"))
44 self.listbox.pack(side=LEFT, fill=BOTH, expand=1)
45 scrollbar.config(command=self.listbox.yview)
46 scrollbar.pack(side=RIGHT, fill=Y)
47
48 panel2.pack(side=TOP, fill=BOTH, \
49 expand=Y, pady=10)
50
51 panel3 = Frame(self)
52
53 sorteiaB = Button(panel3, text="Sorteia",\
54 font=("Tahoma", 10, "bold"), \
55 command=self.sorteia)
56
57 sorteiaB.pack(side=TOP, fill=BOTH, expand=Y)
58
59 nomeSorteadoT = Label(panel3, \
60 textvariable=self.text, \
61 font=("Tahoma", 20, "bold"))
62 nomeSorteadoT.pack(side=TOP, fill=BOTH, \
63 expand=Y, pady=20)
64
65 self.nomeSorteadoT = nomeSorteadoT
66
67 panel3.pack(side=TOP, fill=BOTH, expand=Y)
68 random.shuffle(inscritos)
69 for nome in inscritos:
70 self.listbox.insert(END, nome)
71
72
73 def sorteia(self):
74 listaSorteia = self._getLista()
75 random.shuffle(listaSorteia)
76 self.nomeSorteadoT['fg'] = 'black'
77 if not listaSorteia:
78 return
79
80 t = 0
81
82 while len(listaSorteia) > 1:
83 nome = random.choice(listaSorteia)
84 self.after(t, self.text.set, nome)
85 t += 1000 / len(listaSorteia)
86 listaSorteia.remove(nome)
87
88 sorteado = listaSorteia.pop()
89 self.after(t, self.fimSorteio, sorteado)
90
91 def fimSorteio(self, sorteado):
92 self.text.set(sorteado)
93 self.nomeSorteadoT['fg'] = 'red'
94 self.bell()
95
96 def _getLista(self):
97 listbox = self.listbox
98
99 lista = [listbox.get(i) for i in range(listbox.size())]
100 return lista
101
102 def adicionar(self):
103 nome = self.nome.get()
104 if not len(nome):
105 Dialog(self, title="Erro!", \
106 text="Nome inválido", \
107 bitmap='error', \
108 default=0, \
109 strings=('OK',))
110 return
111
112 if nome in self._getLista():
113 Dialog(self, title="Erro!", \
114 text="Já cadastrado", \
115 bitmap='error', \
116 default=0, \
117 strings=('OK',))
118 return
119
120 self.listbox.insert(END, nome)
121 self.limpaCampos()
122
123 def addEnter(self, ev):
124 self.adicionar()
125
126 def remover(self):
127 self.listbox.delete(ANCHOR)
128
129 def limpaCampos(self):
130 self.nome.set("")
131 self.nomeE.focus()
132
133
134
135 def main():
136 frm = MainFrame()
137 frm.mainloop()
138
139 if __name__ == '__main__':
140 main()
Arquivo: *inscritos.py*
inscritos = ["Charles Babbage", "Alan Turing", "Ada Lovelace"]
Uma das coisas que tentei fazer e não consegui é um 'efeito visual' que faça com que os nomes fiquem passando antes de parar no nome realmente sorteado. Eu fiz mudar mas a tela não atualizava. Alguém sabe como fazer isso? -- OsvaldoSantanaNeto
Bom... passatempo pra manhã de domingo. Ele embaralha a lista de nomes, expõe eles na Label por um tempo igual a 1s / comprimento da lista (assim dá um efeito de "desaceleração" quando o sorteio ocorre). A cada vez que faz isso, retira um dos nomes da lista, embaralha e começa tudo de novo. Quando restar só um nome (o sorteado) ele exibe o nome na Label, muda a cor pra vermelho e emite um sinal (só pra ter certeza). -- PedroWerneck
Página atualizada para representar as modificações feitas para o sorteio da II PyConBrasil. Retiramos o shuffle (que tornava a aplicação muito lenta) e utilizamos o choice para sortear cada um dos nomes da lista. -- EricoAndrei
Versão utilizada para os sorteios na PyConBrasil[3]. Foi feito o embaralhamento, com shuffle, da lista de nomes em dois momentos: Na alimentação do listbox e antes de qualquer sorteio. Foi demandado que o sorteador retire da listbox os nomes já sorteados, a fim de evitar que um mesmo nome seja sorteado duas vezes em uma mesma execução do programa. -- EricoAndrei
Volta para CookBook.