Ваша ошибка должна сказать вам все, что вам нужно здесь.
unsupported operand type(s) for +: 'int' and 'str'
Это говорит о том, что вы не можете добавлять целые числа и строку вместе. Одно простое решение - изменить эту строку:
self.geometry(self.winfo_width() + 'x' + self.winfo_height() + '+{0}+{1}'.format(event.x_root + xwin, event.y_root + ywin))
На это:
self.geometry(str(self.winfo_width()) + 'x' + str(self.winfo_height()) + '+{0}+{1}'.format(event.x_root + xwin, event.y_root + ywin))
Преобразовав целое число, которое winfo
возвращает в строку, вы можете объединить без проблем.
Тем не менее, вместо этого я использовал бы format()
для всех переменных здесь.
Вот как я бы написал эту строку кода:
self.geometry('{}x{}+{}+{}'.format(self.winfo_width(), self.winfo_height(), event.x_root + xwin, event.y_root + ywin))
Все это сказал, что я вижу несколько других проблем, которые должны быть решены для правильной работы вашего кода.
Вам не нужно использовать оба from tkinter import *
и import tkinter as tk
. Просто используйте import tkinter as tk
. Это предпочтительный метод, так как он помогает предотвратить перезапись методов.
Вам не нужно определять все как атрибут класса, поэтому сокращайте использование self.
только там, где это необходимо .
Следуйте стандартному соглашению об именах. Потратьте некоторое время на чтение PEP8.
Ваша функция OnMotion
имеет return
без причины. Эта строка может быть удалена.
Вы используете функции внутри класса, а также global
. Одним из основных преимуществ для класса является возможность избежать global
с помощью атрибута класса. Поэтому я переместил вашу переменную size_change
в __init__
, а затем изменил вашу функцию на метод для get_pos
.
В вашей функции OnMotion
вы выполняли size_change = True
но вы уже определили эту переменную как BooleanVar()
, поэтому вам нужно вместо этого установить значение. Вот так: size_change.set(True)
.
См. Приведенный ниже код:
import tkinter as tk
from tkinter import ttk
class Example(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.floater = FloatingWindow()
self.withdraw()
class FloatingWindow(tk.Toplevel):
def __init__(self):
super().__init__()
self.overrideredirect(True)
self.wm_geometry("400x400")
self.size_change = tk.BooleanVar()
self.label = tk.Label(self, text="Grab the lower-right corner to resize")
self.label.pack(side="bottom", fill="both", expand=True)
canvas_2 = tk.Canvas(self, bg='steelblue1')
canvas_2.pack(anchor='s', side='bottom')
title_bar_2 = tk.Frame(self, height=25, bg='SteelBlue1', relief='raised', bd=1)
title_bar_2.pack(anchor='n', fill='x', side="bottom")
tk.Button(title_bar_2, text='X', command=self.end_app_2).pack(fill='x', side="right")
grip = ttk.Sizegrip(self)
grip.place(relx=1.0, rely=1.0, anchor="se")
grip.lift(self.label)
grip.bind("<B1-Motion>", self.on_motion)
self.bind('<Button-1>', self.get_pos)
def end_app_2(self):
self.destroy()
def get_pos(self, event):
xwin = self.winfo_x()
ywin = self.winfo_y()
startx = event.x_root
starty = event.y_root
ywin = ywin - starty
xwin = xwin - startx
def move_window(event):
if self.size_change:
self.geometry('{}x{}+{}+{}'.format(self.winfo_width(), self.winfo_height(),
event.x_root + xwin, event.y_root + ywin))
else:
self.geometry('400x400' + '+{0}+{1}'.format(event.x_root + xwin, event.y_root + ywin))
if ywin >= -199:
self.bind('<B1-Motion>', move_window)
def on_motion(self, _=None):
x1 = self.winfo_pointerx()
y1 = self.winfo_pointery()
x0 = self.winfo_rootx()
y0 = self.winfo_rooty()
self.geometry("%sx%s" % ((x1-x0), (y1-y0)))
self.size_change.set(True)
if __name__ == '__main__':
app = Example().mainloop()
Все, что говорит, я думаю, что это сложнее, чем нужно. После попытки решить проблему с помощью метода on_motion
, я решил просто переписать все, так как хороший раздел кода даже не требовался для получения функциональности.
Я считаю, что:
if ywin >= -199:
self.bind('<B1-Motion>', move_window)
Была причиной проблемы после изменения размера.
Попробуйте этот код и дайте мне знать, если у вас есть какие-либо вопросы:
import tkinter as tk
import tkinter.ttk as ttk
class Win(tk.Tk):
def __init__(self):
super().__init__()
self.columnconfigure(0, weight=1)
self.rowconfigure(2, weight=1)
self.overrideredirect(True)
self.wm_geometry("400x400")
self.minsize(400, 400)
self.x = 0
self.y = 0
title_bar_2 = tk.Frame(self, height=25, bg='SteelBlue1', relief='raised', bd=1)
title_bar_2.grid(row=0, column=0, sticky='ew')
tk.Button(title_bar_2, text='X', command=self.destroy).pack(fill='x', side="right")
self.canvas_2 = tk.Canvas(self, bg='steelblue1')
self.canvas_2.grid(row=1, column=0)
tk.Label(self, text="Grab the lower-right corner to resize").grid(row=2, column=0)
grip = ttk.Sizegrip(self)
grip.place(relx=1.0, rely=1.0, anchor="se")
title_bar_2.bind('<ButtonPress-1>', self.button_press)
title_bar_2.bind('<B1-Motion>', self.move_window)
def move_window(self, event):
x = self.winfo_pointerx() - self.x
y = self.winfo_pointery() - self.y
self.geometry('+{}+{}'.format(x, y))
def button_press(self, event):
self.x = event.x
self.y = event.y
win = Win()
win.mainloop()