Lecdi
Lecdi

Reputation: 2241

Have PanedWindow separators "snap" to certain positions, instead of just allowing the user to choose any random position

I have a tkinter PanedWindow containing some widgets and I want the user to be able to drag each separator to a certain position and when they let go of the mouse button, the separator should "snap" to the nearest position in a list of positions / proportions I give the program. For example, let's say I have a PanedWindow containing two buttons, and I want the user to be able to resize the buttons such that they can be in the proportions 1/4:3/4, 1/2:1/2 or 3/4:1/4 not just any width the user chooses. Is there a way I can do this? Code for PanedWindow with two buttons:

import tkinter as tk
from tkinter import ttk

root = tk.Tk()
root.geometry("400x400")

pw = tk.PanedWindow(root)
buttons = [ttk.Button(text=message) for message in ["goose", "duck"]]
for button in buttons:
    pw.add(button)
pw.pack(expand=True, fill="both")

root.mainloop()

Is there a way to specify the proportions the separators can snap to?

Allowed positions:

The buttons should snap to the nearest of these positions when resized.

Upvotes: 3

Views: 479

Answers (1)

Art
Art

Reputation: 3089

You can do this by binding <ButtonRelease-1> to a function that calculates the closest point. You can then use this information and update the sash position using PanedWindow.sash_place(index, x, y).

Here is a minimal example:

import tkinter as tk
from tkinter import ttk


def snap(event):
    width = pw.winfo_width()
    closest = min([width//2, width//4, width*3//4], key=lambda w: abs(w - event.x))
    pw.sash_place(0, closest, 1)


root = tk.Tk()
root.title("snappy")

pw = tk.PanedWindow(root)
buttons = [ttk.Button(text=message) for message in ["goose", "duck"]]

for button in buttons:
    pw.add(button)
pw.pack(expand=True, fill="both")

pw.bind("<ButtonRelease-1>", snap)

root.mainloop()

Upvotes: 5

Related Questions