示例#1
1
文件: game.py 项目: Tidaren/ISN
class Game(object):
	"""
	"""
	def __init__(self, wnd, w, h):
		"""
		"""
		Database.init()
		self.hexa_size = 80
		self.width = w
		self.height = h
		self.canvas = Canvas(
			wnd, width=self.width, height=self.height,
			bg='#0080FF', highlightthickness=0, bd=0)
		self.canvas.pack()
		wnd.resizable(False, False)
		self.player = Player(1)
		self.inventory = Inventory()
		self.hexagons = []
		self.defaultBoardArgs = (2, 3, True)

		self.canvas.tag_bind('hexagon', "<Button-1>", self.hexAction)

		# TODO : Remove these tests
		self.player.debug()
		Database.debug_items()
		self.inventory.addItem(0)
		self.inventory.addItem(1)
		self.inventory.addItem(0)
		self.inventory.addItem(2)
		self.inventory.addItem(0)
		self.inventory.debug()
		Database.debug_enemies()

	def hexAction(self, event):
		tmp = self.canvas.find_withtag(CURRENT)
		if tmp:
			id = tmp[0]
			index = self.getHexIndexByID(id)
			if self.hexagons[index].hasTag('Player'):
				print("Action: Open Inventory")
			elif self.hexagons[index].hasTag('Enemy'):
				print("Action: Attack")
			else:
				print("Action: Move")
				movePos = self.hexagons[index].position
				if movePos[0] == 0 and movePos[1] == 0:
					return
				def move(t, nIndex):
					self.hexagons[nIndex].setEntity(t.entity)
					t.unsetEntity()

				move(self.hexagons[self.getPlayerHexIndex()], index)
				doneIDs = []
				def moveUtil(t):
					nPos = [t.position[0] - movePos[0], t.position[1] - movePos[1]]
					if nPos[0] % 2 and not t.position[0] % 2:
						nPos[1] -= 1
					nPos = tuple(nPos)
					nIndex = self.getHexIndexByPosition(nPos)
					if nIndex == -1:
						if not((nPos[0] < t.position[0] and nPos[1] < t.position[0]) or (nPos[0] > t.position[0] and nPos[1] == t.position[1])):
							t.unsetEntity()
						doneIDs.append(t.id)
						return
					if not nIndex in doneIDs:
						moveUtil(self.hexagons[nIndex]) # Bad recursion... but works with small boards
					move(t, nIndex)
					doneIDs.append(t.id)
				for t in self.hexagons:
					if t.id in doneIDs:
						continue
					moveUtil(t)

	def getBoardWidth(self, row=-1):
		return self.defaultBoardArgs[1]

	def getBoardHeight(self, column):
		# This code is a bit tricky
		# Since the board is composed of hexagons
		# The height isn't the same on every row
		# (at least that's how we handled everything)
		# We use the self.defaultBoardArgs
		# Basically, it'll handle the board's form
		# If self.defaultBoardArgs[2] is True, then the first
		# column will have the lowest number
		# of rows, eg. if self.defaultBoardArgs[0] is set to 2
		# then the first column will have 2 rows
		# The other columns have 1 more row
		# The best way to understand is to try it x)
		n = 0
		if column % 2 :
			if self.defaultBoardArgs[2]:
				n = self.defaultBoardArgs[0] + 1
			else:
				n = self.defaultBoardArgs[0]
		else:
			if self.defaultBoardArgs[2]:
				n = self.defaultBoardArgs[0]
			else:
				n = self.defaultBoardArgs[0] + 1
		return n
	
	def keyboard(self, event):
		"""
		Keyboard Pressed
		"""
		#print(event.keysym)
	
	def mouse_b1(self, event):
		"""
		Mouse Left Button Pressed
		"""
		#print(event.x, ";", event.y)

	def getPlayerHexIndex(self):
		for index, t in enumerate(self.hexagons):
			if t.hasTag("Player"):
				return index
		return -1

	def getHexIndexByPosition(self, pos):
		for index, t in enumerate(self.hexagons):
			if t.position[0] == pos[0] and t.position[1] == pos[1]:
				return index
		return -1

	def getHexIndexByID(self, id):
		for index, t in enumerate(self.hexagons):
			if t.id == id:
				return index
		return -1
	
	def draw(self):
		"""
		Draws the whole game, should only be called once
		"""
		self.board_callback(self.draw_board, *self.defaultBoardArgs)

	def board_callback(self, callback, lowest_nb_of_rows = 2, nb_of_columns = 3, lowest_nb_of_rows_first = True, *args):
		"""
		This method calls a callback when a
		tile is supposed to be drawn
		"""
		for i in range(0, nb_of_columns):
			n = self.getBoardHeight(i)
			for j in range(0, n):
				callback(i, j, n, nb_of_columns, lowest_nb_of_rows, *args)
	
	def draw_board(self, i, j, n, nb_of_columns, lowest_nb_of_rows):
		"""
		Draws the game board composed of
		hexagons at the center of the window
		This is supposed to be called by board_callback
		"""
		pos = (i - int(nb_of_columns / 2), j - int(n / 2))
		if pos[0] == 0 and pos[1] == 0:
			self.hexagons.append(
				Tile(self,
					pos,
					-1,
					self.player)
			)
		else:
			self.hexagons.append(
				Tile(self,
					pos,
					-1)
			)
		self.draw_hexa(
			self.width / 2 +
				(i - .5 * nb_of_columns + .5) * self.hexa_size * .75,
			self.height / 2 +
				(j * 2 - lowest_nb_of_rows + 1 - n % lowest_nb_of_rows) *
				self.hexa_size * .375,
			self.hexa_size - 2,
			"red")
	
	def draw_hexa(self, x, y, size, color):
		"""
		Draws an hexagon centered at the given position (x, y)
		"""
		# Only half the size is needed
		# as size is the length of the longest
		# line contained in the hexagon
		# and we are working from the center of it
		size = size / 2
		index = len(self.hexagons) - 1
		self.hexagons[index].id = self.canvas.create_polygon(
				x - size, y,
				x - size / 2, y - size * .75,
				x + size / 2, y - size * .75,
				x + size, y,
				x + size / 2, y + size * .75,
				x - size / 2, y + size * .75,
				fill=color)
		self.hexagons[index].addTag('hexagon')
		self.hexagons[index].addTag()
		self.hexagons[index].drawEntity()
示例#2
0
    def initUI(self):
        self.master.title("Flag of Nepal")
        self.pack(fill=BOTH, expand=1)

        canvas = Canvas(self)


        def SunShape(x, y, r, e, l, b):
            p, a, h=[], 2*pi/e, r*l
            c, d=[0, -a/2][b], [a/2, 0][b]
            for i in range(e):
                p+=[(x+r*cos(i*a+c), y+r*sin(i*a+c)), (x+h*cos(i*a+d), y+h*sin(i*a+d))]
            canvas.create_polygon(p, fill="white")

        #outer polygon with blue color
        canvas.create_polygon((0, 0), (393, 246), (144, 246), (375, k), (0, k), fill="#003893") 
        # inner polygon with red color over blue polygon
        canvas.create_polygon((14, 25), (o, n), (110, n), (o, m), (14, m), fill="#DC143C") 
        #Sun Shape at lower part
        SunShape(96, o, 68, 12, .6, 0) 
        #Semi cricle for the moon
        canvas.create_arc(31, 90, 163, 221, start=-180, extent=l, fill="#ffffff", outline="#ffffff")
        #another smaller semicircle with red color over the provious semicircle to make it small
        canvas.create_arc(28, 68, 166, 200, start=-180, extent=l, fill="#DC143C", outline="#DC143C")
        #Sun shape above the moon semicicle
        SunShape(96, 178, 40, 16, .7, 1) 

        canvas.pack(fill=BOTH, expand=1)
示例#3
0
class HullApp():
    def __init__(self, master):
        """App to construct polygon by successive left-mouse clicks."""

        master.title(
            "Left press to add point to polygon. Right press to start new one."
        )
        self.master = master

        # keep track of points being created
        self.points = []

        self.canvas = Canvas(master, width=512, height=512)
        self.canvas.bind("<Button-1>", self.add)
        self.canvas.bind("<Button-2>", self.clear)
        self.canvas.pack()

    def toCartesian(self, y):
        """Convert tkinter point into Cartesian."""
        return self.canvas.winfo_height() - y

    def toTk(self, y):
        """Convert Cartesian into tkinter point."""
        return self.canvas.winfo_height() - y

    def add(self, event):
        """Add point to polygon and redraw."""
        self.points.append(Point(event.x, self.toCartesian(event.y)))
        self.visit()

    def clear(self, event):
        """Clear all polygons and start again."""
        self.points = []
        self.visit()

    def visit(self):
        """Visit structure and represent graphically."""
        self.canvas.delete(ALL)

        p = computeHull(self.points)
        if p.valid():
            # create single list of (x,y) coordinates
            full = [None] * 2 * p.numEdges()
            idx = 0
            for pt in p:
                full[idx] = pt.x()
                full[idx + 1] = self.toTk(pt.y())
                idx += 2
                self.canvas.create_polygon(full, fill='lightGreen')

        # show points in gray
        for pt in self.points:
            self.canvas.create_oval(pt.x() - 4,
                                    self.toTk(pt.y() - 4),
                                    pt.x() + 4,
                                    self.toTk(pt.y() + 4),
                                    fill='gray')
 def create_line(self, points):
     global canvas, line_color, lines, maze_size
     if canvas == "":
         canvas = Canvas(self)
     lines.append([points[2], points[3]])
     canvas.create_polygon(points,
                           fill="",
                           outline=line_color,
                           width=maze_size / of_map)
示例#5
0
    def initUI(self):
        self.master.title("Lines")
        self.pack(fill=BOTH, expand=1)
        canvas = Canvas(self)
        canvas.create_polygon(self.tupleOfTops, outline=self.outline_colour,
                              fill=self.fill_color, width=2)
        # canvas.create_line(self.tupleOfTops)

        canvas.pack(fill=BOTH, expand=1)
