0

So I'm trying to make some different virtual keyboard designs with the goal of using them in combination with head tracking. I wanted to explore if maybe a circular keyboard would be easier to use with head tracking compared to a standard layout. enter image description here

The keyboard would look like the one in the picture, but I'm not sure how to make this kind of a layout using tkinter (this is what I used for the other keyboard but I'm not limited to this lib in any way). Any tips on how to make non square/rectangular UI? Thanks in advance.

tkarina
  • 13
  • 2
  • Your question isn't clear. What you need exactly help with? Do you want a window in the shape of your picture? – Thingamabobs Dec 16 '21 at 18:54
  • The window itself can be square i don't really mind. But i want to make the buttons like in the picture. I want for example the Q button to be curved. And I'm not sure how to do that in tkinter or python in general. So in short I would like to make a GUI keyboard that looks like the one in the picture. – tkarina Dec 16 '21 at 19:06
  • There are ways to achieve this. Easiest way to go would be to use `tk.Canvas` and [draw the shapes](https://stackoverflow.com/a/44100075) in combination with `canvas.tag_bind`. – Thingamabobs Dec 16 '21 at 19:16
  • Thanks will definitely look in to canvas and tag_bind. – tkarina Dec 16 '21 at 19:24

1 Answers1

1

You can use the Canvas widget to draw the menu as a collection of arc items. One of the features of the canvas is that you can give items on the canvas a tag, and you can bind that tag to an event.

This isn't a complete solution, but it illustrates how it's possible to draw a circular menu that responds to clicks, as well as enter and leave events. In the following code we draw a circle as a sequence of eight arcs. Each arc is given a generic tag of "item" and a specific tag of "item-". These tags can then be used to bind events, and to get information about the item that was clicked on.

class PieMenu(tk.Canvas):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.tag_bind("item", "<ButtonRelease-1>", self._click)
        self.tag_bind("item", "<Enter>", self._enter)
        self.tag_bind("item", "<Leave>", self._leave)

        for index, start in enumerate(range(0, 360, 45)):
            self.create_arc(
                (2, 2, 200, 200),
                outline="black", fill="white",
                start=start, extent=45, tags=(f"item-{index}", "item")
            )

    def _click(self, event):
        item = event.widget.find_withtag("current")[0]
        tags = event.widget.itemcget("current", "tags")
        print(f"item: {item} tags: {tags}")

    def _enter(self,event):
        event.widget.itemconfigure("current", fill="lightgray")

    def _leave(self,event):
        event.widget.itemconfigure("current", fill="white")

You would need to add code to include the text of each item, and code to know what function to call when a particular part of the menu is clicked. The point of the example is to show the technique for drawing one simple menu that can respond to mouse events.

Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685