Playing with Tkinter in the form of Logogame and Editor
This commit is contained in:
Voussoir 2015-03-04 02:07:48 -08:00
parent 46b49f7113
commit 90b943c90f
12 changed files with 436 additions and 1 deletions

2
.gitignore vendored
View file

@ -1,3 +1,5 @@
Classifieds/
# Windows image file caches
Thumbs.db
ehthumbs.db

View file

@ -8,7 +8,7 @@ class dodgygame:
def __init__(self):
tkvar = Tk()
tkvar.resizable(0,0)
tkvar.wm_title("Dodgy")
tkvar.wm_title('Dodgy')
tkvar.iconbitmap('Excl.ico')
arenasize = 40

6
Editor/README.md Normal file
View file

@ -0,0 +1,6 @@
Editor
==========
A neat idea that I would one day like to make into a website or something. Users read and write text files simply by choosing the file name. If it exists, the text is returned to them for editing. If it does not, it will be created when they press Save. No logins and no file security. Since it's using a database instead of actual txt files, there are no filename character restrictions, only a maximum title length for sanity's sake.
For now, it's just a tkinter toy.

200
Editor/editor.py Normal file
View file

@ -0,0 +1,200 @@
import tkinter
import sqlite3
import hashlib
import random
class Editor:
def __init__(self):
self.WINDOWS_BADCHARS = '\\/?:*"><|'
self.sql = sqlite3.connect('textfiles.db')
self.cur = self.sql.cursor()
self.cur.execute('CREATE TABLE IF NOT EXISTS textfiles(id TEXT, filename TEXT, filetext TEXT)')
self.cur.execute('CREATE INDEX IF NOT EXISTS textfilesindex ON textfiles(id)')
self.sql.commit()
self.font_large = ("Consolas", 16)
self.font_med = ("Consolas", 12)
self.font_small = ("Consolas", 10)
self.kilobyte = 1024
self.megabyte = 1048576
self.maximum_characters = 1*self.megabyte
self.maximum_title = 64
self.t = tkinter.Tk()
self.w = 450
self.h = 350
self.screenwidth = self.t.winfo_screenwidth()
self.screenheight = self.t.winfo_screenheight()
self.windowwidth = self.w
self.windowheight = self.h
self.windowx = (self.screenwidth-self.windowwidth) / 2
self.windowy = ((self.screenheight-self.windowheight) / 2) - 27
self.geometrystring = '%dx%d+%d+%d' % (self.windowwidth, self.windowheight, self.windowx, self.windowy)
self.t.geometry(self.geometrystring)
self.entities = []
self.filename = None
self.gui_build_fileloader()
self.t.mainloop()
def annihilate(self):
for x in self.entities:
try:
x.grid_forget()
x.pack_forget()
except:
pass
x.destroy()
def gui_build_fileloader(self, *b):
self.annihilate()
self.frame_fileloader = tkinter.Frame(self.t)
self.entities.append(self.frame_fileloader)
self.entry_filename = tkinter.Entry(self.frame_fileloader, font=self.font_large, justify='right')
self.entry_filename.grid(row=0, column=0, columnspan=3)
self.entry_filename.focus_set()
self.entry_filename.bind("<Return>", self.loadfile_smart)
self.entities.append(self.entry_filename)
self.label_filename = tkinter.Label(self.frame_fileloader, font=self.font_large, text='.txt')
self.label_filename.grid(row=0, column=3)
self.entities.append(self.label_filename)
self.button_fileloader = tkinter.Button(self.frame_fileloader, font=self.font_large, text='Load', command=self.loadfile_smart)
self.button_fileloader.grid(row=1, column=1, pady=10)
self.entities.append(self.button_fileloader)
width = self.t.winfo_width()
height = self.t.winfo_height()
if min([width, height]) < 20:
width = self.w
height = self.h
#self.frame_fileloader.pack(expand=True, fill='both', anchor='center')
self.frame_fileloader.place(x=width/2, y=(height/2)-10, anchor='center')
def gui_build_editor(self, filetext, *b):
self.annihilate()
self.frame_toolbar = tkinter.Frame(self.t)
self.frame_toolbar.pack()
self.entities.append(self.frame_toolbar)
self.button_back = tkinter.Button(self.frame_toolbar, text='back', command=self.gui_build_fileloader, font=self.font_small)
self.button_back.grid(row=0, column=0)
self.entities.append(self.button_back)
self.label_filename = tkinter.Label(self.frame_toolbar, text=self.filename, font=self.font_small)
self.label_filename.grid(row=0, column=1, padx=20)
self.entities.append(self.label_filename)
self.button_save = tkinter.Button(self.frame_toolbar, text='save', command=self.savefile_smart, font=self.font_small)
self.button_save.grid(row=0, column=2)
self.entities.append(self.button_save)
self.label_filesize = tkinter.Label(self.frame_toolbar, text='', font=self.font_small)
self.label_filesize.grid(row=1, column=0, columnspan=10)
self.entities.append(self.label_filesize)
self.text_editor = tkinter.Text(self.t, wrap='word', font=self.font_med)
self.text_editor.insert('end', filetext)
self.text_editor.pack(expand=True, fill='both')
self.text_editor.focus_set()
self.text_editor.bind('<Control-s>', self.savefile_smart)
self.text_editor.bind('<Control-w>', self.gui_build_fileloader)
self.entities.append(self.text_editor)
def savefile_smart(self, *b):
try:
filetext = self.text_editor.get('0.0', 'end')
self.savefile(self.filename, filetext)
filesize = len(filetext) - 1
self.label_filesize.configure(text=self.filesizestring(filesize))
except NameError:
# text editor does not exist for some reason
return
def savefile(self, filename, filetext):
filetext = filetext[:-1]
# Text widget seems to add \n to the end at all times
# So remove it.
if self.filename is None:
return False
filesize = len(filetext)
namesize = len(filename)
if filesize > self.maximum_characters:
diff = filesize-self.maximum_characters
print('File exceeds maximum character limit. %d / %d (-%d)' % (filesize, self.maximum_characters, diff))
return False
elif namesize > self.maximum_title:
diff = namesize - self.maximum_title
print('Filename exceeds maximum character limit: %d / %d (-%d)' % (namesize, self.maximum_title, diff))
return False
sha = self.sha(filename)
self.cur.execute('SELECT * FROM textfiles WHERE id=?', [sha])
fetch = self.cur.fetchone()
if filesize == 0:
print('Deleting %s' % filename)
self.cur.execute('DELETE FROM textfiles WHERE id=?', [sha])
else:
if fetch:
self.cur.execute('UPDATE textfiles SET filename=?, filetext=? WHERE id=?', [filename, filetext, sha])
else:
self.cur.execute('INSERT INTO textfiles VALUES(?, ?, ?)', [sha, filename, filetext])
print('Wrote %s: %s' % (filename, self.filesizestring(filesize)))
self.sql.commit()
return True
def filesizestring(self, filesize):
percentage = "%0.4f" % (100 * filesize / self.maximum_characters)
diff = self.maximum_characters - filesize
out = '%d c, %s%%, +%d' % (filesize, percentage, diff)
return out
def loadfile_smart(self, *b):
try:
filename = self.entry_filename.get()
except NameError:
# entry_filename does not exist somehow
return
filetext = self.loadfile(filename)
if filetext is not None:
self.gui_build_editor(filetext)
return
def loadfile(self, filename):
if filename == 'random':
filename = self.loadrandom()
if len(filename) < 1:
return None
if len(filename) > self.maximum_title:
print('Title too long. %d / %d' % (len(filename), self.maximum_title))
return None
self.filename = filename
sha = self.sha(filename)
self.cur.execute('SELECT * FROM textfiles WHERE id=?', [sha])
fetch = self.cur.fetchone()
if fetch:
loadedtext = fetch[2]
return loadedtext
else:
print('New file: %s' % filename)
return ""
def loadrandom(self):
self.cur.execute('SELECT * FROM textfiles')
fetch = self.cur.fetchall()
if len(fetch) < 1:
return ""
return random.choice(fetch)[1]
def strip_to_filename(self, s):
for bad in self.WINDOWS_BADCHARS:
s = s.replace(bad, '')
return s
def sha(self, data):
sha = hashlib.sha256()
data = data.encode('utf-8')
sha.update(data)
sha = sha.hexdigest()
return sha
editor = Editor()

