Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Adding Tkinter GUI #693

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Jan 22, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
160 changes: 160 additions & 0 deletions gui/vacuum_agent.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
from tkinter import *
import random
import sys
import os.path
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
from agents import *

loc_A, loc_B = (0, 0), (1, 0) # The two locations for the Vacuum world


class Gui(Environment):

"""This GUI environment has two locations, A and B. Each can be Dirty
or Clean. The agent perceives its location and the location's
status."""

def __init__(self, root, height=300, width=380):
super().__init__()
self.status = {loc_A: 'Clean',
loc_B: 'Clean'}
self.root = root
self.height = height
self.width = width
self.canvas = None
self.buttons = []
self.create_canvas()
self.create_buttons()

def thing_classes(self):
"""The list of things which can be used in the environment."""
return [Wall, Dirt, ReflexVacuumAgent, RandomVacuumAgent,
TableDrivenVacuumAgent, ModelBasedVacuumAgent]

def percept(self, agent):
"""Returns the agent's location, and the location status (Dirty/Clean)."""
return (agent.location, self.status[agent.location])

def execute_action(self, agent, action):
"""Change the location status (Dirty/Clean); track performance.
Score 10 for each dirt cleaned; -1 for each move."""
if action == 'Right':
agent.location = loc_B
agent.performance -= 1
elif action == 'Left':
agent.location = loc_A
agent.performance -= 1
elif action == 'Suck':
if self.status[agent.location] == 'Dirty':
if agent.location == loc_A:
self.buttons[0].config(bg='white', activebackground='light grey')
else:
self.buttons[1].config(bg='white', activebackground='light grey')
agent.performance += 10
self.status[agent.location] = 'Clean'

def default_location(self, thing):
"""Agents start in either location at random."""
return random.choice([loc_A, loc_B])

def create_canvas(self):
"""Creates Canvas element in the GUI."""
self.canvas = Canvas(
self.root,
width=self.width,
height=self.height,
background='powder blue')
self.canvas.pack(side='bottom')

def create_buttons(self):
"""Creates the buttons required in the GUI."""
button_left = Button(self.root, height=4, width=12, padx=2, pady=2, bg='white')
button_left.config(command=lambda btn=button_left: self.dirt_switch(btn))
self.buttons.append(button_left)
button_left_window = self.canvas.create_window(130, 200, anchor=N, window=button_left)
button_right = Button(self.root, height=4, width=12, padx=2, pady=2, bg='white')
button_right.config(command=lambda btn=button_right: self.dirt_switch(btn))
self.buttons.append(button_right)
button_right_window = self.canvas.create_window(250, 200, anchor=N, window=button_right)

def dirt_switch(self, button):
"""Gives user the option to put dirt in any tile."""
bg_color = button['bg']
if bg_color == 'saddle brown':
button.config(bg='white', activebackground='light grey')
elif bg_color == 'white':
button.config(bg='saddle brown', activebackground='light goldenrod')

def read_env(self):
"""Reads the current state of the GUI."""
for i, btn in enumerate(self.buttons):
if i == 0:
if btn['bg'] == 'white':
self.status[loc_A] = 'Clean'
else:
self.status[loc_A] = 'Dirty'
else:
if btn['bg'] == 'white':
self.status[loc_B] = 'Clean'
else:
self.status[loc_B] = 'Dirty'

def update_env(self, agent):
"""Updates the GUI according to the agent's action."""
self.read_env()
# print(self.status)
before_step = agent.location
self.step()
# print(self.status)
# print(agent.location)
move_agent(self, agent, before_step)


def create_agent(env, agent):
"""Creates the agent in the GUI and is kept independent of the environment."""
env.add_thing(agent)
# print(agent.location)
if agent.location == (0, 0):
env.agent_rect = env.canvas.create_rectangle(80, 100, 175, 180, fill='lime green')
env.text = env.canvas.create_text(128, 140, font="Helvetica 10 bold italic", text="Agent")
else:
env.agent_rect = env.canvas.create_rectangle(200, 100, 295, 180, fill='lime green')
env.text = env.canvas.create_text(248, 140, font="Helvetica 10 bold italic", text="Agent")


def move_agent(env, agent, before_step):
"""Moves the agent in the GUI when 'next' button is pressed."""
if agent.location == before_step:
pass
else:
if agent.location == (1, 0):
env.canvas.move(env.text, 120, 0)
env.canvas.move(env.agent_rect, 120, 0)
elif agent.location == (0, 0):
env.canvas.move(env.text, -120, 0)
env.canvas.move(env.agent_rect, -120, 0)


# TODO: Add more agents to the environment.
# TODO: Expand the environment to XYEnvironment.
def main():
"""The main function of the program."""
root = Tk()
root.title("Vacuum Environment")
root.geometry("420x380")
root.resizable(0, 0)
frame = Frame(root, bg='black')
# reset_button = Button(frame, text='Reset', height=2, width=6, padx=2, pady=2, command=None)
# reset_button.pack(side='left')
next_button = Button(frame, text='Next', height=2, width=6, padx=2, pady=2)
next_button.pack(side='left')
frame.pack(side='bottom')
env = Gui(root)
agent = ReflexVacuumAgent()
create_agent(env, agent)
next_button.config(command=lambda: env.update_env(agent))
root.mainloop()


