使用python做一个年会抽奖软件(一)

先来个几张最终的图

2020Python年会抽奖 python年会滚动抽奖软件_2020Python年会抽奖


2020Python年会抽奖 python年会滚动抽奖软件_控件_02


2020Python年会抽奖 python年会滚动抽奖软件_2020Python年会抽奖_03


花了2个晚上,一个下午。

最终这个功能里面,包含了滚动抽奖,显示当前场次的抽奖情况,可以显示所有抽奖,可以选择奖项,剔除了中奖的人 重新抽奖,VIP也可以重新抽奖已经中奖的人等等

当然后面因为 软件我邮件发到了自己工作邮箱,在公司一个早上又加了音乐控制,同时一些其他的bug等,不过家里的这个还是可以用的

不过,我还是先说说一开始 并不是用QT实现的,使用的tkinter, 先试了下。发现比较难用,才改用QT的。虽然都是边学边做

先说说第一个失败的例子

一开始我是在ubuntu上开发的,所以tkinter其实也开发了差不多的demo,但是放到windows上发现各种问题,就放弃了,再加上我个人感觉不好用。

tkinter做的图展示:

2020Python年会抽奖 python年会滚动抽奖软件_Image_04


在tkinter里面 我用到了 菜单,按键控件,lable控件,text控件等

ubuntu里面多线程+tkinter没有啥问题,但是windows上就是各种问题。再加上不好用,,先看看代码:

关键的控件介绍:
其实很多控件的属性应该都是差不多的(个人感觉)

Label

text  要现实的文本
image 想要贴的图片
bg 背景颜色
compound 文本和图片如何显示 (center 居中)
比如:

Tkinter.Label(self.app, text=self.str_text[-1], compound='center', image=self.now_show_photo[-1])

menu

add_command: 新增一个选项
lable:标签
command: 链接的动作(函数)

self.meubar = Tkinter.Menu(self.app)
self.prize_bar = Tkinter.Menu(self.meubar, tearoff = 0)
self.prize_bar.add_command(label="一等奖", command = self.prize_menu_chose_one)
self.prize_bar.add_command(label="二等奖", command = self.prize_menu_chose_two)
self.prize_bar.add_command(label="三等奖", command = self.prize_menu_chose_three)
self.meubar.add_cascade(label='奖项设置', menu=self.prize_bar)

Button

text: 按键显示的文字
command:链接的动作
bg:背景色
其实button也支持图片, image

Tkinter.Button(self.app, text="开始", command=self.newtask, bg='gold')

Text

width: 宽
height: 高
bg: 背景颜色

Tkinter.Text(self.app, width=5, height=1, bg = "red")

基本的一些操作

打包控件:pack()
控制位置放置: place
删除控制:destroy() place_forget()

更新UI: update

图片的处理

这里图片处理用到了PIL库:
ImageTk、Image

photo_resize(self, photo_file, para):
im = Image.open(photo_file)
print photo_file, " : ", im.size
width =  (float)(im.size[0]) * para
height=  (float)(im.size[1]) * para
im = im.resize(((int)(width), (int)(height)),Image.ANTIALIAS)
return ImageTk.PhotoImage(im), im.size

好嘞, 我的一个下午的失败作先放到这儿吧,明天在说说 QT实现的。

下面是tkinter的一个简单demo代码:

#!/usr/bin/python
# -*- coding: UTF-8 -*-

import Tkinter
import time
import threading
from PIL import Image,ImageTk
import random
import copy
import ttk
import tkMessageBox as msg


class prize:

    hit_prize_number = 3
    hit_prize_persion = []  


    one_prize_all_number = 1
    one_prize_now_number = 0

    two_prize_all_number = 2
    two_prize_now_number = 0

    three_prize_all_number = 3
    three_prize_now_number = 0

    Vip_prize_all_number = 100
    Vip_prize_now_number = 0

    menu = ["一等奖", "二等奖", "三等奖"]



class person:

    photo = [['t1','test_photo\unkown.png'],
               ['t2','test_photo\unkown.png'],
               ['t3','test_photo\unkown.png'],
               ['t4','test_photo\\robot.png']]

    photo_f = []

    unkown_photo = ['???','test_photo\unkown.png']

    prize_menu = prize.menu
    

    def __init__(self):
        self.photo_f = copy.deepcopy(self.photo)

    def reset(self):
        self.photo_f = copy.deepcopy(self.photo)


