{ "cells": [ { "cell_type": "markdown", "id": "77eaeea0", "metadata": {}, "source": [ "# basic GUI for billiard ball" ] }, { "cell_type": "markdown", "id": "70dd065c", "metadata": {}, "source": [ "This basic GUI to model a billiard ball consists\n", "of a canvas, a start and stop button." ] }, { "cell_type": "code", "execution_count": 1, "id": "30ac11fe", "metadata": {}, "outputs": [], "source": [ "from tkinter import Tk, Canvas, Button, W, E\n", "from math import cos, sin, pi\n", "from random import randint, uniform" ] }, { "cell_type": "code", "execution_count": 2, "id": "e46e4309", "metadata": {}, "outputs": [], "source": [ "class BilliardBall(object):\n", " \"\"\"\n", " GUI to simulate billiard ball movement.\n", " \"\"\"\n", " def __init__(self, wdw, dimension, increment, delay):\n", " \"\"\"\n", " determines the layout of the GUI\n", " \"\"\"\n", " wdw.title('a pool table')\n", " self.dim = dimension # dimension of the canvas\n", " self.inc = increment\n", " self.dly = delay\n", " self.togo = False # state of animation\n", " # initial coordinates of the ball\n", " self.xpos = randint(10, self.dim-10)\n", " self.ypos = randint(10, self.dim-10)\n", " self.cnv = Canvas(wdw, width=self.dim, \\\n", " height=self.dim, bg ='green')\n", " self.cnv.grid(row=0, column=0, columnspan=2)\n", " self.startbut = Button(wdw, text='start', \\\n", " command = self.start)\n", " self.startbut.grid(row=1, column=0, sticky=W+E)\n", " self.stopbut = Button(wdw, text='stop', \\\n", " command = self.stop)\n", " self.stopbut.grid(row=1, column=1, sticky=W+E)\n", "\n", " def map_to_table(self, pos):\n", " \"\"\"\n", " keeps the ball on the pool table\n", " \"\"\"\n", " if pos < 0:\n", " (quot, remd) = divmod(-pos, self.dim)\n", " else:\n", " (quot, remd) = divmod(pos, self.dim)\n", " if quot % 2 == 1:\n", " remd = self.dim - remd\n", " return remd\n", "\n", " def draw_ball(self):\n", " \"\"\"\n", " draws the ball on the pool table\n", " \"\"\"\n", " xvl = self.map_to_table(self.xpos)\n", " yvl = self.map_to_table(self.ypos)\n", " self.cnv.delete('dot')\n", " self.cnv.create_oval(xvl-6, yvl-6, xvl+6, yvl+6, \\\n", " width=1, outline='black', fill='red', \\\n", " tags='dot')\n", "\n", " def animate(self):\n", " \"\"\"\n", " performs the animation\n", " \"\"\"\n", " self.draw_ball()\n", " angle = uniform(0, 2*pi)\n", " xdir = cos(angle)\n", " ydir = sin(angle)\n", " while self.togo:\n", " xvl = self.xpos\n", " yvl = self.ypos\n", " self.xpos = xvl + xdir*self.inc\n", " self.ypos = yvl + ydir*self.inc\n", " self.cnv.after(self.dly)\n", " self.draw_ball()\n", " self.cnv.update()\n", "\n", " def start(self):\n", " \"\"\"\n", " starts the animation\n", " \"\"\"\n", " self.togo = True\n", " self.animate()\n", "\n", " def stop(self):\n", " \"\"\"\n", " stops the animation\n", " \"\"\"\n", " self.togo = False" ] }, { "cell_type": "markdown", "id": "aca79655", "metadata": {}, "source": [ "The next cell launches the GUI." ] }, { "cell_type": "code", "execution_count": 4, "id": "42ace809", "metadata": {}, "outputs": [], "source": [ "top = Tk()\n", "dimension = 400 # dimension of pool table\n", "dims = \"%dx%d\" % (dimension, dimension)\n", "top.geometry(dims)\n", "increment = 10 # increment for coordinates\n", "delay = 60 # how much sleep before update\n", "BilliardBall(top, dimension, increment, delay)\n", "top.mainloop()" ] }, { "cell_type": "code", "execution_count": null, "id": "a75ecfbd-448b-4cd7-acc0-48395ee56e94", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.10" } }, "nbformat": 4, "nbformat_minor": 5 }