示例#6
0
def main():
    from tkinter import Canvas, mainloop, Tk
    gamma, size = [0.3, 0.2, -0.1, -0.4, 0.0], 11
    width, height, scale, center = 800, 800, 20, 400+400j
    w = Canvas(Tk(), width=width, height=height)
    w.pack()
    for rhombus, color in tiling(gamma, size):
        coords = to_canvas(rhombus, scale, center)
        w.create_polygon(*coords, fill=color, outline="black")
    mainloop()
示例#7
0
def render(canvas: tkinter.Canvas, polygons: List[List[int]], outline: str,
           dist: int, height: int, width: int):
    canvas.delete(tkinter.ALL)
    polygons = sorted(polygons, key=priority, reverse=True)
    for polygon in polygons:
        points = []
        for point in polygon:
            points.append(project(point, dist, height, width))
        canvas.create_polygon(points, fill=background, outline=outline)
    canvas.pack()
示例#8
0
class Canvas3D(Frame):
    def __init__(self):
        super().__init__()
        self.shape_dict = {}
        self.canvas = Canvas(self)
        self.initUI()

    def initUI(self):
        self.master.title("Lines")
        self.pack(fill=BOTH, expand=1)
        self.canvas.pack(fill=BOTH, expand=1)
        self.canvas.create_polygon()
    def initUI(self):

        self.master.title("Shapes")
        self.pack(fill=BOTH, expand=1)

        canvas = Canvas(self)
        canvas.create_oval(10, 10, 80, 80, outline="#f11",fill="#1f1", width=2)
        canvas.create_oval(110, 10, 210, 80, outline="#f11",fill="#1f1", width=2)
        canvas.create_rectangle(230, 10, 290, 60, outline="#f11", fill="#1f1", width=2)
        canvas.create_arc(30, 200, 90, 100, start=0, extent=210, outline="#f11", fill="#1f1", width=2)
        points = [150, 100, 200, 120, 240, 180, 210,200, 150, 150, 100, 200]
        canvas.create_polygon(points, outline='#f11',fill='#1f1', width=2)
        canvas.pack(fill=BOTH, expand=1)
class PolygonApp():
    def __init__(self, master):
        """App to construct polygon by successive left-mouse clicks."""

        master.title(
            "Left press to add point to polygon. Right press to start new one."
        )
        self.master = master

        # keep track of polygons being created
        self.polygons = [Polygon()]

        self.canvas = Canvas(master, width=512, height=512)
        self.canvas.bind("<Button-1>", self.add)
        self.canvas.bind("<Button-2>", self.finalize)
        self.canvas.pack()

    def add(self, event):
        """Add point to polygon and redraw."""
        self.polygons[0].add(event.x, event.y)
        self.visit()

    def finalize(self, event):
        """Finalize polygon and add a new one."""
        self.polygons.insert(0, Polygon())
        self.visit()

    def visit(self):
        """Visit structure and represent graphically."""
        self.canvas.delete(ALL)
        c = len(self.polygons) - 1
        for p in self.polygons:
            if p.valid():
                # create single list of (x,y) coordinates
                full = [None] * 2 * p.numEdges()
                idx = 0
                for pt in p:
                    full[idx] = pt.x()
                    full[idx + 1] = pt.y()
                    idx += 2
                self.canvas.create_polygon(full, fill=color(c))
            else:
                for pt in p:
                    self.canvas.create_oval(pt.x() - 4,
                                            pt.y() - 4,
                                            pt.x() + 4,
                                            pt.y() + 4,
                                            fill='gray')
            c -= 1
示例#11
0
def draw_rect(canvas:tk.Canvas, position:dim2.Vector, size:dim2.Vector, angle:float=0, **kwargs):
    width, height = size.as_tuple
    width = max(2, width)
    height = max(2, height)
    points = list(map(
        lambda x: (position + x).as_tuple,
        rotate((
            (-width/2, -height/2),
            ( width/2, -height/2),
            ( width/2,  height/2),
            (-width/2,  height/2),
        ), angle)
    ))

    canvas.create_polygon(points, **kwargs)
示例#12
0
def round_rectangle(canvas_obj: tk.Canvas,
                    paddingx,
                    paddingy,
                    rectangle_width,
                    rectangle_height,
                    radius=25,
                    **kwargs):
    """
    :param canvas_obj:
    :param paddingx:
    :param paddingy:
    :param rectangle_width:
    :param rectangle_height:
    :param radius:
    :param kwargs:
    """
    points = [
        paddingx + radius, paddingy, paddingx + radius, paddingy,
        rectangle_width - radius, paddingy, rectangle_width - radius, paddingy,
        rectangle_width, paddingy, rectangle_width, paddingy + radius,
        rectangle_width, paddingy + radius, rectangle_width, rectangle_height -
        radius, rectangle_width, rectangle_height - radius, rectangle_width,
        rectangle_height, rectangle_width - radius, rectangle_height,
        rectangle_width - radius, rectangle_height, paddingx + radius,
        rectangle_height, paddingx + radius, rectangle_height, paddingx,
        rectangle_height, paddingx, rectangle_height - radius, paddingx,
        rectangle_height - radius, paddingx, paddingy + radius, paddingx,
        paddingy + radius, paddingx, paddingy
    ]

    return canvas_obj.create_polygon(points, **kwargs, smooth=True)
    def _draw_triangle(tri: Triangle, window: Canvas) -> None:
        """
        Draw triangle to screen

        :param tri: Triangle to be drawn
        """
        points = [
            tri.p[0].x, tri.p[0].y, tri.p[1].x, tri.p[1].y, tri.p[2].x,
            tri.p[2].y
        ]
        shade_of_triangle = Renderer._calculate_shade_of_triangle(tri)

        # With wireframe
        # window.create_polygon(points, outline="red", fill=shade_of_triangle.to_hex())

        window.create_polygon(points, fill=shade_of_triangle.to_hex())
 def draw(self, canvas: Canvas):
     h = 2 * self.area() / self.a
     x0 = 15
     y0 = 15 + h
     x1 = x0 + self.a
     y1 = y0
     x2 = x1 - self.b * math.sqrt(1 - (h / self.b)**2)
     y2 = y0 - h
     canvas.create_polygon(x0,
                           y0,
                           x1,
                           y1,
                           x2,
                           y2,
                           fill='white',
                           outline='black')
示例#15
0
class TkCanvas:
    _board = None
    _parent = None
    _name_id = ""

    def __init__(self, parent, name_id, options=None):
        if options is None:
            options = {}
        self._board = Canvas(parent.getWindow(), options)
        self._parent = parent
        self._name_id = name_id
        self._parent.newCanvas(name_id, self._board)

    def getBoard(self):
        return self._board

    # OBJECTS ----------------------------------------------------------------------

    def arc(self, coords, options={}):
        return self._board.create_arc(coords, options)

    def oval(self, coords, options={}):
        return self._board.create_oval(coords, options)

    def polygon(self, coords, options={}):
        return self._board.create_polygon(coords, options)

    def line(self, coords, options={}):
        return self._board.create_line(coords, options)

    def text(self, x1, y1, text, options={}):
        options["text"] = text
        return self._board.create_text(x1, y1, options)
