如何在没有主按钮的情况下创建用于移动 window 的按钮?
How to create a button for moving the window without the main button?
我是法国人所以我的英语有点差所以不要注意。
我做了一个 tkinter
计算器,为此我删除了标题和关闭按钮所在的 window 的顶部,并用 canvas 替换它,它看起来非常好,但是我无法再移动屏幕上的 window,window 停留在 upper-left 角 ,我无法移动它方式...我希望有人能有想法。
用于删除顶部的 window 我使用了 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()
...
给出这个参数
我有另一个想法:是否可以将标题栏放在我的 canvas 前面,当它在我的退出按钮和菜单前面时隐藏它并且可爱?所以我们没有看到它,但它正常工作
设置根.geometry( Width x Height + X + Y )
.
保持宽度和高度相同,只需更改 X 和 Y 参数。
编辑: 是的,这有点复杂。您需要存储初始拖动位置,然后从后续事件中减去它。释放按钮后清除值。您还想设置最小/最大值以确保它不会超出屏幕范围。
#! /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()
这里有一个简单的移动方法canvas。
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()
我添加了一个 window 居中函数
稍作修改,使其 2.x 兼容。
我已经找到解决方案及其工作完美!!!
希望帮助人做一个个性化的标题栏!!!
我的代码:
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()
我是法国人所以我的英语有点差所以不要注意。
我做了一个 tkinter
计算器,为此我删除了标题和关闭按钮所在的 window 的顶部,并用 canvas 替换它,它看起来非常好,但是我无法再移动屏幕上的 window,window 停留在 upper-left 角 ,我无法移动它方式...我希望有人能有想法。
用于删除顶部的 window 我使用了 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()
...
我有另一个想法:是否可以将标题栏放在我的 canvas 前面,当它在我的退出按钮和菜单前面时隐藏它并且可爱?所以我们没有看到它,但它正常工作
设置根.geometry( Width x Height + X + Y )
.
保持宽度和高度相同,只需更改 X 和 Y 参数。
编辑: 是的,这有点复杂。您需要存储初始拖动位置,然后从后续事件中减去它。释放按钮后清除值。您还想设置最小/最大值以确保它不会超出屏幕范围。
#! /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()
这里有一个简单的移动方法canvas。
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()
我添加了一个 window 居中函数 稍作修改,使其 2.x 兼容。
我已经找到解决方案及其工作完美!!!
希望帮助人做一个个性化的标题栏!!!
我的代码:
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()