if __name__ == "__main__":
main()
178 changes: 178 additions & 0 deletions gui/xy_vacuum_environment.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
from tkinter import *
import random
import sys
import os.path
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
from agents import *


class Gui(VacuumEnvironment):
"""This is a two-dimensional GUI environment. Each location may be
dirty, clean or can have a wall. The user can change these at each step.
"""
xi, yi = (0, 0)

def __init__(self, root, width=7, height=7, elements=['D', 'W']):
super().__init__(width, height)
self.root = root
self.create_frames()
self.create_buttons()
self.create_walls()
self.elements = elements

def create_frames(self):
"""Adds frames to the GUI environment."""
self.frames = []
for _ in range(7):
frame = Frame(self.root, bg='grey')
frame.pack(side='bottom')
self.frames.append(frame)

def create_buttons(self):
"""Adds buttons to the respective frames in the GUI."""
self.buttons = []
for frame in self.frames:
button_row = []
for _ in range(7):
button = Button(frame, height=3, width=5, padx=2, pady=2)
button.config(
command=lambda btn=button: self.display_element(btn))
button.pack(side='left')
button_row.append(button)
self.buttons.append(button_row)

def create_walls(self):
"""Creates the outer boundary walls which do not move."""
for row, button_row in enumerate(self.buttons):
if row == 0 or row == len(self.buttons) - 1:
for button in button_row:
button.config(text='W', state='disabled',
disabledforeground='black')
else:
button_row[0].config(
text='W', state='disabled', disabledforeground='black')
button_row[len(button_row) - 1].config(text='W',
state='disabled', disabledforeground='black')
# Place the agent in the centre of the grid.
self.buttons[3][3].config(
text='A', state='disabled', disabledforeground='black')

def display_element(self, button):
"""Show the things on the GUI."""
txt = button['text']
if txt != 'A':
if txt == 'W':
button.config(text='D')
elif txt == 'D':
button.config(text='')
elif txt == '':
button.config(text='W')

def execute_action(self, agent, action):
"""Determines the action the agent performs."""
xi, yi = ((self.xi, self.yi))
if action == 'Suck':
dirt_list = self.list_things_at(agent.location, Dirt)
if dirt_list != []:
dirt = dirt_list[0]
agent.performance += 100
self.delete_thing(dirt)
self.buttons[xi][yi].config(text='', state='normal')
xf, yf = agent.location
self.buttons[xf][yf].config(
text='A', state='disabled', disabledforeground='black')

else:
agent.bump = False
if action == 'TurnRight':
agent.direction += Direction.R
elif action == 'TurnLeft':
agent.direction += Direction.L
elif action == 'Forward':
agent.bump = self.move_to(agent, agent.direction.move_forward(agent.location))
if not agent.bump:
self.buttons[xi][yi].config(text='', state='normal')
xf, yf = agent.location
self.buttons[xf][yf].config(
text='A', state='disabled', disabledforeground='black')

if action != 'NoOp':
agent.performance -= 1

def read_env(self):
"""Reads the current state of the GUI environment."""
for i, btn_row in enumerate(self.buttons):
for j, btn in enumerate(btn_row):
if (i != 0 and i != len(self.buttons) - 1) and (j != 0 and j != len(btn_row) - 1):
agt_loc = self.agents[0].location
if self.some_things_at((i, j)) and (i, j) != agt_loc:
for thing in self.list_things_at((i, j)):
self.delete_thing(thing)
if btn['text'] == self.elements[0]:
self.add_thing(Dirt(), (i, j))
elif btn['text'] == self.elements[1]:
self.add_thing(Wall(), (i, j))

def update_env(self):
"""Updates the GUI environment according to the current state."""
self.read_env()
agt = self.agents[0]
previous_agent_location = agt.location
self.xi, self.yi = previous_agent_location
self.step()
xf, yf = agt.location


def XYReflexAgentProgram(percept):
"""The modified SimpleReflexAgentProgram for the GUI environment."""
status, bump = percept
if status == 'Dirty':
return 'Suck'

if bump == 'Bump':
value = random.choice((1, 2))
else:
value = random.choice((1, 2, 3, 4)) # 1-right, 2-left, others-forward

if value == 1:
return 'TurnRight'
elif value == 2:
return 'TurnLeft'
else:
return 'Forward'


class XYReflexAgent(Agent):
"""The modified SimpleReflexAgent for the GUI environment."""

def __init__(self, program=None):
super().__init__(program)
self.location = (3, 3)
self.direction = Direction("up")


# TODO: Check the coordinate system.
def main():
"""The main function."""
root = Tk()
root.title("Vacuum Environment")
root.geometry("420x440")
root.resizable(0, 0)
frame = Frame(root, bg='black')
# create a reset button
# reset_button = Button(frame, text='Reset', height=2,
# width=6, padx=2, pady=2, command=None)
# reset_button.pack(side='left')
next_button = Button(frame, text='Next', height=2,
width=6, padx=2, pady=2)
next_button.pack(side='left')
frame.pack(side='bottom')
env = Gui(root)
agt = XYReflexAgent(program=XYReflexAgentProgram)
env.add_thing(agt, location=(3, 3))
next_button.config(command=env.update_env)
root.mainloop()


if __name__ == "__main__":
main()