-
Notifications
You must be signed in to change notification settings - Fork 0
/
solution.py
151 lines (118 loc) · 7.5 KB
/
solution.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
import tkinter as tk
import keyboard_design as kd
import recognizer
from template import Point, WordTemplates
from tkinter import messagebox # SOLUTION STEP 1: Import message box component
class Application(tk.Frame):
def __init__(self, window_width, window_height, master=None):
super().__init__(master) # Call tk.Frame.__init__(master)
self.master = master # Update the master object after tk.Frame() makes necessary changes to it
frame_bottom_height = 200
frame_middle_height = 50
frame_top_height = window_height - frame_bottom_height - frame_middle_height
# the top frame is used to show input words in the text
frame_top = tk.Frame(self.master)
frame_top.place(x=0, y=0, width=window_width, height=frame_top_height)
self.text = tk.Text(frame_top, bg='white', borderwidth=2, relief='groove', font=('Arial', 20))
self.text.place(x=0, y=0, width=window_width, height=frame_top_height)
# the middle frame is used to list word candidates (four labels)
frame_middle = tk.Frame(self.master)
frame_middle.place(x=0, y=frame_top_height, width=window_width, height=frame_middle_height)
word_candidate_num = 4
self.label_word_candidates = [] # labels used to show word candidates
for i in range(word_candidate_num): # the values 0 to (word_candidate_num - 1)
label_word = tk.Label(frame_middle, bg='white', borderwidth=2, relief='groove', font=15) #anchor='w',
label_word.place(relx=i/word_candidate_num, relwidth=1/word_candidate_num, height=frame_middle_height)
label_word.bind("<ButtonRelease-1>", self.select_word_candidate)
print(i/word_candidate_num)
self.label_word_candidates.append(label_word)
# the bottom frame is used to show the keyboard
frame_bottom = tk.Frame(self.master)
frame_bottom.place(x=0, y=(frame_top_height + frame_middle_height), width=window_width,
height=frame_bottom_height)
self.canvas_keyboard = tk.Canvas(frame_bottom, bg='light gray', borderwidth=2, relief='groove')
self.canvas_keyboard.place(x=0, y=0, width=window_width, height=frame_bottom_height)
self.keyboard = kd.Keyboard(self.canvas_keyboard)
self.keyboard.keyboard_layout()
# generate word templates
templates = WordTemplates(self.keyboard.get_keys())
# generate a recognizer
self.word_recognizer = recognizer.Recognizer(templates.set_templates())
self.gesture_points = []
# mouse events on the canvas keyboard
self.canvas_keyboard.bind("<ButtonPress-1>", self.mouse_left_button_press)
self.canvas_keyboard.bind("<ButtonRelease-1>", self.mouse_left_button_release)
self.canvas_keyboard.bind("<B1-Motion>", self.mouse_move_left_button_down)
# store x, y, segment tag
self.cursor_move_position_list = []
# store the tag for each segment of the drawn gesture
self.line_tag = []
# when users select a word candidate from the four labels in the middle frame
def select_word_candidate(self, event):
btn = event.widget # event.widget is the widget that called the event
#self.label_show_text.config(text=btn.cget('text'))
self.text.insert(tk.END, btn.cget('text')) # show it to the text widget
for i in range(len(self.label_word_candidates)): # clear the content of all word labels
self.label_word_candidates[i].config(text='')
# press mouse left button
def mouse_left_button_press(self, event):
self.cursor_move_position_list.append([event.x, event.y, 0]) # store x, y, segment tag
self.keyboard.key_press(event.x, event.y)
self.gesture_points.clear()
#self.gesture_points.append(Point(event.x, event.y))
# release mouse left button
def mouse_left_button_release(self, event):
previous_x = self.cursor_move_position_list[-1][0]
previous_y = self.cursor_move_position_list[-1][1]
line_tag = self.canvas_keyboard.create_line(previous_x, previous_y, event.x, event.y)
self.cursor_move_position_list.append([event.x, event.y, line_tag])
self.keyboard.key_release(event.x, event.y)
result = self.word_recognizer.recognize(self.gesture_points)
answers = [] # SOLUTION STEP 2: Create answers array to hold values that will be predicted by gesture code below
if len(result) > 0:
for i in range(len(result)):
if i < len(self.label_word_candidates):
self.label_word_candidates[i].config(text=result[i][1])
answers.append(result[i][1]) # SOLUTION STEP 3: Add predicted words to answers array
else:
break
else:
key = self.keyboard.get_key_pressed()
if key == '<--': # remove the final character from the text
length = len(self.text.get("1.0", 'end-1c'))
# print(length)
if length > 0:
self.text.delete("end-2c") # remover the last character
'''
else: # not the delete key ("<--")
characters = self.label_word_candidates[0].cget("text")
characters += self.keyboard.get_key_pressed().lower() # convert to lowercase
self.label_word_candidates[0].config(
text=characters) # only one key was pressed
'''
# SOLUTION STEP 4: Check if the first element in answers array is one of the required words
if answers[0]=="save" or answers[0]=="copy" or answers[0]=="redo" or answers[0]=="undo":
# SOLUTION STEP 5: If yes, then output that word in the message box
messagebox.showinfo(title='Message Box', message=answers[0])
else:
# SOLUTION STEP 6: If no, then output "Not a command" in the message box
messagebox.showinfo(title='Message Box', message="Not a command")
if len(self.cursor_move_position_list) > 1: # delete cursor trajectory
for x in self.cursor_move_position_list[1:]:
self.canvas_keyboard.delete(x[2])
# users drag the mouse cursor on the keyboard while pressing the left button: drawing gestures on the keyboard
def mouse_move_left_button_down(self, event):
previous_x = self.cursor_move_position_list[-1][0]
previous_y = self.cursor_move_position_list[-1][1]
line_tag = self.canvas_keyboard.create_line(previous_x, previous_y, event.x, event.y) # draw a line
self.cursor_move_position_list.append([event.x, event.y, line_tag])
self.keyboard.mouse_move_left_button_down(event.x, event.y)
self.gesture_points.append(Point(event.x, event.y)) # store all cursor movement points
if __name__ == '__main__':
master = tk.Tk()
window_width = 500
window_height = 600
master.geometry(str(window_width) + 'x' + str(window_height)) # master.geometry('500x600')
master.resizable(0, 0) # can not change the size of the window
app = Application(window_width, window_height, master=master)
app.mainloop() # mainloop() tells Python to run the Tkinter event loop. This method listens for events, such as button clicks or keypresses, and blocks any code that comes after it from running until the window it's called on is closed.