示例#16
0
    def draw(self, camera: Vec3D, viewer: Vec3D, canvas: tkinter.Canvas,
             width: int, height: int) -> List[int]:
        points = self.points
        colors = self.colors
        hw = width // 2
        hh = height // 2

        a = camera[0]
        b = camera[1]
        c = camera[2]

        faces = [[0, 2, 4, 6], [0, 14, 8, 6], [0, 2, 12, 14], [4, 10, 8, 6],
                 [2, 4, 10, 12], [10, 12, 14, 8]]

        face_indices = [0, 1, 2, 3, 4, 5]

        distances = [0] * 8
        distances[0] = ((a - points[0])**2 + (b - points[1])**2 +
                        (c - points[2])**2)**0.5
        distances[1] = ((a - points[3])**2 + (b - points[4])**2 +
                        (c - points[5])**2)**0.5
        distances[2] = ((a - points[6])**2 + (b - points[7])**2 +
                        (c - points[8])**2)**0.5
        distances[3] = ((a - points[9])**2 + (b - points[10])**2 +
                        (c - points[11])**2)**0.5
        distances[4] = ((a - points[12])**2 + (b - points[13])**2 +
                        (c - points[14])**2)**0.5
        distances[5] = ((a - points[15])**2 + (b - points[16])**2 +
                        (c - points[17])**2)**0.5
        distances[6] = ((a - points[18])**2 + (b - points[19])**2 +
                        (c - points[20])**2)**0.5
        distances[7] = ((a - points[21])**2 + (b - points[22])**2 +
                        (c - points[23])**2)**0.5

        def key(i):
            return (distances[faces[i][0] // 2] + distances[faces[i][1] // 2] +
                    distances[faces[i][2] // 2] +
                    distances[faces[i][3] // 2]) / 4

        # sort the faces of the cube by the average distance of their vertices from the camera.
        # those furthest from the camera are drawn first, which is why reverse=True.
        face_indices.sort(key=key, reverse=True)

        ppoints = self.apply_perspective(camera, viewer)

        polygons = [0] * 6
        for i in face_indices:
            color = colors[i]
            face = faces[i]
            polygons[i] = canvas.create_polygon(hw + ppoints[face[0]],
                                                hh - ppoints[face[0] + 1],
                                                hw + ppoints[face[1]],
                                                hh - ppoints[face[1] + 1],
                                                hw + ppoints[face[2]],
                                                hh - ppoints[face[2] + 1],
                                                hw + ppoints[face[3]],
                                                hh - ppoints[face[3] + 1],
                                                fill=color)
        return polygons
示例#17
0
 def draw(self, canvas: Canvas):
     if self.drawn is not None:
         canvas.coords(self.drawn, self.get_location()[2:])
     else:
         self.drawn = canvas.create_polygon(self.get_location()[2:],
                                            fill=self.fill,
                                            outline=self.color,
                                            width=self.width)
示例#18
0
 def draw(self, canvas: Canvas):
     if self.is_drawn():
         canvas.coords(self.drawn, self.get_location())
     else:
         self.drawn = canvas.create_polygon(self.get_location(),
                                            fill=self.fill,
                                            outline=self.color,
                                            width=self.width)
示例#19
0
文件: setup.py 项目: decitre/pykbool
def demo1():
    try:
        
        if sys.version_info[0] == 3:
            from tkinter import Tk, Canvas, PhotoImage, NW, SW
        else:
            from Tkinter import Tk, Canvas, PhotoImage, NW, SW
    except ImportError:
        Tk = Canvas = None      

    if Tk: 
        from pykbool import connect
        
        contour = [(491.1025968497233, 19.886736214605065), (491.1025968497233, 5.524093392945851), (455.34269902086, 5.524093392945851), (455.34269902086, 19.886736214605065), (353.68241805023416, 17.677098857426728), (353.68241805023416, 8.838549428713364), (323.20136228182207, 8.838549428713364), (323.20136228182207, 17.677098857426728), (210.81311196253725, 14.362642821659207), (210.81311196253725, 3.3144560357675132), (175.05321413367392, 3.3144560357675132), (175.05321413367392, 14.362642821659207), (73.22264793529162, 14.362642821659207), (73.22264793529162, 10.0), (34.05704555129843, 10.0), (32.18390804597701, 110.48186785891704), (10.0, 110.48186785891704), (10.0, 162.40834575260803), (48.36100468284376, 156.88425235966218), (75.09578544061303, 156.88425235966218), (128.56534695615156, 162.40834575260803), (178.62920391656024, 176.77098857426725), (226.81992337164752, 196.65772478887232), (249.9787143465304, 211.02036761053148), (291.18773946360153, 246.374565325385), (328.65048957002983, 283.9384003974168), (337.5053214133674, 298.30104321907595), (337.5053214133674, 341.3889716840536), (448.1907194550873, 350.22752111276696), (448.1907194550873, 333.6552409339294), (685.7386121753938, 350.22752111276696), (683.8654746700724, 356.856433184302), (771.3920817369094, 364.5901639344262), (774.9680715197957, 318.18777943368104), (767.816091954023, 318.18777943368104), (789.272030651341, 60.765027322404364), (796.4240102171137, 60.765027322404364), (800.0, 8.838549428713364), (757.088122605364, 8.838549428713364), (757.088122605364, 23.20119225037257), (644.6998722860792, 19.886736214605065), (644.6998722860792, 8.838549428713364), (610.8131119625373, 5.524093392945851), (608.9399744572158, 19.886736214605065)]
        holea = [(162.62239250744997, 127.0541480377546), (189.35717326521925, 135.89269746646795), (239.42103022562793, 159.09388971684052), (287.6117496807152, 187.81917536015894), (308.8974031502767, 205.49627421758566), (348.2332907620264, 246.374565325385), (366.1132396764581, 266.26130153999003), (389.272030651341, 301.6154992548435), (450.0638569604087, 307.13959264778936), (451.7667092379736, 57.45057128663686), (355.38527032779905, 55.24093392945852), (355.38527032779905, 66.28912071535022), (323.20136228182207, 66.28912071535022), (323.20136228182207, 55.24093392945852), (210.81311196253725, 55.24093392945852), (210.81311196253725, 60.765027322404364), (173.35036185610898, 60.765027322404364), (173.35036185610898, 55.24093392945852), (73.22264793529162, 51.926477893691), (71.51979565772669, 116.00596125186286), (107.27969348659005, 119.32041728763039)]
        holeb = [(749.9361430395913, 60.765027322404364), (498.254576415496, 57.45057128663686), (494.67858663260967, 294.9865871833085), (566.0280970625798, 301.6154992548435), (566.0280970625798, 292.77694982613014), (591.0600255427842, 292.77694982613014), (589.3571732652192, 303.8251366120218), (730.3533418475947, 315.9781420765027)]
          
        connected_polygon = connect([contour, holea, holeb])

        root = Tk()
        root.title(string='connect holes to contour / fill resulting polygon')
        canvas1 = Canvas(root, width=900, height=415, background='white')
        canvas1.pack()

        canvas1.create_polygon(contour, outline='blue', fill='')
        canvas1.create_text(contour[0], text='C(1)')
        canvas1.create_text(contour[20], text='C(i)')
        canvas1.create_text(contour[-1], text='C(n)')

        canvas1.create_polygon(holea, outline='red', fill='')
        canvas1.create_text(holea[0], text='H1(1)')
        canvas1.create_text(holea[9], text='H1(i)')
        canvas1.create_text(holea[-1], text='H1(n)')

        canvas1.create_polygon(holeb, outline='green', fill='')
        canvas1.create_text(holeb[0], text='H2(1)')
        canvas1.create_text(holeb[2], text='H2(i)')
        canvas1.create_text(holeb[-1], text='H2(n)')
        
        canvas1.create_text((10, 350), text='# More info in setup.py\n'
            'from pykbool import connect\n'
            'contour=[(... , ...) ... ]; hole1=[(... , ...) ... ]; hole2=...\n'
            'polygon=connect([contour, hole1, hole2, ...])', anchor=SW)
        
        canvas2 = Canvas(root, width=900, height=415, background='white')
        canvas2.pack()
        image=PhotoImage(file=os.path.join('data','demo.gif'))
        canvas2.create_image((0,0), image=image, anchor=NW)
        canvas2.image=image
        canvas2.create_polygon(connected_polygon, outline='black', fill='grey')
        canvas2.create_text(connected_polygon[0], text='P1')
        canvas2.create_text(connected_polygon[62], text='Pi')
        canvas2.create_text(connected_polygon[-1], text='Pn')

        root.mainloop()
示例#20
0
文件: test.py 项目: izag/beeg
def test_transparancy():
    global root

    img_background = ImageTk.PhotoImage(file="assets/rec1.png")
    img_record = ImageTk.PhotoImage(file="assets/rec2.png")
    img_bee = Image.open("assets/girl.jpg")
    # img_rec = Image.open("assets/rec3.gif")
    # img_canbe = Image.open("assets/canbebought.jpg")

    maxwidth = 200
    maxheight = 120
    img = fit_image(img_bee, maxwidth, maxheight)
    # img_rec = fit_image(img_rec, maxwidth, maxheight)

    width, height = img.size
    root.geometry('{}x{}'.format(width, height))
    root.overrideredirect(True)

    # Label(root, compound=N, image=background_img).place(x=0, y=0, relwidth=1, relheight=1)
    #
    # # background.image = background_img  # keep a reference!
    # Label(root, image=scanbtn_img).pack()

    canvas = Canvas(root,
                    width=width,
                    height=height,
                    bd=0,
                    highlightthickness=0)

    x_center = width // 2
    y_center = height // 2
    photo_img = ImageTk.PhotoImage(img)
    canvas.create_image(x_center, y_center, image=photo_img)
    # image_id = canvas.create_image(50, 50, image=img_record)

    # id_red_circle = canvas.create_oval(width - 30, 10, width - 10, 30, fill='red')
    id_red_frame = canvas.create_polygon(5,
                                         5,
                                         width - 5,
                                         5,
                                         width - 5,
                                         height - 5,
                                         5,
                                         height - 5,
                                         outline='red',
                                         width=10,
                                         fill='')

    # photo_img_rec = ImageTk.PhotoImage(img_rec, format="gif -index 3")
    # canvas.create_image(x_center, y_center, image=photo_img_rec)

    # canvas.move(image_id, 245, 100)

    canvas.pack()

    root.after(333, blink, canvas, id_red_frame)
    root.mainloop()
示例#21
0
def Animation(canvas: Canvas):
    global target

    canvas.delete('all')
    SetPage(3)
    try:
        canvas.delete(target)
    except:
        pass

    canvas.create_text(960, 50, text='Анимация', font='JetBrainsMono 40')

    canvas.create_rectangle(365, 770, 1925, 910)
    canvas.create_rectangle(365, 780, 315, 797)
    Button(canvas, 1780, 845, 100, 50, text='Старт', font='JetBrainsMono 15')
    canvas.create_polygon(316, 753, 343, 767, 310, 812, 284, 798, fill='black')

    # Подсказка про выход в меню
    canvas.create_text(960, 1055, text='Для выхода в меню нажмите Esc', font='JetBrainsMono 15')
示例#22
0
def round_rectangle(x1, y1, x2, y2, radius=25, **kwargs):

    points = [
        x1 + radius, y1, x1 + radius, y1, x2 - radius, y1, x2 - radius, y1, x2,
        y1, x2, y1 + radius, x2, y1 + radius, x2, y2 - radius, x2, y2 - radius,
        x2, y2, x2 - radius, y2, x2 - radius, y2, x1 + radius, y2, x1 + radius,
        y2, x1, y2, x1, y2 - radius, x1, y2 - radius, x1, y1 + radius, x1,
        y1 + radius, x1, y1
    ]

    return Canvas.create_polygon(points, **kwargs, smooth=True)
示例#23
0
    def initUI(self):

        self.parent.title("Shapes")
        self.pack(fill=BOTH, expand=1)

        canvas = Canvas(self)
        canvas.create_oval(10,
                           10,
                           80,
                           80,
                           outline="white",
                           fill="red",
                           width=2)
        canvas.create_oval(110,
                           10,
                           210,
                           80,
                           outline="yellow",
                           fill="blue",
                           width=2)
        canvas.create_rectangle(230,
                                10,
                                290,
                                60,
                                outline="green",
                                fill="brown",
                                width=2)
        canvas.create_arc(30,
                          200,
                          90,
                          100,
                          start=0,
                          extent=210,
                          outline="purple",
                          fill="pink",
                          width=2)

        points = [150, 100, 200, 120, 240, 180, 210, 200, 150, 150, 100, 200]
        canvas.create_polygon(points, outline='black', fill='orange', width=2)

        canvas.pack(fill=BOTH, expand=1)
示例#24
0
文件: dice.py 项目: sn1cka/ZONK
 def draw(self, canvas: Canvas, value):
     canvas.create_polygon(self.a[0],
                           self.a[1],
                           self.b[0],
                           self.b[1],
                           self.d[0],
                           self.d[1],
                           self.c[0],
                           self.c[1],
                           fill=Colors.BLACK)
     if value == 1 or value == 3 or value == 5:
         self.__draw_point(canvas, self.center_dot)
     if value == 2 or value == 3 or value == 5 or value == 4 or value == 6:
         self.__draw_point(canvas, self.left_top_dot)
         self.__draw_point(canvas, self.right_bottom_dot)
     if value == 4 or value == 5 or value == 6:
         self.__draw_point(canvas, self.right_top_dot)
         self.__draw_point(canvas, self.lef_bottom_dot)
     if value == 6:
         self.__draw_point(canvas, self.center_left_dot)
         self.__draw_point(canvas, self.center_right_dot)
    def init_maze(self):
        global maze_size, canvas, background_color

        self.master.title("Maze generator")
        self.master.attributes("-topmost", True)
        self.master.resizable(False, False)
        self.pack(fill=BOTH, expand=1)

        self.master.geometry(str(maze_size) + 'x' +
                             str(maze_size))  # for the size of the window

        # convas to hold the 3d renders
        if canvas == "":
            canvas = Canvas(self)
        canvas.pack(fill=BOTH, expand=1)

        canvas.create_polygon([
            0, 0, 0, maze_size, 0, maze_size, maze_size, maze_size, maze_size,
            maze_size, maze_size, 0, maze_size, 0, 0, 0
        ],
                              fill=background_color)
        self.generate()
示例#26
0
    def inicializar_gui(self):
        canvas = Canvas(self.master,
                        width=50,
                        height=50,
                        bd=0,
                        highlightthickness=0)

        canvas.create_polygon(0, 0, 1, 1, 2, 2, fill='blue', tags='flecha')
        canvas.create_line(0, 0, 1, 1, 2, 2, 0, 0, fill='black', tags='linea')

        self.escala = Scale(self.master,
                            orient=VERTICAL,
                            length=285,
                            from_=0,
                            to=250,
                            tickinterval=50,
                            command=lambda h, c=canvas: establecerAltura(c, h))

        self.escala.grid(row=0, column=0, sticky='NE')
        canvas.grid(row=0, column=1, sticky='NWSE')

        self.escala.set(100)
示例#27
0
def init_substitute_players(parent, column, ui_team: UITeam):
    if ui_team.players is None:
        ui_team.players = Frame(parent)
        ui_team.players.grid(column=column + 1, row=1, sticky=N)

    team = get_team_by_name(ui_team.name.get())
    player_color = team.player_uniform_color
    goalie_color = team.goalie_uniform_color
    col = 0
    row = 0
    index = 0
    for player in ui_team.substitute_players:
        player.canvas.grid_forget()
    ui_team.substitute_players.clear()
    for player_id, player in team.players.items():
        shirt_number = player.shirt_number
        position = player.position
        last_name = player.last_name
        canvas_player = Canvas(ui_team.players, width=80, height=90)
        polygon_color = goalie_color if position == 'goalie' else player_color
        font_color = '#fff' if is_polygon_dark(polygon_color) else '#000'
        player_canvas_id = canvas_player.create_polygon(
            resources['shirt_path'], outline='#000', fill=polygon_color)
        canvas_player.create_text(35,
                                  30,
                                  fill=font_color,
                                  font='Times 20 bold',
                                  text=shirt_number)
        canvas_player.create_text(35,
                                  50,
                                  fill=font_color,
                                  font='Times 8',
                                  text=last_name)
        canvas_player.create_text(35,
                                  70,
                                  fill='#000',
                                  font='Times 8',
                                  text=position)
        canvas_player.bind(
            '<Button-1>',
            lambda event, arg=index: ui_team.select_player(False, arg))
        canvas_player.grid(column=col, row=row)
        ui_team.substitute_players.append(
            SubstitutePlayer(canvas_player, player_canvas_id, player_id,
                             shirt_number, last_name))
        row += 1
        index += 1
        if row > 8:
            row = 0
            col += 1
示例#28
0
    def _draw_plus(cls, canvas: tk.Canvas, range_: range_.PlusRange, position,
                   cell_size, *args, **kwargs):
        x, y = position
        o = range_.outer_radius * cell_size
        i = range_.inner_radius * cell_size

        # Could derive a formula, but cbf
        coords = [(-o, i), (-i, i), (-i, o), (i, o), (i, i), (o, i), (o, -i),
                  (i, -i), (i, -o), (-i, -o), (-i, -i), (-o, -i)]

        coords.append(coords[0])

        coords = [(x + dx, y + dy) for dx, dy in coords]

        return [canvas.create_polygon(coords, tag='range', fill='')]
示例#29
0
文件: setup.py 项目: decitre/pykbool
def demo2():
    try:
        if sys.version_info[0] == 3:
            from tkinter import Tk, Canvas
        else:
            from Tkinter import Tk, Canvas
    except ImportError:
        Tk = Canvas = None

    if Tk:
        from pykbool import connect
        import json, gzip

        with gzip.open(os.path.join('data', 'poly.json.gz'), 'r') as f:
            contour, holes = json.loads(f.readline().decode())

        try:
            connected = connect([contour] + holes)

            root1 = Tk()
            root1.title(
                string='not connected - contour (%d points) + holes (%d points)'
                % (len(contour), sum(map(len, holes))))
            canvas1 = Canvas(root1, width=810, height=510, background='white')
            canvas1.pack()
            canvas1.create_polygon(contour, outline='blue', fill='')
            for hole in holes:
                canvas1.create_polygon(hole, outline='red', fill='')

            root2 = Tk()
            root2.title(string='connected - keyhole polygon (%d points)' %
                        (len(connected)))
            canvas2 = Canvas(
                root2,
                width=810,
                height=510,
                background='white',
            )
            canvas2.pack()

            canvas2.create_polygon(connected,
                                   outline='black',
                                   fill='#98BAD3',
                                   dash=(4, ))

            canvas2.create_text(connected[0], text='P1', fill='red')
            canvas2.create_text(connected[int(len(connected) * 0.5)],
                                text='Pi',
                                fill='red')
            canvas2.create_text(connected[int(len(connected) * 2 / 3)],
                                text='Pj',
                                fill='red')

            root1.mainloop()
        except:
            traceback.print_exc()
示例#30
0
    def _draw_plus(cls, canvas: tk.Canvas, range_: PlusRange, position,
                   cell_size):
        """Draws a plus range"""
        x, y = position
        # pylint: disable=invalid-name
        o = range_.outer_radius * cell_size
        i = range_.inner_radius * cell_size

        # Could derive a formula, but cbf
        coords = [(-o, i), (-i, i), (-i, o), (i, o), (i, i), (o, i), (o, -i),
                  (i, -i), (i, -o), (-i, -o), (-i, -i), (-o, -i)]

        coords.append(coords[0])

        coords = [(x + dx, y + dy) for dx, dy in coords]

        return [canvas.create_polygon(coords, tag='range', fill='')]
示例#31
0
    def createButton(self, btn: int, coords: tuple[int]) -> Canvas:
        def hoverEvent(clr: str):
            cnv.itemconfigure(tagOrId=cir, outline=clr)
            cnv.itemconfigure(tagOrId=poly, outline=clr, fill=clr)

        cnv = Canvas(master=self, height=BTN_SIZE, width=BTN_SIZE)
        # create outline
        cir: int = cnv.create_oval(0,
                                   0,
                                   BTN_SIZE - 1,
                                   BTN_SIZE - 1,
                                   outline=CLR_BTNS)
        # create symbol
        poly: int = cnv.create_polygon(*coords,
                                       outline=CLR_BTNS,
                                       fill=CLR_BTNS)
        # bind hover/click
        cnv.bind(sequence='<Enter>', func=lambda _: hoverEvent(CLR_BTN_HOVER))
        cnv.bind(sequence='<Leave>', func=lambda _: hoverEvent(CLR_BTNS))
        cnv.bind(sequence='<ButtonRelease-1>',
                 func=lambda e, b=btn: self.sendInput(e, b))
        # place the canvas
        cnv.grid(column=[0, 2, 2, 4][btn], row=0)
        return cnv
示例#32
0
文件: setup.py 项目: decitre/pykbool
def demo2():
    try:
        if sys.version_info[0] == 3:
            from tkinter import Tk, Canvas
        else:
            from Tkinter import Tk, Canvas
    except ImportError:
        Tk = Canvas = None      

    if Tk: 
        from pykbool import connect
        import json, gzip
        
        with gzip.open(os.path.join('data','poly.json.gz'), 'r') as f:
            contour, holes = json.loads(f.readline().decode())
        
        try:
            connected = connect([contour]+holes)

            root1 = Tk()
            root1.title(string='not connected - contour (%d points) + holes (%d points)'%(len(contour), sum(map(len, holes))))
            canvas1 = Canvas(root1, width=810, height=510, background='white')
            canvas1.pack()
            canvas1.create_polygon(contour, outline='blue', fill='')
            for hole in holes:
                canvas1.create_polygon(hole, outline='red', fill='')

            root2 = Tk()
            root2.title(string='connected - keyhole polygon (%d points)' %(len(connected)))
            canvas2 = Canvas(root2, width=810, height=510, background='white',)
            canvas2.pack()

            canvas2.create_polygon(connected, outline='black', fill='#98BAD3', dash=(4,))

            canvas2.create_text(connected[0], text='P1', fill='red')
            canvas2.create_text(connected[int(len(connected)*0.5)], text='Pi', fill='red')
            canvas2.create_text(connected[int(len(connected)*2/3)], text='Pj', fill='red')

            root1.mainloop()
        except:
            traceback.print_exc()
示例#33
0
class prgCanvas(Frame):
    def __init__(self,window=None,height=500,width=500,bg="grey"):
        Frame.__init__(self,window,height=height,width=width,bg=bg)
        self.canvas = Canvas(self, bg=bg, height=height, width=width)
        self.flagDescription = False
        self.setdefault(mashtab=True,reper=True,normalization=True)
        self.canvas.pack(expand='y',fill="both")
        self.field = None #данные, блоки групп, графические примитивы, точки, #графические примитивы, надписи
        self.fileprogram = None #имя файла для загрузки

        self.filter = None #фильтр, по которому определяется выделенный фрагмент

    def setdefault(self,mashtab=False,reper=False,normalization=False):
        if mashtab:
            self.mashtab = 1.00 #масштаб
        if reper:
            self.reper = [10.00,10.00] #смещение
        if normalization:
            self.normalization = [0.00,0.00] #коэффициент для нормализации координат
        
    def configure(self,file=None,filter= None):
        if file!=None:
            self.fileprogram = file
        self.filter=filter

    def setMashtab(self):
        '''Эта функция устанавливает текущий масштаб, так чтобы вся плата была в зоне видимости'''
        def findcoord(field):
            mX,mY = field[0][0],field[0][1]
            # sX,sY = field[0][0],field[0][1]
            sX,sY = 0, 0
            for c in field:
                if c[0]<sX: sX = c[0]
                elif c[0]>mX: mX = c[0]
                if c[1]<sY: sY = c[1]
                elif c[1]>mY: mY = c[1]
            return [sX,sY,mX,mY]
        sX,sY,mX,mY=findcoord(self.field)
        lX = int(self.canvas["width"])
        lY = int(self.canvas["height"])
        lengthX = abs(mX-sX)
        lengthY = abs(mY-sY)
        if lengthX>0 and lengthY>0:
            cX = lX/lengthX
            cY = lY/lengthY
        else:
            cX,cY=1.0,1.0
        print("MSH",cX,cY)
        
        self.normalization = [abs(sX),abs(sY)]
        self.mashtab = int(min(cX,cY)*0.9)
    
    def transform(self,x,y,a,etalon):
        """
        точка отсчета - в центре эталона
        """
        new = list()
        for item in etalon:
            ca = cos(a)
            sa = sin(a)
            x2,y2 = item[0]-x, item[1]-y
            
            new.append([x2*ca + y2*sa+x, x2*sa - y2*ca+y])
        return new
        
    def genfield(self):
        x,y,d=0,1,2
        
        self.canvas.delete("all")

        for c in self.field:
            cx = (c[x]+self.normalization[x])*self.mashtab+self.reper[x]
            cy = (c[y]+self.normalization[y])*self.mashtab+self.reper[y]

            print("filter",self.filter)
            
            if self.flagDescription and self.filter==None:
                tag = "BLACK"
                _color1,_color2 = "black","black"
                font = "Verdana 8"
                self.canvas.create_text(cx,cy,anchor="nw",text=str(c[d][1]), fill=_color1,font=font,tag=("DESC",tag))
            elif (not self.flagDescription) and self.filter==None:
                tag = "BLACK"
                _color1,_color2 = "black","black"
            elif self.flagDescription and self.filter!=None and self.filter(c[d][2]):
                _color1,_color2 = ["red","red"]
                tag = "RED"
                font = "Verdana 10 bold"
                self.canvas.create_text(cx,cy,anchor="nw",text=str(c[d][1]), fill=_color1,font=font,tag=("DESC",tag))
            elif self.flagDescription:
                _color1,_color2 = "black","black"
                tag = "BLACK"
                # font = "Verdana 8"
                # self.canvas.create_text(cx,cy,anchor="nw",text=str(c[d][1]), fill=_color1,font=font,tag=("DESC",tag))
                pass
                
            # здесь может быть выбор фигуры
            # здесь может быть угол поворота
            print("c",c)
            if c[-2][0]=="25":
                angle = radians(c[-1])
                pattern = [[-3,-5.0],[3,-5.0],[0.0,3.0],[-3.0,-5.0]]
                et = [[cx+item[0],cy+item[1]] for item in pattern]
                new = self.transform(cx,cy,angle,et)
                self.canvas.create_polygon(new,activefill="white",fill=_color2,tag=("FIG",tag))
            else:
                self.canvas.create_rectangle(cx-1,cy-1,cx+1,cy+1,outline=_color1,fill=_color2,tag=("FIG",tag))
        self.canvas.tag_lower("RED")
        
    def move(self,x,y):
        #в группы
        self.reper[0]+=x
        self.reper[1]+=y
        self.canvas.move("FIG",x,y)
        self.canvas.move("DESC",x,y)

    def load(self):
        _p = prg(self.fileprogram)
        _p.download()
        _p.extract()
        #вариант кода для загрузки информации о установке
        self.field = [x[1:4]+[x[0]] for x in _p.progdigit if ("25" in x[3]) or ("107" in x[3])]
        print(_p.progdigit)
        #вариант кода для загрузки информации о дозировании:
        # self.field.group = [x[1:4] for x in _p.progdigit if "107" in x[3]]
        # print(self.field)

    def paint(self):
        self.load()
        try:
            self.setMashtab()
            self.genfield()
        except ZeroDivisionError:
            print("Zero division")
        except IndexError:
            print("Index error")
            #рисуем надпись
            self.canvas.delete("all")
            x,y = int(self.canvas["width"]),int(self.canvas["height"])
            self.canvas.create_text(x//2,y//2,text="FILE IS CORRUPTED", font="Verdana 12 bold",fill="red",tag="del")
示例#34
0
文件: client.py 项目: Omertorren/ex12
class Application():
    def __init__(self, master, network, debug=False):
        """
        Init method for the Application class, this method is the GUI
        Class for our solution, it gets master (Tk root, network
        and debug (Open debug window if needded)
        :param master: The root Tk of the Application
        :param network: network is object from Network class (communication)
        :param debug: bool, to open or not..
        """
        self.init_constants(master, network)  # create constants
        self.__create_top_toolbar()
        self.__create_app_frame()
        self.bindings()
        self.__network.listen()  # network mainloop..
        if debug:
            self.debug = True
            self.open_debug_dialog()

    def init_constants(self, master, network):
        """
        This function contruct all the vital constant
        for this class it gets the root and the network
        and save them as constant of the class
        :param master: The root Tk of the Application
        :param network: network is object from Network class (communication)
        """
        self.__master_splinter = master
        self.__user_color = StringVar()
        self.__current_shape = None
        self.__drawing_shape = None
        self.__users_list = []
        self.__points = []  # private because I dont want that someone change them
        self.__network = network  # private for the same reason
        self.debug = False

    def __create_app_frame(self):
        """
        This function creates and pack (using grid) the main app frame
        (The left toolbar (users list) and the canvas
        """
        app_frame = Frame(self.__master_splinter)
        self.create_game_canvas(app_frame)
        self.create_left_toolbar(app_frame)
        app_frame.grid(row=1)

    def create_game_canvas(self, app_frame):
        """
        This function creates and pack the game canvas
        :param app_frame: Tk frame object
        """
        self.canvas = Canvas(app_frame, width=500, height=500, bg='white')
        self.canvas.grid(column=1)

    def __create_top_toolbar(self):
        """
        This function creates and pack the top toolbar (with all the colors, shapes
        and etc..
        """
        top_toolbar = Frame(self.__master_splinter)
        help_button = Button(top_toolbar, text="Help", command=self.open_help_dialog)
        help_button.grid(row=0, column=4)

        color_frame = self.create_color_frame(top_toolbar)
        color_frame.grid(row=0, column=0)

        empty_label = Label(top_toolbar, padx=20)
        empty_label.grid(column=1, row=0)

        my_shapes_frame = self.create_shape_buttons(top_toolbar)
        my_shapes_frame.grid(row=0, column=2)

        empty_label = Label(top_toolbar, padx=45)
        empty_label.grid(column=3, row=0)

        top_toolbar.grid(row=0)

    def create_left_toolbar(self, app_frame):
        """
        This function creates and pack the left toolbar
        :param app_frame: root for this toolbar.. (Frame obj)
        :return:
        """
        left_toolbar = Frame(app_frame)
        self.lb_users = Listbox(left_toolbar)
        self.lb_users.config(height=30)
        self.lb_users.grid(row=0, column=0)
        scroll_bar = Scrollbar(left_toolbar)
        scroll_bar.config(command=self.lb_users.yview)
        scroll_bar.grid(row=0, column=1, sticky='ns')
        left_toolbar.propagate("false")
        left_toolbar.grid(column=0, row=0)
        self.lb_users.config(yscrollcommand=scroll_bar.set)
        self.debug_event("Left toolbar was generated")

    def create_shape_buttons(self, root):
        """
        This function get a root and creates all the shapes
        buttons (because they have picture they need to
        compile and resize the icons...
        :param root: Tk frame
        :return: returns Frame object (it won`t pack it)
        """
        shapes_frame = Frame(root)
        shape_text = Label(shapes_frame, text="Shape: ")
        shape_text.grid(row=0, column=0)
        self.line_image = self.create_shape_img(SHAPES_DICT[LINE])
        line_btn = Button(shapes_frame,
                          image=self.line_image,
                          command=lambda: self.create_shape(LINE))
        line_btn.grid(row=0, column=1)
        self.square_image = self.create_shape_img(SHAPES_DICT[SQUARE])
        square_btn = Button(shapes_frame,
                            image=self.square_image,
                            command=lambda: self.create_shape(SQUARE))
        square_btn.grid(row=0, column=2)
        self.triangle_image = self.create_shape_img(SHAPES_DICT[TRIANGLE])
        triangle_btn = Button(shapes_frame,
                              image=self.triangle_image,
                              command=lambda: self.create_shape(TRIANGLE))
        triangle_btn.grid(row=0, column=3)
        self.elipse_image = self.create_shape_img(SHAPES_DICT[ELIPSE])
        elipse_btn = Button(shapes_frame,
                            image=self.elipse_image,
                            command=lambda: self.create_shape(ELIPSE))
        elipse_btn.grid(row=0, column=4)
        self.debug_event("shapes toolbar was generated")
        return shapes_frame

    def create_color_frame(self, root):
        """
        This function creates a color frame
        :param root: Frame obj
        :return: frame..
        """
        color_frame = Frame(root)
        color_text = Label(color_frame, text="Color:  ")
        color_text.grid(row=0, column=0)
        self.colors_list = ttk.Combobox(color_frame,
                                        textvariable=self.__user_color,
                                        values=COLOR_LIST,
                                        state="readonly")
        self.colors_list.grid(row=0, column=1)
        self.colors_list.current(FIRST_COLOR)
        self.debug_event("color toolbar was generated")
        return color_frame

    def create_shape_img(self, path):
        """
        This function get a path for picture.. and creates a
        icon in size of 32X32
        :param path:
        :return:
        """
        img = Image.open(path)
        img = img.resize(ICON_SIZE, Image.ANTIALIAS)
        return ImageTk.PhotoImage(img)



    def bindings(self):
        """
        This is our binding function.. it bind some things in the GUI
        some events like get new user, get clicks, close window
        """
        self.canvas.bind(LEFT_BUTTON_CLICK,
                         lambda event: self.try_draw_user_shape(event))
        self.__master_splinter.bind(JOIN_EVT,
                                    lambda x: self.change_users_list(JOIN_EVT, self.__network.get_event(JOIN_EVT)))
        self.__master_splinter.bind(LEAVE_EVT,
                                    lambda x: self.change_users_list(LEAVE_EVT, self.__network.get_event(LEAVE_EVT)))
        self.__master_splinter.bind(SHAPE_EVT, lambda event: self.shape_handler())
        self.__master_splinter.bind(USERS_EVT, lambda event: self.init_users())
        self.__master_splinter.protocol(CLOSE_WINDOW_PROT, self.on_close)

    def create_shape(self, shape_type):
        """
        After click on Shape this function appear :)
        it set the current shape to "shape type"
        :param shape_type: String repr shape type
        """
        self.canvas.config(cursor="target")
        self.__points = []
        self.__current_shape = shape_type
        self.debug_event("button " + shape_type + " clicked")

    def shape_handler(self):
        """
        This function handle new shapes events
        :return:
        """
        shape = self.__network.get_event(SHAPE_EVT)
        points = self.points_to_tuple(shape[COORDS])
        self.debug_event("shape msg:")
        self.debug_event(str(points))
        self.draw_shape(points, shape[SHAPE_TYPE], shape[USER], shape[COLOR])

    def init_users(self):
        """
        This function handle "connected" msg
        when connected it asks the communicator
        for users list, group name and user name
        and update the users list
        """
        group_name = self.__network.get_group()
        self.add_user_to_list(group_name + ":")
        user = self.__network.get_user_name()
        self.add_user_to_list(user)
        users = self.__network.get_user_list()
        self.debug_event("users list generated")
        for user in users:
            self.add_user_to_list(user)


    def try_draw_user_shape(self, event):
        """
        This function handles canvas clicks,
        after any click on the canvas this function
        checks if there was enough clicks to create
        the relevant shape (If shape is None it won`t happen..)
        :param event: event obj, contain the x,y of the click
        """
        # trying to draw
        if self.__current_shape is not self.__drawing_shape:
            # check if it is a new shape
            self.__drawing_shape = self.__current_shape
        self.__points.append((event.x, event.y))
        if len(self.__points) is POINTS_NEEDED[self.__drawing_shape]:  # Success
            self.send_shape_details_and_restart()
        self.debug_event("button is clicked in " + str(event.x) + "," + str(event.y))

    def send_shape_details_and_restart(self):
        """
        This function called when the user completed a shape
        it send to communicator a message the says "New shape was added"
        """
        self.__network.shape_msg([self.__drawing_shape, self.__points, self.__user_color.get()])
        self.__current_shape = None
        self.__drawing_shape = None
        self.__points = []
        self.canvas.config(cursor="")



    def draw_shape(self, points, s_type, user_name, color):
        """
        This function draw a new shape on the screen
        :param points: "x,y,z,w,a,b" string
        that each odd nu is x and each even is y
        :param s_type: shape type, string
        :param user_name: user_name string
        :param color: color, string
        """
        if s_type == LINE:
            self.canvas.create_line(points,
                                    fill=color, width=LINE_WIDTH)
        elif s_type == SQUARE:
            self.canvas.create_rectangle(points,
                                         fill=color)
        elif s_type == ELIPSE:
            self.canvas.create_oval(points,
                                    fill=color)
        elif s_type == TRIANGLE:
            self.canvas.create_polygon(points,
                                       fill=color)
        self.canvas.create_text(points[:FIRST_XY],
                                text=user_name)
        self.debug_event("draws: " + s_type)

    def points_to_tuple(self, str_points):
        """
        this function gets alot of numbers in string and returns
        :param str_points: "x,y,z,w,a,b" string
        that each odd nu is x and each even is y
        :return: list of coordinates as tuple in format (x,y,x,y,x,y)
        """
        nums = str_points.split(',')
        return tuple(nums)

    def open_help_dialog(self):
        """
        This function creates new "help" dialog
        :return:
        """
        try:
            self.help_frame.destroy()
        except:
            pass
        infromative_txt = self.get_informative_text()
        self.help_frame = Tk()
        self.help_frame.title(HELP_TITLE)
        infromative_text = Label(self.help_frame, text=infromative_txt)
        infromative_text.pack()
        self.help_frame.mainloop()

    def get_informative_text(self):
        f = open(INFO_DIR, READ_PREM)
        reader = f.read()
        f.close()
        return reader

    def open_debug_dialog(self):
        """
        this function create new "debug" dialog
        :return:
        """
        self.debug_frame = Tk()
        self.debug_frame.title(DEBUG_TITLE)
        self.debug_messages = Text(self.debug_frame)
        self.debug_messages.insert(END, "Messages")
        self.debug_messages.pack()
        self.debug_frame.mainloop()

    def debug_event(self, event):
        """
        This function check if the debug option is enabled
        if it is it will record the event in the debug messages dialog
        :param event: string repr event to debug..
        """
        if self.debug:
            self.debug_messages.insert(END, "\nEVENT: " + str(event))

    def on_close(self):
        """
        Handles closing the programe
        :return:
        """
        self.__network.leave_msg()
        self.__master_splinter.destroy()
        try:
            self.debug_frame.destroy()
            self.help_frame.destroy()
        except:
            pass

    def change_users_list(self, msg_type, user):
        """
        Handle "change user" event (Leave\Join)
        :param msg_type: CONSTANT, JOIN\LEAVE
        :param user: list of users..
        """
        users = user[ONE_USER]
        self.debug_event(user + " has " + msg_type)
        if msg_type is LEAVE_EVT:
            self.remove_user_from_list(users)
        elif msg_type is JOIN_EVT:
            self.add_user_to_list(users)

    def add_user_to_list(self, user):
        """
        Add specific user the list_box.. of users list
        :param user: string repr username
        """
        if user not in self.__users_list:
            self.__users_list.append(user)
            self.lb_users.insert(END, user)
        else:
            self.debug_event(user + " already exists")

    def remove_user_from_list(self, user):
        """
        This function tries to delete specific username
        from the list
        :param user: string repr username
        :return:
        """
        try:
            i = self.__users_list.index(user)
            self.lb_users.delete(i)
            self.__users_list.pop(i)
        except:
            self.debug_event(user + " is not in our list..")
示例#35
0
class QuickHull(Tk):
	def __init__(self,points):
		Tk.__init__(self)
		board = Frame(self)
		self.title("Diagram") 

		width = 800 #setting height and width
		height = 600

		windowx = self.winfo_screenwidth()
		windowy = self.winfo_screenheight()
		x = (windowx - width)/2		#getting center
		y = (windowy - height)/2

		self.geometry("%dx%d+%d+%d" % (width,height,x,y)) #creates window of size _width by _height, and positions it at the center of the screen

		board.pack(fill=BOTH, expand=1)
	
		self.canvas = Canvas(board,height=600,width=800,background="white")
		self.canvas.place(x=0,y=0)
		
		self.drawPoints(points) #Draw points and the first line from the highest an lowest points
		

					

		
		def point(event):  #Add points by clicking on the screen
			self.canvas.create_text(event.x, event.y,text = "+")
			points.append([event.x,event.y])

		def start():
			if(points != []):
				startB.destroy()
				quickHullStart(points)
				self.nextButton()
	
		self.canvas.bind("<Button-1>", point)
		
		startB = Button(self, text = "Start QuickHull", command = start)
		startB.pack()
	
		
	
		self.mainloop()
	
				
	def nextButton(self):					#Button that steps forward one step in the QuickHull
		def callBack():
			self.animate()

		continueB = Button(self, text="-->",command=callBack)
		continueB.place(x=350,y=550)


	def animate(self):						#animation loop
		if(triList == []):
			self.onExit()
			return
		self.canvas.create_polygon(triList.pop(0),fill="red",outline="black")
			





	def onExit(self):  #Window popup signaling that the Quick Hull is complete
		alert = Tk()
		finish = Window(alert)
		finish.config(title="Complete",w = 200, h=50)
		finish.positionWindow()

		done = Label(alert,text="QuickHull Complete")
		done.pack()

		ok = Button(alert,text="OK",command=alert.destroy)
		ok.pack()
		alert.mainloop()
		return
		


	def drawPoints(self,points):			#Draw points Imported from a file
		for p in points:
			self.canvas.create_text(p[0],p[1],text="+")
示例#36
0
文件: plot.py 项目: pletzer/compos
class Plot:

    def __init__(self, root, grid, title='', boxsize=[], width=800, height=800):
        
        if boxsize:
            self.xmin, self.ymin, self.xmax, self.ymax = boxsize
        else:
            self.xmin, self.ymin, self.xmax, self.ymax = grid.boxsize()
        self.width = width
        self.height = height
        self.title = title
        self.grid = grid
    
        self.frame = Frame(root)
        self.frame.pack()
        self.canvas = Canvas(bg="white", width=width, height=height)
        self.canvas.pack()

    def draw(self, rho, the, xyPath=[]):
        
        border_x, border_y = 0.2, 0.2
        scale = min((1.-border_x)*self.width/(self.xmax-self.xmin), \
                    (1.-border_y)*self.height/(self.ymax-self.ymin))
        a = max(border_x * self.width/2., (self.width-scale*(self.xmax-self.xmin))/2.)
        b = max(border_y * self.height/2.,(self.height-scale*(self.ymax-self.ymin))/2.)
    
        box_pix = (a, self.height-scale*(self.ymax-self.ymin) - b,
                   scale*(self.xmax-self.xmin) + a, self.height - b)
        # draw the box
        self.addBox((self.xmin, self.ymin, self.xmax, self.ymax), box_pix)
    
        # color plot
        cells = cell.cell(self.grid)
        for index in range(len(cells.data)):
                ia, ib, ic = cells.data[index]
                xa, ya = scale*(self.grid.x(ia)-self.xmin) + a, \
                         self.height -scale*(self.grid.y(ia)-self.ymin) - b
                xb, yb = scale*(self.grid.x(ib)-self.xmin) + a, \
                         self.height -scale*(self.grid.y(ib)-self.ymin) - b
                xc, yc = scale*(self.grid.x(ic)-self.xmin) + a, \
                         self.height -scale*(self.grid.y(ic)-self.ymin) - b

                rhoAbc = (rho[ia] + rho[ib] + rho[ic])/3.0
                theAbc = (the[ia] + the[ib] + the[ic])/3.0
                color = colormap(rhoAbc, theAbc)
                self.canvas.create_polygon(xa, ya, xb, yb, xc, yc, fill=color)
        
        # add path if present
        index = 0
        for (x, y) in xyPath:
            xa, ya = scale*(x - self.xmin) + a, \
                self.height -scale*(y - self.ymin) - b
            self.canvas.create_oval(xa-5, ya-5,
                                    xa+5, ya+5)
            #self.canvas.create_text(xa+2, ya+1, text=str(index))
            index += 1
    
        # add title
        x, y = self.width/3., self.height/15.0
        self.canvas.create_text(x, y, text=str(self.title),
                                font =("Helvetica", 24),
                                fill='black')


    def addBox(self, xxx_todo_changeme, xxx_todo_changeme1):
        """
        Add Box. Min/Max coordinates are in pixels.
        """
        (self.xmin,self.ymin,self.xmax,self.ymax) = xxx_todo_changeme
        (self.xmin_pix, self.ymin_pix, self.xmax_pix, self.ymax_pix) = xxx_todo_changeme1
        self.canvas.create_line(self.xmin_pix, self.ymax_pix, self.xmax_pix, self.ymax_pix)
        self.canvas.create_text(self.xmin_pix   ,self.ymax_pix+ 8, text=('%4.1f' % self.xmin))
        self.canvas.create_text(self.xmin_pix-12,self.ymax_pix   , text=('%4.1f' % self.ymin))
        self.canvas.create_line(self.xmax_pix, self.ymax_pix, self.xmax_pix, self.ymin_pix)
        self.canvas.create_text(self.xmax_pix   ,self.ymax_pix+ 8, text=('%4.1f' % self.xmax))
        self.canvas.create_line(self.xmax_pix, self.ymin_pix, self.xmin_pix, self.ymin_pix)
        self.canvas.create_text(self.xmin_pix-12,self.ymin_pix   , text=('%4.1f' % self.ymax))
        self.canvas.create_line(self.xmin_pix, self.ymin_pix, self.xmin_pix, self.ymax_pix)
示例#37
0
canvas = Canvas(gui,
                width=window_width,
                height=window_height,
                background='white')
canvas.pack()
##################################################################################
point_list = []
f = open(utilities.get_file_path('florida.csv'))
for line in f.readlines():
    line = line.replace('\n', '')
    items = line.split(',')
    x = float(items[0])
    y = float(items[1])
    point_list.append((x, y))

canvas.create_polygon(point_list, fill='white', outline='black', tag='florida')
gui.update()

while True:
    center = utilities.get_center(canvas, 'florida')
    width = utilities.get_width(canvas, 'florida')
    print(center, width)
    shape_ids = canvas.find_withtag('florida')
    for shape_id in shape_ids:
        flipped_coordinates = []
        shape_coords = canvas.coords(shape_id)
        counter = 0
        for num in shape_coords:
            if counter % 2 == 0:
                shape_coords[counter] = -num + center[0] + width / 2
            counter += 1
示例#38
0
                          320,
                          145,
                          360,
                          outline=c.body_color,
                          fill=c.body_color)
foot_right = c.create_oval(250,
                           320,
                           330,
                           360,
                           outline=c.body_color,
                           fill=c.body_color)

ear_left = c.create_polygon(75,
                            80,
                            75,
                            10,
                            165,
                            70,
                            outline=c.body_color,
                            fill=c.body_color)
ear_right = c.create_polygon(255,
                             45,
                             325,
                             10,
                             320,
                             70,
                             outline=c.body_color,
                             fill=c.body_color)

eye_left = c.create_oval(130, 110, 160, 170, outline='black', fill='white')
pupil_left = c.create_oval(140, 145, 150, 155, outline='black', fill='black')
eye_right = c.create_oval(230, 110, 260, 170, outline='black', fill='white')
示例#39
0
class World(Tk):
    def __init__(self, filename=None, block=50, debug=True, delay=0.25,
                 image=False, width=10, height=10):
        Tk.__init__(self)
        self.title("")
        arg = block
        self.width = width
        self.height = height
        self.beepers = {}
        self.ovals = {}
        self.numbers = {}
        self.robots = {}
        self.walls = {}
        self.m = arg * (width + 3)
        self.n = arg * (height + 3)
        self.t = arg
        self.delay = delay
        self.debug = debug
        self.use_image = image
        a = self.t + self.t / 2
        b = self.m - self.t / 2
        c = self.n - self.t / 2
        self.canvas = Canvas(self, bg="white", width=self.m, height=self.n)
        self.canvas.pack()
        count = 1
        for k in range(2*self.t, max(self.m, self.n)-self.t, self.t):
            if k < b:
                self.canvas.create_line(k, c, k, a, fill="red")
                self.canvas.create_text(k, c+self.t/2, text=str(count),
                                        font=("Times",
                                              max(-self.t*2/3, -15), ""))
            if k < c:
                self.canvas.create_line(b, k, a, k, fill="red")
                self.canvas.create_text(a-self.t/2, self.n-k, text=str(count),
                                        font=("Times",
                                              max(-self.t*2/3, -15), ""))
            count += 1
        self.canvas.create_line(a, c, b, c, fill="black", width=3)
        self.canvas.create_line(a, a, a, c, fill="black", width=3)
        if filename is not None:
            self.read_world(filename)
        self.refresh()

    def read_world(self, filename):
        try:
            infile = open("worlds\\{0}.wld".format(filename), "r")
        except IOError:
            try:
                infile = open("worlds/{0}.wld".format(filename), "r")
            except IOError:
                infile = open(filename, "r")
        text = infile.read().split("\n")
        infile.close()
        for t in text:
            if t.startswith("eastwestwalls"):
                s = t.split(" ")
                y, x = int(s[1]), int(s[2])
                self.add_wall(x, y, -1, y)
            if t.startswith("northsouthwalls"):
                s = t.split(" ")
                x, y = int(s[1]), int(s[2])
                self.add_wall(x, y, x, -1)
            if t.startswith("beepers"):
                s = t.split(" ")
                y, x, n = int(s[1]), int(s[2]), int(s[3])
                if n is INFINITY:
                    self.add_infinite_beepers(x, y)
                else:
                    for k in range(n):
                        self.add_beeper(x, y)

    def pause(self):
        sleep(self.delay)

    def is_beeper(self, x, y):
        return (x, y) in list(self.beepers.keys()) and not \
            self.beepers[(x, y)] == 0

    def count_robots(self, x, y):
        if (x, y) not in list(self.robots.keys()):
            return 0
        return len(self.robots[(x, y)])

    def crash(self, x1, y1, x2, y2):
        if 0 in (x1, y1, x2, y2):
            return True
        if (x2, y2) in list(self.walls.keys()) and \
                (x1, y1) in self.walls[(x2, y2)]:
            return True
        if (x1, y1) in list(self.walls.keys()) and \
                (x2, y2) in self.walls[(x1, y1)]:
            return True
        return False

    def add_infinite_beepers(self, x, y):
        flag = (x, y) not in list(self.beepers.keys()) or \
            self.beepers[(x, y)] is 0
        self.beepers[(x, y)] = INFINITY
        text = "oo"
        a = self.t + x * self.t
        b = self.n - (self.t + y * self.t)
        t = self.t / 3
        if flag:
            self.ovals[(x, y)] = self.canvas.create_oval(a-t, b-t, a+t,
                                                         b+t, fill="black")
            self.numbers[(x, y)] = self.canvas.create_text(a, b, text=text,
                                                           fill="white",
                                                           font=("Times",
                                                                 max(-self.t/2,
                                                                     -20),
                                                                 ""))
        else:
            self.canvas.itemconfig(self.numbers[(x, y)], text=text)
        if (x, y) in list(self.robots.keys()):
            for robot in self.robots[(x, y)]:
                robot.lift()

    def add_beeper(self, x, y):
        if (x, y) in list(self.beepers.keys()) and \
                self.beepers[(x, y)] is INFINITY:
            return
        flag = (x, y) not in list(self.beepers.keys()) or \
            self.beepers[(x, y)] is 0
        if flag:
            self.beepers[(x, y)] = 1
        else:
            self.beepers[(x, y)] += 1
        text = str(self.beepers[(x, y)])
        a = self.t + x * self.t
        b = self.n - (self.t + y * self.t)
        t = self.t / 3
        if flag:
            self.ovals[(x, y)] = self.canvas.create_oval(a-t, b-t, a+t, b+t,
                                                         fill="black")
            self.numbers[(x, y)] = self.canvas.create_text(a, b, text=text,
                                                           fill="white",
                                                           font=("Times",
                                                                 max(-self.t/2,
                                                                     -20),
                                                                 ""))
        else:
            self.canvas.itemconfig(self.numbers[(x, y)], text=text)
        if (x, y) in list(self.robots.keys()):
            for robot in self.robots[(x, y)]:
                robot.lift()

    def remove_beeper(self, x, y):
        if self.beepers[(x, y)] is INFINITY:
            return
        self.beepers[(x, y)] -= 1
        flag = self.beepers[(x, y)] is 0
        text = str(self.beepers[(x, y)])
        if flag:
            self.canvas.delete(self.ovals[(x, y)])
            self.canvas.delete(self.numbers[(x, y)])
        else:
            self.canvas.itemconfig(self.numbers[(x, y)], text=text)
        if (x, y) in list(self.robots.keys()):
            for robot in self.robots[(x, y)]:
                robot.lift()

    def add_wall(self, x1, y1, x2, y2):
        if not x1 == x2 and not y1 == y2:
            return
        if x1 == x2:
            y1, y2 = min(y1, y2), max(y1, y2)
            if y1 == -1:
                y1 = y2
            for k in range(y1, y2+1):
                self.walls.setdefault((x1, k), []).append((x1+1, k))
                a = self.t + x1 * self.t+self.t / 2
                b = self.n - (self.t + k * self.t) + self.t / 2
                c = self.t + x1 * self.t + self.t / 2
                d = self.n - (self.t + k * self.t) - self.t / 2
                self.canvas.create_line(a, b+1, c, d-1, fill="black", width=3)
        else:
            x1, x2 = min(x1, x2), max(x1, x2)
            if x1 == -1:
                x1 = x2
            for k in range(x1, x2+1):
                self.walls.setdefault((k, y1), []).append((k, y1+1))
                a = self.t + k * self.t - self.t / 2
                b = self.n - (self.t + y1 * self.t) - self.t / 2
                c = self.t + k * self.t + self.t / 2
                d = self.n - (self.t + y1 * self.t) - self.t / 2
                self.canvas.create_line(a-1, b, c+1, d, fill="black", width=3)

    def draw(self, x, y, d, img):
        t = self.t / 2
        angle = 120
        x = self.t + x * self.t
        y = self.n - (self.t + y * self.t)
        x1 = x + 3 ** 0.5 * t / 2 * cos(radians(d))
        y1 = y - 3 ** 0.5 * t / 2 * sin(radians(d))
        x2 = x + t * cos(radians(d + angle))
        y2 = y - t * sin(radians(d + angle))
        x3 = x + t / 4 * cos(radians(d + 180))
        y3 = y - t / 4 * sin(radians(d + 180))
        x4 = x + t * cos(radians(d - angle))
        y4 = y - t * sin(radians(d - angle))
        if img is not None:
            self.canvas.delete(img)
        return self.canvas.create_polygon(x1, y1, x2, y2, x3, y3, x4, y4,
                                          fill="blue")

    def erase(self, img):
        self.canvas.delete(img)

    def record_move(self, count, x1, y1, x2, y2):
        for robot in self.robots[(x1, y1)]:
            if robot.count == count:
                self.robots[(x1, y1)].remove(robot)
                self.robots.setdefault((x2, y2), []).append(robot)
                break

    def lift(self, img):
        self.canvas.lift(img)

    def refresh(self):
        self.canvas.update()
        self.pause()

    def register(self, x, y, robot):
        self.robots.setdefault((x, y), []).append(robot)

    def remove(self, x, y, robot):
        self.robots[(x, y)].remove(robot)
示例#40
-19
class IsometricViewer:
    def __init__(self, width, height):
        self.width = width
        self.height = height
        self.wireframe = True
        self.drawables = []
        self.items = {}
        self.text = ""
        self.theta = 0
        self.phi = 0
        self.scale = 0
        self.x_offset = 0
        self.y_offset = 0
        self.canvas = Canvas(Tk(), width=self.width, height=self.height)
        self.reset_viewport()
        self.init_gui()
    @property
    def camera_coords(self):
        return Point3(math.cos(self.theta) * math.cos(self.phi), -math.sin(self.theta) * math.cos(self.phi), math.sin(self.phi))
    def reset_viewport(self):
        self.theta = math.pi / 8
        self.phi = math.pi / 16
        self.scale = 1
        self.x_offset = self.width / 2
        self.y_offset = self.height / 2
    def init_gui(self):
        self.canvas.pack()
        self.canvas.focus_set()
        self.canvas.bind("<Up>", self._callback_commandline_up)
        self.canvas.bind("<Down>", self._callback_commandline_down)
        self.canvas.bind("<Left>", self._callback_commandline_left)
        self.canvas.bind("<Right>", self._callback_commandline_right)
        self.canvas.bind("=", self._callback_commandline_equal)
        self.canvas.bind("-", self._callback_commandline_minus)
        self.canvas.bind("<Shift-Up>", self._callback_commandline_shift_up)
        self.canvas.bind("<Shift-Down>", self._callback_commandline_shift_down)
        self.canvas.bind("<Shift-Left>", self._callback_commandline_shift_left)
        self.canvas.bind("<Shift-Right>", self._callback_commandline_shift_right)
        self.canvas.bind("<Shift-Return>", self._callback_commandline_shift_return)
        self.canvas.bind("<Button-1>", self._callback_button_1)
        self.canvas.bind("<B1-Motion>", self._callback_button_1_motion)
    def add_drawable(self, drawable):
        assert isinstance(drawable, Drawable)
        self.drawables.append(drawable)
    def project(self, point):
        projected = point.rotate(self.theta, self.phi)
        return Point2(projected.y * self.scale + self.x_offset, -projected.z * self.scale + self.y_offset)
    def unproject(self, point):
        return point.rotate(0, -self.phi).rotate(-self.theta, 0)
    def move_camera(self, theta, phi):
        self.theta += theta
        if self.theta > 2 * math.pi:
            self.theta -= 2 * math.pi
        elif self.theta < 0:
            self.theta += 2 * math.pi
        if -math.pi / 2 <= self.phi + phi <= math.pi / 2:
            self.phi += phi
    def clear(self):
        for item in self.items:
            self.canvas.delete(item)
    def draw_line(self, owner, p1, p2, **kargs):
        assert isinstance(p1, Point3)
        assert isinstance(p2, Point3)
        p1 = self.project(p1)
        p2 = self.project(p2)
        item = self.canvas.create_line(p1.x, p1.y, p2.x, p2.y, **kargs)
        self.items[item] = owner
        return item
    def draw_ellipse(self, owner, corners, **kargs):
        assert all(isinstance(p, Point3) for p in corners)
        item = self.draw_polygon(owner, corners, outline="#000000", smooth=1, **kargs)
        self.items[item] = owner
        return item
    def draw_polygon(self, owner, pts, **kargs):
        assert all(isinstance(p, Point3) for p in pts)
        args = []
        for p in pts:
            p = self.project(p)
            args.extend((p.x, p.y))
        item = self.canvas.create_polygon(*args, **kargs)
        self.items[item] = owner
        return item
    def draw_wireframe(self):
        for drawable in self.drawables:
            drawable.draw_wireframe(self)
    def draw(self):
        for drawable in self.drawables:
            drawable.draw(self)
    def update(self):
        self.clear()
        header = [
            "(theta, phi): ({:.3f}, {:.3f})".format(self.theta, self.phi),
            "(x, y, z): {}".format(self.camera_coords),
        ]
        text = "\n".join(header) + "\n\n" + self.text
        item = self.canvas.create_text((10, 10), anchor="nw", text=text)
        self.items[item] = None
        if self.wireframe:
            self.draw_wireframe()
        else:
            self.draw()
    def display(self):
        self.update()
        mainloop()
    def _callback_commandline_up(self, event):
        self.move_camera(0, math.pi / 16)
        self.update()
    def _callback_commandline_down(self, event):
        self.move_camera(0, -math.pi / 16)
        self.update()
    def _callback_commandline_left(self, event):
        self.move_camera(math.pi / 16, 0)
        self.update()
    def _callback_commandline_right(self, event):
        self.move_camera(-math.pi / 16, 0)
        self.update()
    def _callback_commandline_equal(self, event):
        self.scale *= 1.2
        self.update()
    def _callback_commandline_minus(self, event):
        self.scale /= 1.2
        self.update()
    def _callback_commandline_shift_up(self, event):
        self.y_offset -= 10
        self.update()
    def _callback_commandline_shift_down(self, event):
        self.y_offset += 10
        self.update()
    def _callback_commandline_shift_left(self, event):
        self.x_offset -= 10
        self.update()
    def _callback_commandline_shift_right(self, event):
        self.x_offset += 10
        self.update()
    def _callback_commandline_shift_return(self, event):
        self.reset_viewport()
        self.update()
    def _callback_button_1(self, event):
        text = []
        closest = self.canvas.find_closest(event.x, event.y)[0]
        overlapping = self.canvas.find_overlapping(event.x, event.y, event.x+1, event.y+1)
        if closest in overlapping and closest in self.items and self.items[closest] is not None:
            text.append(self.items[closest].clicked(self, event, closest))
        self.text = "\n".join(text)
        self.update()
    def _callback_button_1_motion(self, event):
        pass