BIN
Editor/textfiles.db Normal file

Binary file not shown.

4
Logogame/README.md Normal file
View file

@ -0,0 +1,4 @@
Logos
=======
Another tkinter thing that I probably won't finish, but I'm playing around with displaying PNG images.

Binary file not shown.

After

Width:  |  Height:  |  Size: 179 KiB

BIN
Logogame/images/Jarate.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 207 KiB

BIN
Logogame/logos.db Normal file

Binary file not shown.

209
Logogame/logos.py Normal file
View file

@ -0,0 +1,209 @@
import os
import tkinter
import sqlite3
import hashlib
import string
from PIL import Image
from PIL import ImageTk
class Generic:
def __init__(self):
pass
def set_dict_attributes(self, attributes):
for attribute in attributes:
setattr(self, attribute, attributes[attribute])
class LogoGame:
def __init__(self):
self.WINDOWS_BADCHARS = '\\/?:*"><|'
self.t = tkinter.Tk()
self.t.title('Logogame')
self.tkinter_elements = []
if not os.path.exists('logos.db'):
print('You\'re missing the game\'s logo database!')
print('Cannot proceed!')
quit()
self.font_main = ('Consolas', 12)
self.font_small = ('Consolas', 8)
self.color_blue = '#0ed'
self.color_green = '#31f13a'
self.color_red = '#e23939'
self.sql = sqlite3.connect('logos.db')
self.cur = self.sql.cursor()
self.stats_main = self.stats_load('stats')
self.playerstats_load(self.stats_main.playername)
self.w = 1062
self.h = 600
self.screenwidth = self.t.winfo_screenwidth()
self.screenheight = self.t.winfo_screenheight()
self.windowwidth = self.w
self.windowheight = self.h
self.windowx = (self.screenwidth-self.windowwidth) / 2
self.windowy = ((self.screenheight-self.windowheight) / 2) - 27
self.geometrystring = '%dx%d+%d+%d' % (self.windowwidth, self.windowheight, self.windowx, self.windowy)
self.t.geometry(self.geometrystring)
self.uirefresher = self.buildui_main
self.buildui_main()
self.t.bind('<Configure>', self.update_wh)
self.t.mainloop()
def update_wh(self, *b):
oldw = self.w
oldh = self.h
self.w = self.t.winfo_width()
self.h = self.t.winfo_height()
if oldw != self.w or oldh != self.h:
pass
#self.uirefresher()
def destroy_all_elements(self):
while len(self.tkinter_elements) > 0:
self.tkinter_elements[0].destroy()
del self.tkinter_elements[0]
def buildui_main(self, *b):
self.destroy_all_elements()
x = self.w
y = self.h
self.button_playgame = tkinter.Button(
self.t,
text='Play',
#relief='flat',
font=self.font_main,
bg=self.color_green,
activebackground=self.color_green,
command=self.buildui_game)
self.button_playgame.grid(row=10, column=5)
self.label_playername = tkinter.Label(self.t, text='Player name: ', font=self.font_main)
self.label_playername.grid(row=30, column=4)
self.entry_playername = tkinter.Entry(
self.t,
font=self.font_main,
relief='solid',
width=30)
self.entry_playername.bind('<Return>', lambda x: self.playername_set(self.entry_playername.get()))
self.entry_playername.insert(0, self.stats_main.playername)
self.entry_playername.grid(row=30, column=5)
self.button_playername = tkinter.Button(
self.t,
text='Set',
font=self.font_small,
#relief='flat',
bg=self.color_blue,
activebackground=self.color_blue,
command=lambda: self.playername_set(self.entry_playername.get()))
self.button_playername.grid(row=30, column=6)
self.label_playerhash = tkinter.Label(self.t, text=self.sha8(self.stats_main.playername),
font=self.font_main)
self.label_playerhash.grid(row=30, column=7)
self.tkinter_elements.append(self.button_playgame)
self.tkinter_elements.append(self.label_playername)
self.tkinter_elements.append(self.entry_playername)
self.tkinter_elements.append(self.button_playername)
self.tkinter_elements.append(self.label_playerhash)
def buildui_game(self, *b):
self.destroy_all_elements()
self.button_back = tkinter.Button(
self.t,
text='X',
font=self.font_main,
bg=self.color_red,
activebackground=self.color_red,
command=self.buildui_main)
self.button_back.grid(row=0, column=0)
self.tkinter_elements.append(self.button_back)
def playername_set(self, newname):
if newname != self.stats_main.playername:
self.cur.execute('UPDATE stats SET value=? WHERE key="playername"', [newname])
self.sql.commit()
playerhash = self.playerstats_load(newname)
self.stats_main.playername = newname
if self.label_playerhash:
self.label_playerhash.configure(text=playerhash)
print('Name: ' + self.stats_main.playername)
def sha8(self, text):
sha = hashlib.sha256()
sha.update(text.encode('utf-8'))
sha = sha.hexdigest()
return sha[:8]
def getnext(self):
pass
def png_load(self, filename, resize=None):
if filename[-4:] != '.png':
filename = filename + '.png'
i = Image.open(filename)
if resize:
ratio = resize / max(i.size)
newx = int(i.size[0] * ratio)
newy = int(i.size[1] * ratio)
i = i.resize([newx, newy])
i = ImageTk.PhotoImage(i)
return i
def stats_load(self, database):
if database == 'stats':
self.cur.execute('SELECT * FROM stats')
fetchall = self.cur.fetchall()
if database == 'player':
self.cur_player.execute('SELECT * FROM stats')
fetchall = self.cur_player.fetchall()
keyvals = {}
for fetched in fetchall:
keyvals[fetched[0]] = fetched[1]
stats = Generic()
stats.set_dict_attributes(keyvals)
return stats
def playerstats_load(self, playername, presha=False):
if not presha:
sha = self.sha8(playername)
else:
sha = playername
filename = self.strip_to_filename(playername) + '_' + sha
self.sql_player = sqlite3.connect('playerdata/%s.db' % filename)
self.cur_player = self.sql_player.cursor()
self.cur_player.execute('CREATE TABLE IF NOT EXISTS stats(key TEXT, value TEXT)')
self.sql_player.commit()
return sha
def playerstats_set(self, key, value):
self.cur_player.execute('SELECT * FROM stats WHERE key=?', [key])
if cur.fetchone():
self.cur_player.execute('UPDATE stats SET value=? WHERE key=?', [value, key])
else:
self.cur_player.execute('INSERT INTO stats VALUES(?, ?)', [key, value])
self.sql_player.commit()
def playerstats_get(self, key):
self.cur_execute.execute('SELECT * FROM stats WHERE key=?', [key])
f = cur.fetchone()
if f:
return f[1]
return None
def strip_to_filename(self, s):
for badchar in self.WINDOWS_BADCHARS:
s = s.replace(badchar, '')
return s
logogame = LogoGame()

Binary file not shown.

14
Logogame/test.py Normal file
View file

@ -0,0 +1,14 @@
import tkinter
from PIL import Image
from PIL import ImageTk
t=tkinter.Tk()
im = Image.open('images/swirl_00.png')
im = ImageTk.PhotoImage(im)
l = tkinter.Label(t, text="heyo", image=im)
l.im = im
l.pack()
t.mainloop()