tkinter - 如果我单击覆盖重定向的窗口并移动它(窗口),如何获得更好的窗口位置?
问题描述
当我单击窗口时(在我的情况下,当我单击self.top_frame
and时self.app_name
)移动它,窗口位置变为 0 x 和 y 坐标。所以如果我想移动窗口,窗口会移动到右侧。我可以修复它,以使窗口不会移动到右侧(或从我的光标)?
from tkinter import *
from tkinter import ttk
#from controls import call_back
#import random
class MainWindow:
def __init__(self):
# lists
# color list [0] frame main bg [1] navibar [2] border color [3] status bar [4] Description Font
self.color_lst = ["#363e4a", "#1d2128", "#8b9ebf", "#2b303b", "#45505f"]
# button list [0] Home [1] Keyboard [2] Music [3] Timer [4] Setting Bar [5] exit [6] minimize
self.btn_list = ["\u2263","\u2328","\u266B","\u23F1","\u2348","\u26CC","\u268A"]
# control list [0] [1] [2] [3] [4] move setting bar
self.controls = ["","","","",self.setting_move]
# window settings, background, transparent, geometry
self.root = Tk()
self.root.geometry("1150x800")
self.root.minsize(400, 400)
self.root.overrideredirect(1) # <------------
self.root.resizable(True, True)
# create a background frame (border)
self.background_frame = Frame(self.root, bg=self.color_lst[2])
self.background_frame.pack(expand=YES, fill=BOTH)
# create a background frame
self.background = Frame(self.background_frame, bg=self.color_lst[0])
self.background.pack(expand=YES, fill=BOTH, padx=1, pady=1)
# navigation bar
self.navi_bar = Frame(self.background, bg=self.color_lst[1])
self.navi_bar.pack(side="left", fill=Y, ipadx=40)
# setting bar
self.setting_bar = Frame(self.background, bg=self.color_lst[2])
self.setting_bar.pack(side="left", fill=Y, ipadx=0)
# top frame
self.top_frame = Frame(self.background, bg=self.color_lst[1])
self.top_frame.pack(fill=X)
self.top_frame.bind("<B1-Motion>", self.call_back) # <--------------
self.top_frame.bind("<Map>", lambda event: self.show_window(event))
# create label description in the top frame
self.top_description = Label(self.top_frame,anchor=W, padx=20, bg=self.color_lst[3], fg=self.color_lst[4], text="Application Description")
self.top_description.pack(side="bottom", anchor=SW, expand=YES, fill=X)
# exit buttton
self.exit_btn = Button(self.top_frame, bg=self.color_lst[1], fg=self.color_lst[2], text=self.btn_list[5], font=("Bahnschrift", 16), bd=0, command=self.root.destroy)
self.exit_btn.pack(side="right", anchor=E, ipadx=10)
# minimize buttton
self.minimize_btn = Button(self.top_frame, bg=self.color_lst[1], fg=self.color_lst[2], text=self.btn_list[6], font=("Bahnschrift", 16), bd=0, command=self.minimize_window)
self.minimize_btn.pack(side="right", anchor=E, ipadx=10)
# Application name
self.app_name = Label(self.top_frame,anchor=W, padx=20, bg=self.color_lst[1], fg=self.color_lst[2], font=("Bahnschrift", 14), text="Application Name")
self.app_name.pack(side="right", anchor=E, expand=YES, fill=X)
self.app_name.bind("<B1-Motion>", self.call_back) # <------------
# background for different frames
self.frames = Frame(self.background, bg=self.color_lst[0])
self.frames.pack(expand=YES, fill=BOTH, side="top")
# bottom status bar
self.bottom_bar = Label(self.background,anchor=W, padx=20, bg=self.color_lst[3], fg=self.color_lst[4], text="Application Description")
self.bottom_bar.pack(fill=X, side="bottom", ipady=2)
# resize grip
self.resize_grip = ttk.Sizegrip(self.bottom_bar)
#self.resize_grip.
self.resize_grip.pack(side="right")
self.resize_grip.bind("<B1-Motion>", self.grip_resize)
# button statement to move setting bar
self.btn_SETTINGS = False
# buttons in the navigation bar
y=0
for index in range(5):
self.btn = Button(self.navi_bar, bg=self.color_lst[1], fg=self.color_lst[2], text=self.btn_list[index], font=("Bahnschrift", 20), bd=0)
self.btn.configure(command=self.controls[index])
self.btn.place(x=0, y=y, relwidth=1, height=64)
y +=64
# function to move the setting bar
def setting_move(self):
self.x = 0
if self.btn_SETTINGS == False:
for x in range(10):
self.setting_bar.pack_configure(ipadx=self.x)
self.btn.configure(text="\u2347")
self.setting_bar.after(20)
self.setting_bar.update_idletasks()
self.x += 10
self.btn_SETTINGS = True
else:
self.setting_bar.pack_configure(ipadx=0)
self.btn.configure(text="\u2348")
self.btn_SETTINGS = False
# better graphics
def grip_resize(self, event):
self.root.update_idletasks()
# minimize the window
def minimize_window(self):
self.root.overrideredirect(0)
self.root.iconify()
# show the window
def show_window(self, event):
self.root.overrideredirect(1)
#self.root.deiconify()
# function to move the whole window (on top frame clicked) # <------------
def call_back(self, event):
self.root.geometry("+{0}+{1}".format(event.x_root,event.y_root))# <--------------
if __name__ == "__main__":
app = MainWindow()
mainloop()
我设置了一些arrows
函数和它的绑定位置,你可以更好地找到它,看看我的意思。
解决方案
尝试这个:
import tkinter as tk
class DraggableWindow(tk.Tk):
def __init__(self):
self.draggable = True
super().__init__()
self._offsetx = 0
self._offsety = 0
self.bind("<Button-1>", self.clickwin)
self.bind("<B1-Motion>", self.dragwin)
def topmost(self):
self.attributes("-topmost", True)
try:
self.attributes("-type", "splash") # Linux
except:
self.overrideredirect(True) # Windows
def dragwin(self, event):
if self.draggable:
x = self.winfo_pointerx() - self._offsetx
y = self.winfo_pointery() - self._offsety
self.geometry("+%d+%d" % (x, y))
def clickwin(self, event):
if self.draggable:
self._offsetx = event.widget.winfo_rootx() - self.winfo_rootx() + event.x
self._offsety = event.widget.winfo_rooty() - self.winfo_rooty() + event.y
root = DraggableWindow()
root.mainloop()
我很久以前做过这个 - 忘记了它是如何工作的细节。当我再次发现它是如何工作的时,我会用解释来更新它。
使窗口不可拖动更改<DraggableWindow>.draggable
为False
. 您可能还想看看这个。它支持调整大小和调整Alt-Tab
它。
推荐阅读
- three.js - Three.js 材质透明度无法按预期工作
- c# - 在cosmos C#中获取屏幕高度和宽度
- copy - dockerfile 复制指令:“in”字是什么意思?
- amazon-web-services - Cognito 用户池直接链接到 Auth API 中的 SIGNUP 端点
- html - 如何在 Bootstrap 导航栏中添加边框底部悬停效果?
- php - 使用 preg match all php 获取标签内的内容
- c++ - 如何检查 Media Foundation 是否可以实际播放文件而不仅仅是加载它
- r - Shiny中的内联文本输出
- docker - Docker运行不保存脚本创建的文件
- html - Webpack SVG 渐变问题