class APP_UI:

    backim_size = None

    start_place = [0.8, 0.8]
    reset_place = [0.82, 0.95]
    all_show_place = [0.7, 0.2]
    prize_menu_place = [0.5, 0.05]
    #prize_show_place 
    
    show_start = [0.05, 0.2]
    show_zone = 0.95
    persion_size = [182, 176]

    isloop = False
    newloop = False

    meubar = None

    hit_show = []


    def __init__(self):
        self.isloop = False
        self.newloop = False
        self.person = person()
        self.app = Tkinter.Tk()
        self.app.title('新年抽奖')
        #back_photo = Tkinter.PhotoImage(file='bakimage.png')
        self.back_photo,self.backim_size = self.photo_resize('bakimage.png', 1)
        self.back_lable = Tkinter.Label(self.app, image=self.back_photo, width=self.backim_size[0], height=self.backim_size[1]).pack()
        #size = "%dx%d" % (self.backim_size[0],self.backim_size[1])
        #self.app.geometry(size) 
        #self.app.resizable(0,0)
        self.init_windows()
        self.app.config(menu=self.meubar)
        self.app.mainloop()




    def init_windows(self):
        self.init_button()
        self.init_prize_menu()
        self.init_text()
        self.init_show_photo()

    def init_hit_list(self, number):
        self.prize_hit_list = []
        for i in range(number):
            self.prize_hit_list.append(self.person.unkown_photo)


    def init_text(self):
        #self.prize_text = Tkinter.StringVar()
        self.prize_text = Tkinter.Text(self.app, width=5, height=1, bg = "red")
        p_size = self.getplace(self.prize_menu_place)
        self.prize_text.place(x=p_size[0], y=p_size[1])
        self.prize_text.insert(Tkinter.INSERT, '三等奖')
        self.prize_num = 3
        self.init_hit_list(self.prize_num)

    def init_show_photo(self):
        hit_list = self.prize_hit_list
        place_all = self.clac_show_place(hit_list)
        self.clear_hit_show()
        self.hit_show = []
        self.now_show_photo = []
        self.str_text = []
        if len(place_all) < len(hit_list): return 
        print "now: place_all ", place_all
        for i in range(len(hit_list)):
            now_photo,_ = self.photo_size_set(hit_list[i][1],self.persion_size)
            self.now_show_photo.append(now_photo)
            self.str_text.append(hit_list[i][0])
            self.hit_show.append(Tkinter.Label(self.app, text=self.str_text[-1], compound='center', image=self.now_show_photo[-1]))
            p_size = self.getplace(place_all[i])
            self.hit_show[-1].place(x=p_size[0], y=p_size[1])

        
    def clac_show_place(self, hit_list):
        place_all = []
        number = min(len(hit_list), self.prize_num)
        #print number
        zone_sigle = self.show_zone / number
        new_start = self.show_start[0]
        new_place = 0.0
        photo_new = (self.persion_size[0] * 1.0) / (self.backim_size[0] * 2 * 1.0)
        for i in range(number):
            new_place = [(new_start + zone_sigle / 2 - photo_new), self.show_start[1]]
            place_all.append(new_place)
            new_start += zone_sigle
        return place_all

       

    def init_prize_menu_by_box(self):
        self.comvalue=Tkinter.StringVar()
        self.comboxlist=ttk.Combobox(self.app,textvariable=self.comvalue)
        self.comboxlist["values"]=self.person.prize_menu
        self.comboxlist.current(2)
        self.comboxlist.bind("<<ComboboxSelected>>",self.prize_chose)
        p_size = self.getplace(self.prize_menu_place)
        self.comboxlist.place(x=p_size[0], y=p_size[1])

    def init_prize_menu(self):
        self.meubar = Tkinter.Menu(self.app)
        self.prize_bar = Tkinter.Menu(self.meubar, tearoff = 0)
        self.prize_bar.add_command(label="一等奖", command = self.prize_menu_chose_one)
        self.prize_bar.add_command(label="二等奖", command = self.prize_menu_chose_two)
        self.prize_bar.add_command(label="三等奖", command = self.prize_menu_chose_three)
        self.meubar.add_cascade(label='奖项设置', menu=self.prize_bar)

    def prize_menu_chose_one(self):
        print "enter config...  prize_menu_chose_one"
        self.prize_menu_chose(1)

    def prize_menu_chose_two(self):
        print "enter config...  prize_menu_chose_two"
        self.prize_menu_chose(2)

    def prize_menu_chose_three(self):
        print "enter config...  prize_menu_chose_two"
        self.prize_menu_chose(3)
        
    def prize_menu_chose(self,number):
        if number<1 : print "error"
        self.prize_text.delete('1.0',Tkinter.END)
        self.prize_text.insert(Tkinter.INSERT, self.person.prize_menu[number-1])
        self.clear_hit_show()
        self.prize_num = number
        self.init_hit_list(self.prize_num)
        self.add_hit_prize(self.prize_hit_list)
        self.app.update()

    def prize_chose(self, *args):
        print(self.comboxlist.get()) 

    def init_button(self):
        #start_photo = Tkinter.PhotoImage(file="start.gif")
        self.start_btn = Tkinter.Button(self.app, text="开始", command=self.newtask, bg='gold')
        p_size = self.getplace(self.start_place)
        self.start_btn.place(x=p_size[0], y=p_size[1], width=70, height=50)

        self.restart_btn = Tkinter.Button(self.app, text="重置", command=self.init_windows, font=("Arial", 5), bg='SeaGreen')
        p_size = self.getplace(self.reset_place)
        self.restart_btn.place(x=p_size[0], y=p_size[1])

    def test(self):
        print "just test---"
        if self.isloop == True: return
        #number = 0
        #all_number = len(self.person.photo_f)
        if len(self.person.photo_f)==0 :
            self.clear_hit_show()
            msg.showwarning('showwarning', '已经抽奖完了所有人')
            return
        while True:
            if self.newloop == True:
                print "start chose hit..."
                self.newloop = False
                self.clear_hit_show()
                self.chose_prize_hit(self.person.photo_f)
                print self.prize_hit_list
                self.add_hit_prize(self.prize_hit_list)
                time.sleep(0.1)
                self.app.update()
                time.sleep(0.1)
                self.clear_hit_show()
                print "end chose hit..."
                return
            #if all_number == (number+1):
            #    random.shuffle(self.person.photo_f)
            #    number = 0
            #number+=1
            self.srcoll_show(self.person.photo_f)
            

    def test2(self):
        #self.srcoll_show(self.person.photo_f)
        #self.now_show_photo = []
        #self.str_text = []
        print 'here 1'
        hit_list = self.person.photo_f
        random.shuffle(hit_list)
        place_all = self.clac_show_place(hit_list)
        for i in range(self.prize_num):
            self.str_text[i] = hit_list[i][0]
            temp,_ = self.photo_size_set(hit_list[i][1],self.persion_size)
            self.now_show_photo[i] = temp
            print 'here 2'
            self.app.update()
            time.sleep(2)
            print 'here 3'
            time.sleep(2)
            print 'here 4'


    def chose_prize_hit(self, person_list):
        random.shuffle(person_list)
        for i in range(self.prize_num):
            if len(person_list) == 0: break
            new = person_list[0]
            self.prize_hit_list.append(new)
            person_list.remove(new)
        
    def add_hit_prize(self, hit_list):
        place_all = self.clac_show_place(hit_list)
        self.clear_hit_show()
        self.hit_show = []
        self.now_show_photo = []
        if len(place_all) < len(hit_list): return 
        print "now: place_all ", place_all
        for i in range(len(hit_list)):
            now_photo,_ = self.photo_size_set(hit_list[i][1],self.persion_size)
            self.now_show_photo.append(now_photo)
            self.hit_show.append(Tkinter.Label(self.app, text=hit_list[i][0], compound='center', image=self.now_show_photo[-1]))
            p_size = self.getplace(place_all[i])
            self.hit_show[-1].place(x=p_size[0], y=p_size[1])

    def clear_hit_show(self):
        print self.hit_show
        for show in self.hit_show:
            #show.place_forget()
            show.destroy()
            time.sleep(0.1)
        self.now_show_photo = []
        self.prize_hit_list = []
        self.hit_show = []


    def srcoll_show(self, person_list):

        random.shuffle(person_list)
        time.sleep(0.05)
        show_list = []
        for i in range(self.prize_num):
            if len(person_list) <= i : break
            show_list.append(person_list[i])
        self.clear_hit_show()
        self.add_hit_prize(show_list)
        time.sleep(0.05)
        self.app.update()
        time.sleep(0.05)


    def photo_resize(self, photo_file, para):
        im = Image.open(photo_file)
        print photo_file, " : ", im.size
        width =  (float)(im.size[0]) * para
        height=  (float)(im.size[1]) * para
        im = im.resize(((int)(width), (int)(height)),Image.ANTIALIAS)
        return ImageTk.PhotoImage(im), im.size

    def photo_size_set(self, photo_file, size):
        im = Image.open(photo_file)
        print photo_file, " : ", im.size
        im = im.resize(((int)(size[0]), (int)(size[1])),Image.ANTIALIAS)
        return ImageTk.PhotoImage(im), im.size

    def getplace(self, place):
        p_x =  (float)(self.backim_size[0]) * place[0]
        p_y =  (float)(self.backim_size[1]) * place[1]
        return [p_x, p_y]

    def newtask(self):
        if self.isloop == False:
          #self.clear_hit_show()
          # 建立线程
          print "new..."
          t = threading.Thread(target = self.test)
          # 开启线程运行
          t.start()
          # 设置循环开始标志
          time.sleep(0.1)
          self.isloop = True
        elif self.isloop == True:
          print "stop..."
          self.isloop = False
          self.newloop = True

    def start_new_thread(self):
        t = threading.Thread(target = self.thread_show)
        # 开启线程运行
        t.start()
        # 设置循环开始标志
        time.sleep(0.1)
        self.isloop = True

    #def 

def main():
    app_ui = APP_UI()


if __name__ == '__main__':
    main()

参考了很多同学的,不过一些忘记了: https://baijiahao.baidu.com/s?id=1577495887121721644&wfr=spider&for=pc