Control location on screen where new windows open with graphics.py

1k Views Asked by At

I have a python program that deploys a windows via graphics.py. The initial window opened by the GraphWin class opens in the top left corner of the screen. Subsequent calls to GraphWin cascade from the upper left to the lower right.

I'd like to control the placement of each window. (Example: Have all the windows open in a grid-layout so I can create a dashboard.)

2

There are 2 best solutions below

0
On

I think there is no such method in graphics.py right now.

Ref: The Book and webpage.

If you want to stick to using graphics.py, I suggest creating a dashboard by dividing a single window into different slots.

This option does exist in Tkinter library. Please refer to this answer for more information on that.

1
On

graphics.py doesn't provide a way for you to control the location of instances of its GraphWin class. However the fact that it's built on top of Python's Tk GUI toolkit module named tkinter means that sometimes you can work around its limitations by looking at its source code to see how things operate internally.

For example, here's a snippet of code from the module (version 5.0) showing the beginning of GraphWin class' definition from the graphics.py file:

class GraphWin(tk.Canvas):

    """A GraphWin is a toplevel window for displaying graphics."""

    def __init__(self, title="Graphics Window",
                 width=200, height=200, autoflush=True):
        assert type(title) == type(""), "Title must be a string"
        master = tk.Toplevel(_root)
        master.protocol("WM_DELETE_WINDOW", self.close)
        tk.Canvas.__init__(self, master, width=width, height=height,
                           highlightthickness=0, bd=0)
        self.master.title(title)
        self.pack()
        master.resizable(0,0)
        self.foreground = "black"
        self.items = []
        self.mouseX = None
        self.mouseY = None
        self.bind("<Button-1>", self._onClick)
        self.bind_all("<Key>", self._onKey)
        self.height = int(height)
        self.width = int(width)
        self.autoflush = autoflush
        self._mouseCallback = None
        self.trans = None
        self.closed = False
        master.lift()
        self.lastKey = ""
        if autoflush: _root.update()

As you can see it's derived from a tkinter.Canvas widget which has an attribute named master which is a tkinter.Toplevel widget. It then initializes the Canvas base class and specifies the newly created Toplevel window as its parent.

The size and position of a Toplevel window can be controlled by calling its geometry() method as described in the linked documentation. This method expects to be passed a "geometry string" argument in a certain format ('wxh±x±y').

This mean you can take advantage of how this implementation detail in order to put it anywhere you want it and as well as resize if desired.

Here's an example of doing that:

from graphics import *


def main():
    win = GraphWin("My Circle", 100, 100)

    # Override size and position of the GraphWin.
    w, h = 300, 300  # Width and height.
    x, y = 500, 500  # Screen position.
    win.master.geometry('%dx%d+%d+%d' % (w, h, x, y))

    c = Circle(Point(50,50), 10)
    c.draw(win)
    win.getMouse() # pause for click in window
    win.close()


if __name__ == '__main__':
    main()

My desktop while script is running:

desktop