Перемещение окна tkinter

#python #tkinter

Вопрос:

Я пытаюсь создать окно, удалив строку заголовка. Я заставил окно перемещаться, когда пользователь щелкает и перетаскивает его с помощью мыши. Теперь, если я нажму внутри любого виджета и перетащу его, окно переместится. Но я хочу, чтобы он двигался только в том случае, если пользователь нажимает за пределами виджетов. Любые предложения будут полезны. Вот мой код.

 from tkinter import *
    
win = Tk()
win.geometry('200x200')
win.overrideredirect(True)

offsetx = 0
offsety = 0

lst = ['Sample 1', 'Sample 2', 'Sample 3', 'Sample 4']
    
def drag(event):
    x = win.winfo_pointerx() - win.offsetx
    y = win.winfo_pointery() - win.offsety
    win.geometry(' {x} {y}'.format(x=x,y=y))

def click(event):
    win.offsetx = event.x
    win.offsety = event.y


win.bind('<Button-1>', click)
win.bind('<B1-Motion>', drag)
            
lb1 = Listbox(win)
lb1.pack()

b1 = Button(win, text='Close', command=win.destroy).pack()

for i in range(len(lst)):
    lb1.insert(i, lst[i])

win.mainloop()
 

Комментарии:

1. Попробуйте установить контейнер, может быть, рамку, сделайте то, что вы сделали, чтобы выиграть в рамке, например, привязки, список, кнопку …

2. @JasonYang Я попробовал то, что ты сказал. Тем не менее, он ведет себя так же, как и раньше.

3. Я думаю, что вы должны что-то понять неправильно, покажите один сценарий для вас.

Ответ №1:

Здесь я использую рамку в качестве контейнера, а не корневое окно. Он покажет окно, верхняя область предназначена для списка и, возможно, 10 строк по умолчанию, нижняя область с одной кнопкой и двумя полями зеленой области drak. Здесь щелчок и перетаскивание по списку и кнопке не переместят окно, но эти две темно-зеленые области работают.

введите описание изображения здесь

 from tkinter import *

def mouse_down(event):
    global x, y
    x, y = event.x, event.y

def mouse_up(event):
    global x, y
    x, y = None, None

def mouse_drag(event):
    global x, y
    try:
        deltax = event.x - x
        deltay = event.y - y
        x0 = win.winfo_x()   deltax
        y0 = win.winfo_y()   deltay
        win.geometry(" %s %s" % (x0, y0))
    except:
        pass

win = Tk()
# win.geometry('200x400')
win.overrideredirect(True)

x, y = None, None

frame = Frame(win, background='#004000')
frame.bind('<ButtonPress-1>', mouse_down)
frame.bind('<B1-Motion>', mouse_drag)
frame.bind('<ButtonRelease-1>', mouse_up)
frame.pack()

list_box = Listbox(frame)
list_box.pack()

button = Button(frame, text='Close', command=win.destroy)
button.pack()

lst = ['Sample 1', 'Sample 2', 'Sample 3', 'Sample 4']
for i, item in enumerate(lst):
    list_box.insert(i, item)

win.mainloop()
 

Комментарии:

1. Это то, чего я хочу. Спасибо.

Ответ №2:

Кажется, что самое простое, что нужно сделать, — это просто проверить, какое окно получило событие в функции перетаскивания, и выполнять перетаскивание только в том случае, если это корневое окно:

 def drag(event):
    if event.widget == win:
        x = win.winfo_pointerx() - win.offsetx
        y = win.winfo_pointery() - win.offsety
        win.geometry(' {x} {y}'.format(x=x,y=y))
 

Или, если вы хотите иметь возможность перетаскивать при нажатии в промежуточных окнах, вы можете проверить класс виджета:

 def drag(event):
    window_class = event.widget.winfo_class()
    if window_class in ("Tk", "Toplevel", "Frame"):
        x = win.winfo_pointerx() - win.offsetx
        y = win.winfo_pointery() - win.offsety
        win.geometry(' {x} {y}'.format(x=x,y=y))
 

Ответ №3:

как насчет создания холста строки заголовка с помощью tkinter и привязки клавиш к строке заголовка вместо всего приложения?

 titlebar_canvas = tk.Canvas(win, height=20, width=200)
titlebar_canvas.pack(side='top')
titlebar_canvas.bind('<Button-1>', click)
titlebar_canvas.bind('<B1-Motion>', drag)
 

Комментарии:

1. Мне нужно ограничить перемещение окна только внутри виджетов. Он должен переместиться, если мы нажмем на все остальные места.