else
Playing with Tkinter in the form of Logogame and Editor
This commit is contained in:
parent
46b49f7113
commit
90b943c90f
12 changed files with 436 additions and 1 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,3 +1,5 @@
|
||||||
|
Classifieds/
|
||||||
|
|
||||||
# Windows image file caches
|
# Windows image file caches
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
ehthumbs.db
|
ehthumbs.db
|
||||||
|
|
|
@ -8,7 +8,7 @@ class dodgygame:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
tkvar = Tk()
|
tkvar = Tk()
|
||||||
tkvar.resizable(0,0)
|
tkvar.resizable(0,0)
|
||||||
tkvar.wm_title("Dodgy")
|
tkvar.wm_title('Dodgy')
|
||||||
tkvar.iconbitmap('Excl.ico')
|
tkvar.iconbitmap('Excl.ico')
|
||||||
|
|
||||||
arenasize = 40
|
arenasize = 40
|
||||||
|
|
6
Editor/README.md
Normal file
6
Editor/README.md
Normal 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
200
Editor/editor.py
Normal 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
BIN
Editor/textfiles.db
Normal file
Binary file not shown.
4
Logogame/README.md
Normal file
4
Logogame/README.md
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
Logos
|
||||||
|
=======
|
||||||
|
|
||||||
|
Another tkinter thing that I probably won't finish, but I'm playing around with displaying PNG images.
|
BIN
Logogame/images/Degreaser.png
Normal file
BIN
Logogame/images/Degreaser.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 179 KiB |
BIN
Logogame/images/Jarate.png
Normal file
BIN
Logogame/images/Jarate.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 207 KiB |
BIN
Logogame/logos.db
Normal file
BIN
Logogame/logos.db
Normal file
Binary file not shown.
209
Logogame/logos.py
Normal file
209
Logogame/logos.py
Normal 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()
|
BIN
Logogame/playerdata/Delta_18833da3.db
Normal file
BIN
Logogame/playerdata/Delta_18833da3.db
Normal file
Binary file not shown.
14
Logogame/test.py
Normal file
14
Logogame/test.py
Normal 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()
|
Loading…
Reference in a new issue