zoukankan      html  css  js  c++  java
  • python-tkinter学习实例

      在好友的邀请下,尝试用tkinter做一个卡牌的普通界面显示,正好练习下python的写法。
      花了两天学习,写了两天代码,做了个最基本的demo。显示如下:

    其中需要引入的第三方库主要有,PIL、PILLOW,其它的都是直接引入即可。

    1.1、这里贴下下载地址,以WINDOWS系统为例:


    PILwin32:http://files.cnblogs.com/files/pcat/PILwin32.zip

    PILwin64:http://files.cnblogs.com/files/pcat/PILwin64.zip

    1.2、windows安装Pillow

    pip install Pillow
    或者在http://www.lfd.uci.edu/~gohlke/pythonlibs/#pillow 下载wheel文件使用pip安装

    程序中用到的图片主要有:

    需要图片资源的小伙伴可以自行上git上下载:

    https://github.com/ishikota/PyPokerGUI

    pypokergui--server--static

    贴上程序的源码,仅供参考:

      1 # -*- coding: utf-8 -*-
      2 from Tkinter import *
      3 from PIL import Image,ImageTk
      4 
      5 import Image,math,random,time,sched
      6 import threading as thd
      7 class card2:
      8     #定义全局变量
      9     #总牌数
     10     num_list = ['3', '4', '5', '6', '7', '8', '9','T', 'J','Q','K', 'A','2']
     11     # 全局变量纪录玩家当前要打出的牌数字
     12     #当前牌面字符串
     13     str_num = '';
     14     #当前牌面字符串在num_list中的位置
     15     index_num = -1;
     16     # 中间桌面上牌的大小
     17     mid_num = -2;
     18     #判断是否会生成重复的牌
     19     check_list = [];
     20     #记录当前回合数
     21     round_num = 1;
     22     #当前玩家手中牌位置
     23     cur_position = 0;
     24     #定义玩家当前手中牌的集合
     25     player_card_list = [];
     26     player1_card_list = [];
     27     player2_card_list = [];
     28     player3_card_list = [];
     29     player4_card_list = [];
     30 
     31     #变量判断玩家身份,默认为玩家
     32     cur_identify = 1;
     33 
     34     def __init__(self):
     35         self.tk = Tk()
     36         #tk.geometry('1200x1600')
     37         self.tk.title('A Easy Card Game')
     38 
     39         self.img = Image.open('images/poker_pot.png')
     40         self.w_box = 120
     41         self.h_box = 120
     42         self.w, self.h = self.img.size
     43         # w,h = img2.size
     44         # 缩放图像让它保持比例,同时限制在一个矩形框范围内
     45         self.img_resized = self.resize(self.w, self.h, self.w_box, self.h_box, self.img)
     46         self.photo = ImageTk.PhotoImage(self.img_resized)
     47         # frm_TL = Frame(bg = 'WHITE',width = 300, height = 200)
     48         self.frm_T = Frame(bg='white', width=300, height=200)
     49         self.frm_L = Frame(bg='white', width=300, height=400)
     50         self.frm_M = Frame(bg='white', width=200, height=400)
     51         self.frm_R = Frame(bg='white', width=300, height=400)
     52         self.frm_B = Frame(bg='white', width=400, height=200)
     53         # frm_TL.grid(row=0,column=0)
     54         self.frm_T.grid(row=0, column=1)
     55         self.frm_L.grid(row=1, column=0)
     56         self.frm_M.grid(row=1, column=1)
     57         self.frm_R.grid(row=1, column=2)
     58         self.frm_B.grid(row=2, column=1)
     59         # Top
     60         Label(self.frm_T, text="Player3", font=('Arial', 16)).grid(column=1, sticky=N)
     61         Button(self.frm_T, text="重新发牌", command=self.replay, width=8, height=1,
     62                font=('Arial', 16)).grid(row=0, column=3)
     63         self.frm_T_label_L = Label(self.frm_T, image=self.photo)
     64         self.frm_T_label_L.image = self.photo
     65         self.frm_T_label_L.grid(row=1, column=0, sticky=E)
     66         # frm_T_label_L.grid(row=1,column=1,columnspan=2,rowspan=2,sticky=W+E+N+S,padx=5,pady=5)
     67         self.frm_T_label_M = Label(self.frm_T, image=self.photo)
     68         self.frm_T_label_M.image = self.photo
     69         self.frm_T_label_M.grid(row=1, column=1,padx=10, sticky=E)
     70         self.frm_T_label_R = Label(self.frm_T, image=self.photo)
     71         self.frm_T_label_R.image = self.photo
     72         self.frm_T_label_R.grid(row=1, column=2, sticky=E)
     73 
     74         # Left
     75         Label(self.frm_L, text="Player4", font=('Arial', 16)).grid(row=1, column=0, sticky=N)
     76         self.frm_L_label_T = Label(self.frm_L, image=self.photo)
     77         self.frm_L_label_T.image = self.photo
     78         self.frm_L_label_T.grid(row=0, column=1, sticky=E)
     79         self.frm_L_label_T = Label(self.frm_L, image=self.photo)
     80         self.frm_L_label_T.image = self.photo
     81         self.frm_L_label_T.grid(row=1, column=1, sticky=E)
     82         self.frm_L_label_T = Label(self.frm_L, image=self.photo)
     83         self.frm_L_label_T.image = self.photo
     84         self.frm_L_label_T.grid(row=2, column=1, sticky=E)
     85 
     86         # Middle
     87         self.frm_M_label_T = Label(self.frm_M, image=self.photo)
     88         self.frm_M_label_T.image = self.photo
     89         self.frm_M_label_T.grid(row=1, column=0, sticky=E)
     90         self.frm_M_text = Text(self.frm_M, width=30, height=6, bg='Green', font=('Verdana', 15))
     91 
     92         #self.frm_M_text.insert('1.0', 'this is '+str(self.round_num)+' round
    ')
     93         #self.frm_M_text.insert(END, 'last round')
     94         self.frm_M_text.grid(row=2, column=0, columnspan=2)
     95 
     96         # Right  frm_R
     97         self.frm_R_label_T = Label(self.frm_R, image=self.photo)
     98         self.frm_R_label_T.image = self.photo
     99         self.frm_R_label_T.grid(row=0, column=0, sticky=E)
    100         self.frm_R_label_T = Label(self.frm_R, image=self.photo)
    101         self.frm_R_label_T.image = self.photo
    102         self.frm_R_label_T.grid(row=1, column=0, sticky=E)
    103         self.frm_R_label_T = Label(self.frm_R, image=self.photo)
    104         self.frm_R_label_T.image = self.photo
    105         self.frm_R_label_T.grid(row=2, column=0, sticky=E)
    106         Label(self.frm_R, text="Player2", font=('Arial', 16)).grid(row=1, column=1, sticky=N)
    107 
    108         # 初始化玩家手中牌
    109         self.load_sys()
    110 
    111         self.main_start()
    112 
    113         self.frm_B_label_T_4 = Label(self.frm_B, image=self.photo)
    114         self.frm_B_label_T_4.image = self.photo
    115         self.frm_B_label_T_4.grid(row=0, column=3, sticky=E)
    116         Label(self.frm_B, text="Player1", font=('Arial', 16)).grid(row=1, column=1, sticky=N)
    117         Button(self.frm_B, text="出牌", command=self.discard, width=6, height=1,
    118                font=('Arial', 16)).grid(row=1, column=3)
    119         Button(self.frm_B, text="PASS", command=self.player_pass, width=6, height=1,
    120                font=('Arial', 16)).grid(row=1, column=4)
    121 
    122     def resize(self,w, h, w_box, h_box, pil_image):
    123         '''''
    124         resize a pil_image object so it will fit into
    125         a box of size w_box times h_box, but retain aspect ratio
    126         对一个pil_image对象进行缩放,让它在一个矩形框内,还能保持比例
    127         '''
    128 
    129         f1 = 1.0 * w_box / w  # 1.0 forces float division in Python2
    130         f2 = 1.0 * h_box / h
    131         factor = min([f1, f2])
    132         # print(f1, f2, factor) # test
    133         # use best down-sizing filter
    134         width = int(w * factor)
    135         height = int(h * factor)
    136         return pil_image.resize((width, height), Image.ANTIALIAS)
    137     def replay(self):
    138         self.load_sys()
    139 
    140     #初始化玩家手中牌
    141     def load_sys(self):
    142         # 初始化当前玩家手中牌集合,先重置
    143         self.player1_card_list = []
    144         self.player2_card_list = []
    145         self.check_list = []
    146         self.cur_identify = 1
    147         for i in range(3):
    148             num = random.randint(0,12)
    149             #判断是否生成重复的牌,去重
    150             while self.check_list.__contains__(num):
    151                 num = random.randint(0, 12)
    152             cur_str = self.num_list[num]
    153             photo_current = ImageTk.PhotoImage(self.resize(self.w, self.h, self.w_box, self.h_box, Image.open('images/card_C' + str(cur_str) + '.png')))
    154             frm_B_label_T_1 = Label(self.frm_B, image=photo_current)
    155             frm_B_label_T_1.image = photo_current
    156             frm_B_label_T_1.grid(row=0, column=i,sticky=E)
    157             frm_B_label_T_1.bind('<ButtonRelease-1>', self.handlerAdaptor(self.choose, cur_str,i))
    158             self.check_list.append(num)
    159             self.player1_card_list.append(cur_str)
    160             #生成玩家2手中的牌
    161             num2 = random.randint(0, 12)
    162             # 判断是否生成重复的牌,去重
    163             while self.check_list.__contains__(num2):
    164                 num2 = random.randint(0, 12)
    165             cur_str2 = self.num_list[num2]
    166             self.check_list.append(num2)
    167             self.player2_card_list.append(cur_str2)
    168 
    169         print(self.player1_card_list)
    170         print(self.player2_card_list)
    171         #记录当前轮数并递增
    172         self.frm_M_text.insert('1.0', 'this is ' + str(self.round_num) + ' round
    ')
    173         self.round_num+=1
    174 
    175         # 清空桌面上的牌
    176         frm_M_label_T = Label(self.frm_M, image=self.photo)
    177         frm_M_label_T.image = self.photo
    178         frm_M_label_T.grid(row=1, column=0, sticky=E)
    179         # 重置玩家手中当前牌
    180         frm_B_label_T_4 = Label(self.frm_B, image=self.photo)
    181         frm_B_label_T_4.image = self.photo
    182         frm_B_label_T_4.grid(row=0, column=3, sticky=E)
    183         #重置桌面上牌的大小
    184         self.mid_num = -2
    185     # Bottom
    186     def choose(self,event,a,position):
    187         self.frm_M_text.insert('1.0','Now Your Card Is C'+str(a)+'
    ')
    188         photo_cur = ImageTk.PhotoImage(self.resize(self.w, self.h, self.w_box, self.h_box, Image.open('images/card_C' + str(a) + '.png')))
    189         frm_B_label_T_4 = Label(self.frm_B, image=photo_cur)
    190         frm_B_label_T_4.image = photo_cur
    191         frm_B_label_T_4.grid(row=0, column=3, sticky=E)
    192         self.str_num = a
    193         self.cur_position = position
    194     def handlerAdaptor(self,fun, *kwds):
    195         '''''事件处理函数的适配器,相当于中介,此处接收2个参数,那个event是从那里来的呢,我也纳闷,这也许就是python的伟大之处吧'''
    196         return lambda event,fun=fun,kwds=kwds: fun(event, *kwds)
    197     def discard(self):
    198         if self.cur_identify == 1:
    199             if self.str_num != '':
    200                 self.index_num = self.num_list.index(self.str_num)
    201             if self.index_num == -1:
    202                 self.frm_M_text.insert('1.0','请选择一张牌
    ')
    203                 #return '请选择一张牌'
    204             #判断要打出的牌与桌面上的牌大小
    205             elif self.index_num <= self.mid_num:
    206                 self.frm_M_text.insert('1.0', '请选择一张大牌
    ')
    207                # return '请选择一张大牌'
    208             else:
    209                 photo_mid = ImageTk.PhotoImage(self.resize(self.w, self.h, self.w_box, self.h_box, Image.open('images/card_C' + str(self.str_num) + '.png')))
    210                 frm_M_label_T = Label(self.frm_M, image=photo_mid)
    211                 frm_M_label_T.image = photo_mid
    212                 frm_M_label_T.grid(row=1, column=0, sticky=E)
    213                 #清空玩家手中当前牌
    214                 frm_B_label_T_4 = Label(self.frm_B, image=self.photo)
    215                 frm_B_label_T_4.image = self.photo
    216                 frm_B_label_T_4.grid(row=0, column=3, sticky=E)
    217                 #frm_B_label_T_4.grid_forget()
    218                 #给当前桌面牌赋值
    219                 self.mid_num = self.index_num
    220                 #重置玩家手中牌
    221                 frm_B_label_T_X = Label(self.frm_B, image=self.photo)
    222                 frm_B_label_T_X.image = self.photo
    223                 frm_B_label_T_X.grid(row=0, column=self.cur_position, sticky=E)
    224                 self.frm_M_text.insert('1.0', 'Player1 Play The Card!'+ str(self.str_num) +'
    ')
    225                 self.player1_card_list.remove(self.str_num)
    226                 if self.player1_card_list.__len__() == 0:
    227                     self.frm_M_text.insert('1.0', 'Congratulations! Player1 Win The Game!
    ')
    228                     return
    229                 #当玩家打出牌后,切换到电脑2,调用电脑出牌方法
    230                 self.cur_identify +=1
    231                 self.discard_pc(self.cur_identify)
    232         else:
    233             self.frm_M_text.insert('1.0', '请等待其它玩家出牌
    ')
    234 
    235     #没有可出的牌,切换到下一个对手
    236     def player_pass(self):
    237         # 重置中间牌的大小
    238         self.mid_num = -2
    239         #切换玩家
    240         self.cur_identify += 1
    241         self.discard_pc(self.cur_identify)
    242 
    243     # def player_pc(self,iden):
    244     #     if iden == 2:
    245     #         self.player_card_list = self.player2_card_list
    246     #
    247     #     if iden ==3:
    248     #         self.cur_identify = 1
    249 
    250     def discard_pc(self,iden):
    251         card_list_pc = []
    252         if iden == 2:
    253             for i in range(self.player2_card_list.__len__()):
    254                 #将当前牌转化成索引号进行比较大小
    255                 self.index_pc_num = self.num_list.index(self.player2_card_list[i])
    256 
    257                 if self.index_pc_num > self.mid_num:
    258                     card_list_pc.append(self.player2_card_list[i])
    259             card_list_pc.sort()
    260             if len(card_list_pc) > 0:
    261                 self.index_pc_num_temp = self.num_list.index(card_list_pc[0])
    262                 self.mid_num = self.index_pc_num_temp
    263                 photo_mid = ImageTk.PhotoImage(self.resize(self.w, self.h, self.w_box, self.h_box,
    264                                                            Image.open('images/card_C' + str(card_list_pc[0]) + '.png')))
    265                 frm_M_label_T = Label(self.frm_M, image=photo_mid)
    266                 frm_M_label_T.image = photo_mid
    267                 frm_M_label_T.grid(row=1, column=0, sticky=E)
    268                 self.frm_M_text.insert('1.0', 'Player2 Play The Card!' + str(card_list_pc[0]) + '
    ')
    269                 self.player2_card_list.remove(card_list_pc[0])
    270 
    271                 if self.player2_card_list.__len__() == 0:
    272                     self.frm_M_text.insert('1.0', 'Congratulations! Player2 Win The Game!
    ')
    273                     return
    274                 # 当玩家打出牌后,切换到电脑2,调用电脑出牌方法
    275                 self.cur_identify += 1
    276                 if self.cur_identify == 3:
    277                     self.cur_identify = 1
    278             elif len(card_list_pc) == 0:
    279                 self.frm_M_text.insert('1.0', '没有大过玩家的牌,请玩家出牌
    ')
    280                 #重置中间牌的大小
    281                 self.mid_num = -2
    282                 self.cur_identify = 1
    283 
    284     # # 实例化一个sched对象
    285     # schedule = sched.scheduler(time.time, time.sleep)
    286     def show_time(self):
    287         cur_time = time.strftime('%Y-%m-%d %X',time.localtime())
    288         top_time_label = Label(self.frm_T, text=cur_time, font=('Arial', 16))
    289         top_time_label.grid(column=2, sticky=N)
    290         while True:
    291             cur_time = time.strftime('%Y-%m-%d %X', time.localtime())
    292             top_time_label.configure(text=cur_time)
    293             time.sleep(1)
    294     def main_start(self):
    295         thd.Timer(0, self.show_time).start()
    296 def main():
    297     d = card2()
    298     mainloop()
    299 
    300 if __name__ == '__main__':
    301     main()
    View Code

    注意:调整图片大小需要用到resize()方法,PNG图片需要用到ImageTk.PhotoImage(self.img_resized)转化方可显示。

    增加了定时任务显示当前时间,每秒切换一次,注意不要占用主线程。

    提出几个方向以待大神们能完善:

    2.1、程序中只启用了player2与玩家互动,可以尝试启用4个。

    2.2、只选择了一组牌进行显示,可以尝试加入4组牌,用file文件引入数据。

    2.3、不同花色的相同数字比较可以用3.1、3.2、3.3、3.4浮点数比较大小。

    2.4、图片显示可以增加更多,遗留的问题是图片重叠显示,感觉用tkinter的grid方式无法实现,可能自己水平有限。

  • 相关阅读:
    Redis可视化客户端管理及监控工具TreeNMS
    Memcache分布式锁 转发 https://www.cnblogs.com/li150dan/p/9529090.html
    MemCache在.NET中使用Memcached.ClientLibrary详解 转发 https://www.cnblogs.com/li150dan/p/9529112.html
    C# Memcache分布式缓存简单入门
    ASP.NET cache缓存的用法
    .net core redis 驱动推荐,为什么不使用 StackExchange.Redis 转发 https://www.cnblogs.com/kellynic/p/9325816.html
    StackExchange.Redis通用封装类分享
    Windows下Redis缓存服务器的使用 .NET StackExchange.Redis Redis Desktop Manager 转发非原创
    .Net使用Redis详解之ServiceStack.Redis(七) 转载https://www.cnblogs.com/knowledgesea/p/5032101.html
    redis的过期时间和过期删除机制
  • 原文地址:https://www.cnblogs.com/lq147760524/p/8283803.html
Copyright © 2011-2022 走看看