如何在没有主按钮的情况下创建用于移动窗口的按钮?

时间:2021-06-29 20:51:52

标签: python python-3.x tkinter tkinter-canvas

我是法国人,所以我的英语有点差,所以别在意。 我制作了一个 tkinter 计算器,为此我删除了标题和关闭按钮所在的窗口顶部,并用画布替换它,它看起来非常漂亮,但我无法再移动窗口我的屏幕,窗口停留在左上角,而且我无法以任何方式移动它...希望有人知道。

为了删除窗口顶部,我使用了 win.overrideredirect(1)

我尝试了一些东西,但这不起作用:

import tkinter as tk
win = tk.Tk()

def coordsSouris(event):
    # win.geometry()
    print(event.x, event.y)
    win.after(100, coordsSouris)

can = tk.Canvas(height = 400, width = 400)
can.pack()

can.bind("<Button-1>", coordsSouris)

win.mainloop()

函数遗漏了参数 event,我不能用 after()...

我有另一个想法:是否可以将标题栏放在我的画布前面并隐藏它并在我的退出按钮和菜单前面隐藏它?所以我们没有看到它,但它正常工作

3 个答案:

答案 0 :(得分:0)

设置根.geometry( Width x Height + X + Y )
保持宽度和高度相同,只需更改 X 和 Y 参数。

buttons


编辑:是的,这有点复杂。您需要存储初始拖动位置,然后从后续事件中减去它。释放按钮后清除值。您还需要设置最小/最大值以确保它不会离开屏幕。

lrduX

#! /usr/bin/env python3
import tkinter 

Width, Height, = 100, 33
Xpos, Ypos = 20, 20
dragposX, dragposY = 0, 0

root = tkinter .Tk() 
root .geometry( f'{Width}x{Height}+{Xpos}+{Ypos}')
root .overrideredirect( 1 )  ##  no titlebar

Screenwidth = root .winfo_screenwidth()
Screenheight = root .winfo_screenheight()
Xmax = Screenwidth -Width
Ymax = Screenheight -Height

fontname = 'ariel'
fontsize = 8
fontstyle = 'normal'
font = fontname, fontsize, fontstyle

def left():
    global Xpos ; Xpos -= 5
    if Xpos < 0:  Xpos = 0
    root .geometry( f'{Width}x{Height}+{Xpos}+{Ypos}')

def right():
    global Xpos ; Xpos += 5
    if Xpos > Xmax:  Xpos = Xmax
    root .geometry( f'{Width}x{Height}+{Xpos}+{Ypos}')

def up():
    global Ypos ; Ypos -= 5
    if Ypos < 0:  Ypos = 0
    root .geometry( f'{Width}x{Height}+{Xpos}+{Ypos}')

def down():
    global Ypos ; Ypos += 5
    if Ypos > Ymax:  Ypos = Ymax
    root .geometry( f'{Width}x{Height}+{Xpos}+{Ypos}')

def drag( event ):
    global Xpos, Ypos, dragposX, dragposY
    if dragposX == 0 and dragposY == 0:
        dragposX = event .x
        dragposY = event .y

    Xpos += event .x -dragposX
    Ypos += event .y -dragposY
    if Xpos < 0:  Xpos = 0
    if Ypos < 0:  Ypos = 0
    if Xpos > Xmax:  Xpos = Xmax
    if Ypos > Ymax:  Ypos = Ymax
    root .geometry( f'{Width}x{Height}+{Xpos}+{Ypos}')

def clear( event ):
    global dragposX, dragposY
    dragposX, dragposY = 0, 0

left_button = tkinter .Button( root, text='<', font=font, padx=2, pady=0, bg='blue', activebackground='lightblue', command=left )
left_button .grid( row=0, column=0, padx=1, pady=4 )

right_button = tkinter .Button( root, text='>', font=font, padx=2, pady=0, bg='blue', activebackground='lightblue', command=right )
right_button .grid( row=0, column=1, padx=1, pady=4 )

down_button = tkinter .Button( root, text='v', font=font, padx=2, pady=0, command=down )
down_button .grid( row=0, column=2, padx=1, pady=4 )

up_button = tkinter .Button( root, text='^', font=font, padx=2, pady=0, command=up ) 
up_button .grid( row=0, column=3, padx=1, pady=4 )

close_button = tkinter .Button( root, text='X', font=font, padx=2, pady=0, bg='red', activebackground='pink', command=root.destroy )
close_button .grid( row=0, column=4, padx=1, pady=4 )

root .bind( '<B1-Motion>', drag )
root .bind( '<ButtonRelease-1>', clear )

root .mainloop()

答案 1 :(得分:0)

这是移动画布的简化方法。

import tkinter as tk

def realcenter( o, w, h ) ->'o(w,h) centered on screen':
    x = o.winfo_screenwidth( ) - w
    y = o.winfo_screenheight( ) - h
    o.geometry( '{0:d}x{1:d}+{2:d}+{3:d}'.format( w, h, int( x/2 ), int( y/2 ) ) )

def restore( ev ):
    master.overrideredirect( 0 )

def unrestore( ev ):
    master.overrideredirect( 1 )

master = tk.Tk()
sizew, sizeh = 400, 400
canvas_box = tk.Canvas(master, width=sizew, height=sizeh )
canvas_box.grid(row=0,column=0)

master.geometry( '400x400' )
realcenter( master, 400, 400 )

master.update_idletasks()

master.overrideredirect( 1 )

master.bind( '<F1>', restore )
master.bind( '<F2>', unrestore )

tk.mainloop()

我已经包含了一个窗口居中功能 稍微修改以使其与 2.x 兼容。

答案 2 :(得分:0)

我已经找到解决方案及其完美的工作!!!

我希望它能帮助人们做一个个性化的标题栏!!!

我的代码:

from tkinter import *
import tkinter as tk
root = Tk()
x = 0
y = 0
def move_window(event):
    # global x, y
    print(x, y)
    #event.x_the_name_of_the_widows is false you have to use x_root
    #event if your page is called win or ...
    root.geometry('+{0}+{1}'.format(event.x_root - x, event.y_root - y))

root.overrideredirect(True) # turns off title bar, geometry
root.geometry('400x200+200+200') # set new geometry

# make a frame for the title bar
title_bar = Frame(root, bg='white', relief='raised', bd=2)

# put a close button on the title bar
close_button = Button(title_bar, text='X', command=root.destroy)

# a canvas for the main area of the window
window = Canvas(root, bg='black')

# pack the widgets
title_bar.pack(expand=1, fill=X)
close_button.pack(side=RIGHT)
window.pack(expand=1, fill=BOTH)

# find the position of the cursor on the window and not on the screen

def set_xy(event):
    global x,y
    x=event.x_root - root.winfo_x()
    y=event.y_root - root.winfo_y()
    # print(x,y)
    return x,y;

title_bar.bind('<1>',set_xy)

# bind title bar motion to the move window function

title_bar.bind('<B1-Motion>', move_window)

root.mainloop()

相关问题