szablon_gui.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. #!/usr/bin/env python3
  2. import configparser
  3. import sys
  4. import tkinter as tk
  5. import tkinter.messagebox
  6. from tkinter.constants import NSEW
  7. import threading
  8. import os
  9. import socket
  10. import selectors
  11. import json
  12. from functools import partial
  13. config_fname = "config.txt"
  14. sel = selectors.DefaultSelector()
  15. messages = [b"Message 1 from client.", b"Message 2 from client."]
  16. class Client(threading.Thread):
  17. def __init__(self, host, port, username, gui):
  18. super().__init__()
  19. self.host = host
  20. self.port = port
  21. self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  22. self.name = username
  23. self.gui = gui
  24. self.start()
  25. def start(self):
  26. self.sock.connect((self.host, self.port))
  27. print('Connected to {}:{}'.format(self.host, self.port))
  28. # Send the username as a welcome message
  29. self.sock.sendall(self.name.encode('utf8'))
  30. super().start()
  31. def close(self):
  32. try:
  33. self.sock.close()
  34. except:
  35. pass
  36. def send(self, message):
  37. self.sock.sendall(message.encode('utf8'))
  38. def vote(self, player):
  39. self.sock.sendall(str(player).encode('utf8'))
  40. def run(self):
  41. try:
  42. while True:
  43. message = self.sock.recv(4096).decode('utf8')
  44. if message:
  45. data = json.loads(message)
  46. if "playerid" in data:
  47. self.gui.player_id = int(data["playerid"])
  48. self.gui.server_data = data
  49. if data["state"] == "vote":
  50. self.gui.messages = []
  51. for key in data["messages"]:
  52. self.gui.messages.append((key, data["messages"][key]))
  53. self.gui.switch_to(data["state"])
  54. else:
  55. self.close()
  56. except:
  57. self.close()
  58. class GUI(tk.Frame):
  59. def __init__(self, master=None):
  60. self.config= configparser.ConfigParser()
  61. self.config.read(config_fname, "UTF8")
  62. tk.Frame.__init__(self, master)
  63. self.parent=master
  64. self.parent.protocol("WM_DELETE_WINDOW", self.quit)
  65. domyslne=self.config["DEFAULT"]
  66. self.geometria_baza=domyslne.get('bazowa_geometria',"1000x800+50+50")
  67. self.parent.geometry(self.geometria_baza)
  68. self.parent.minsize(1024, 768)
  69. self.utworz_bazowe_menu()
  70. # self.utworz_pasek_narzedzi()
  71. self.utworz_status()
  72. self.dodaj_menu_custom()
  73. self.dodaj_menu_help()
  74. # self.utworz_dodatki()
  75. self.parent.columnconfigure(0, weight=999)
  76. self.parent.columnconfigure(1, weight=1)
  77. self.parent.rowconfigure(0, weight=1)
  78. self.parent.rowconfigure(1, weight=9999)
  79. self.parent.rowconfigure(2, weight=1)
  80. self.client = None
  81. self.bg_color = '#36393f'
  82. self.font_color = '#cccccc'
  83. self.frames = {}
  84. self.frames["wait"] = self.draw_wait_screen()
  85. self.frames["game"] = self.draw_game_screen()
  86. self.frames["welcome"] = self.draw_welcome_screen()
  87. self.switch_to("welcome")
  88. self.messages = []
  89. self.player_id = -1
  90. self.server_data = {}
  91. self.master.title("AFORYZMY")
  92. def utworz_pasek_narzedzi(self):
  93. self.toolbar_images = [] #muszą być pamiętane stale
  94. self.toolbar = tk.Frame(self.parent)
  95. for image, command in (
  96. ("res/filenew.gif", self.file_new),
  97. ("res/fileopen.gif", self.file_open),
  98. ("res/filesave.gif", self.file_save)):
  99. image = os.path.join(os.path.dirname(__file__), image)
  100. try:
  101. image = tkinter.PhotoImage(file=image)
  102. self.toolbar_images.append(image)
  103. button = tkinter.Button(self.toolbar, image=image,
  104. command=command)
  105. button.grid(row=0, column=len(self.toolbar_images) -1) #KOLEJNE ELEMENTY
  106. except tkinter.TclError as err:
  107. print(err) # gdy kłopoty z odczytaniem pliku
  108. self.toolbar.grid(row=0, column=0, columnspan=2, sticky=tkinter.NSEW)
  109. def utworz_dodatki(self):
  110. pass
  111. def utworz_status(self):
  112. self.statusbar = tk.Label(self.parent, text="Status...",
  113. anchor=tkinter.W)
  114. self.statusbar.after(5000, self.clearStatusBar)
  115. self.statusbar.grid(row=2, column=0, columnspan=2,
  116. sticky=tkinter.EW)
  117. pass
  118. def ustawStatusBar(self, txt):
  119. self.statusbar["text"] = txt
  120. def clearStatusBar(self):
  121. self.statusbar["text"] = ""
  122. def utworz_bazowe_menu(self):
  123. self.menubar = tk.Menu(self.parent)
  124. self.parent["menu"] = self.menubar
  125. fileMenu = tk.Menu(self.menubar)
  126. for label, command, shortcut_text, shortcut in (
  127. ("Rozłącz", self.disconnect, None, None),
  128. ("Quit", self.quit, "Ctrl+Q", "<Control-q>")):
  129. if label is None:
  130. fileMenu.add_separator()
  131. else:
  132. fileMenu.add_command(label=label, underline=0,
  133. command=command, accelerator=shortcut_text)
  134. self.parent.bind(shortcut, command)
  135. self.menubar.add_cascade(label="File", menu=fileMenu, underline=0)
  136. pass
  137. def dodaj_menu_help(self):
  138. fileMenu = tk.Menu(self.menubar)
  139. fileMenu.add_command(label="About...", underline=0,
  140. command=self.file_new, accelerator="Ctrl+B")
  141. self.parent.bind("<Control-b>", self.file_new)
  142. self.menubar.add_cascade(label="Help", menu=fileMenu, underline=0)
  143. pass
  144. def close(self):
  145. geometria = self.parent.winfo_geometry()
  146. self.config["DEFAULT"]["bazowa_geometria"] = geometria
  147. with open(config_fname, 'w') as config_plik:
  148. self.config.write(config_plik)
  149. self.parent.destroy()
  150. def disconnect(self, event= None):
  151. if self.client is not None:
  152. self.client.close()
  153. self.client = None
  154. self.switch_to("welcome")
  155. def quit(self, event= None):
  156. reply = tkinter.messagebox.askyesno(
  157. "Wyjście",
  158. "Naprawdę wyjść?", parent=self.parent)
  159. event=event
  160. if reply:
  161. if (self.client is not None):
  162. self.client.close()
  163. self.close()
  164. def dodaj_menu_custom(self):
  165. pass
  166. def file_new(self, event=None):
  167. event=event
  168. def file_open(self,event=None):
  169. event=event
  170. pass
  171. def file_save(self,event=None):
  172. event=event
  173. pass
  174. def connect(self):
  175. self.client = Client(self.address_entry.get(), 7312, self.username_entry.get(), self)
  176. def upload(self):
  177. self.switch_to("wait")
  178. self.client.send(self.aphorism_entry.get())
  179. def vote(self, player):
  180. self.switch_to("wait")
  181. self.client.vote(player)
  182. def switch_to(self, state):
  183. for frame in self.frames:
  184. self.frames[frame].grid_forget()
  185. if state == "vote" or state == "display":
  186. self.frames[state] = self.draw_screen(state)
  187. self.frames[state].grid(row=1, column=0, columnspan=1, rowspan=1, sticky=NSEW)
  188. def draw_wait_screen(self):
  189. frame = tk.Frame(self.parent, background=self.bg_color)
  190. label = tk.Label(frame, text="Waiting for other players", pady=100, bg=self.bg_color, fg=self.font_color)
  191. label.pack()
  192. return frame
  193. def draw_screen(self, type):
  194. if(type == "vote"):
  195. frame = tk.Frame(self.parent, background=self.bg_color)
  196. title_label = tk.Label(frame, text="AFORYZMY", bg=self.bg_color, fg=self.font_color, font="Helvetica 22")
  197. title_label.pack()
  198. tk.Label(frame, text="Wybierz najlepszą definicję ASS", fg=self.font_color, bg=self.bg_color, font="Helvetica 12", height="2", anchor="n").pack()
  199. for message in self.messages:
  200. player, text = message
  201. if str(player) != str(self.player_id):
  202. tk.Button(frame, text=text, fg=self.font_color, bg=self.bg_color, font="Helvetica 12", width="80", height="3", pady="2", relief="flat", command=partial(self.vote, player)).pack()
  203. return frame
  204. if (type == "display"):
  205. frame = tk.Frame(self.parent, background=self.bg_color)
  206. title_label = tk.Label(frame, text="AFORYZMY", bg=self.bg_color, fg=self.font_color, font="Helvetica 22")
  207. title_label.pack()
  208. tk.Label(frame, text="Wyniki", fg=self.font_color, bg=self.bg_color,
  209. font="Helvetica 12", height="2", anchor="n").pack()
  210. for message in self.messages:
  211. player, text = message
  212. total_score = 0
  213. score = 0
  214. if player in self.server_data["total_scores"]:
  215. total_score = self.server_data["total_scores"][player]
  216. if player in self.server_data["scores"]:
  217. score = self.server_data["scores"][player]
  218. tk.Label(frame, text="{} ({}):\n{} ({})".format(self.server_data["users"][player], total_score, text, score), fg=self.font_color, bg=self.bg_color, font="Helvetica 12", width="100", anchor="nw",
  219. height="3", pady="2").pack()
  220. tk.Label(frame, text="Kolejna runda rozpocznie się za chwilę", fg=self.font_color, bg=self.bg_color,
  221. font="Helvetica 12", height="3", anchor="s").pack()
  222. return frame
  223. def draw_game_screen(self):
  224. frame = tk.Frame(self.parent, background=self.bg_color)
  225. title_label = tk.Label(frame, text="AFORYZMY", bg=self.bg_color, fg=self.font_color, font="Helvetica 22")
  226. title_label.pack()
  227. tk.Label(frame, text="Describe the word: ASS", fg=self.font_color, bg=self.bg_color, font="Helvetica 12").pack()
  228. sv = tk.StringVar()
  229. self.aphorism_entry = tk.Entry(frame, width=80, textvariable=sv)
  230. sv.trace_add("write", lambda x, y, z: self.key_fix(sv, 100))
  231. self.aphorism_entry.pack()
  232. send_button = tk.Button(frame, text="Send", command=self.upload)
  233. send_button.pack()
  234. return frame
  235. def draw_welcome_screen(self):
  236. frame = tk.Frame(self.parent, background=self.bg_color)
  237. title_label = tk.Label(frame, text="AFORYZMY", bg=self.bg_color, fg=self.font_color, font="Helvetica 22")
  238. title_label.pack()
  239. tk.Label(frame, text="Login", fg=self.font_color, bg=self.bg_color, font="Helvetica 12").pack()
  240. sv = tk.StringVar()
  241. self.username_entry = tk.Entry(frame, textvariable=sv)
  242. sv.trace_add("write", lambda x,y,z: self.key_fix(sv, 20))
  243. self.username_entry.pack()
  244. tk.Label(frame, text="Address", fg=self.font_color, bg=self.bg_color, font="Helvetica 12").pack()
  245. self.address_entry = tk.Entry(frame)
  246. self.address_entry.insert(0,"localhost")
  247. self.address_entry.pack()
  248. title_button = tk.Button(frame, text="Connect", command=self.connect)
  249. title_button.pack()
  250. return frame
  251. def key_fix(self, sv, limit):
  252. str = sv.get()
  253. list = [
  254. ('ę', 'ê'), ('Ę', 'Ê'),
  255. ('ś', 'œ'), ('Ś', 'Œ'),
  256. ('ć', 'æ'), ('Ć', 'Æ'),
  257. ('ł', '³'), ('Ł', '£'),
  258. ('ń', 'ñ'), ('Ń', 'Ñ'),
  259. ('ą', '¹'), ('Ą', '¥'),
  260. ('ż', '¿'), ('Ż', '¯'),
  261. ('ź', 'Ÿ'), #('Ź', '')
  262. ]
  263. for (pl, k) in list:
  264. str = str.replace(k, pl)
  265. sv.set(str[:limit])
  266. if __name__ == '__main__':
  267. root = tk.Tk()
  268. app = GUI(master=root)
  269. app.mainloop()
  270. pass