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方式无法实现,可能自己水平有限。

  • 相关阅读:
    【转】【SEE】基于SSE指令集的程序设计简介
    【转】【Asp.Net】asp.net服务器控件创建
    ControlTemplate in WPF ——ScrollBar
    ControlTemplate in WPF —— Menu
    ControlTemplate in WPF —— Expander
    ControlTemplate in WPF —— TreeView
    ControlTemplate in WPF —— ListBox
    ControlTemplate in WPF —— ComboBox
    ControlTemplate in WPF —— TextBox
    ControlTemplate in WPF —— RadioButton
  • 原文地址:https://www.cnblogs.com/lq147760524/p/8283803.html
Copyright © 2011-2022 走看看