我想根据用户是否点击它来定制tkinter PanedWindow上的窗扇的外观,所以我用这个来做。
import tkinter as tk
from tkinter import ttk
class PanedTest(tk.Tk):
def __init__(self, master = None) -> None:
super().__init__(master)
self.style = ttk.Style()
self.style.configure('TPanedwindow', background='black')
self.style.configure('Clicked.TPanedwindow', background='blue')
self.style.configure('Sash', sashthickness = 8)
self.bind_class('TPanedwindow', '<Button-1>', lambda e : e.widget.configure(style = 'Clicked.TPanedwindow'))
self.bind_class('TPanedwindow', '<B1-Motion>', lambda e : e.widget.sash_place(0, e.x, e.y))
self.bind_class('TPanedwindow', '<ButtonRelease-1>', lambda e : e.widget.configure(style = 'TPanedwindow'))
self.paned1 = ttk.PanedWindow()
self.paned1.pack()
self.frame1 = ttk.Frame(self.paned1, width = 200, height = 200)
self.paned1.add(self.frame1)
self.frame2 = ttk.Frame(self.paned1, width = 200, height = 200)
self.paned1.add(self.frame2)
self.paned2 = ttk.PanedWindow(orient = 'horizontal')
self.paned2.pack()
self.frame3 = ttk.Frame(self.paned2, width = 200, height = 200)
self.paned2.add(self.frame3)
self.frame4 = ttk.Frame(self.paned2, width = 200, height = 200)
self.paned2.add(self.frame4)
if __name__ == "__main__":
app = PanedTest()
app.mainloop()
不幸的是,这会导致错误
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Program Files\Python310\lib\tkinter\__init__.py", line 1921, in __call__
return self.func(*args)
File "paned_test.py", line 15, in <lambda>
self.bind_class('TPanedwindow', '<B1-Motion>', lambda e : e.widget.sash_place(0, e.x, e.y))
File "C:\Program Files\Python310\lib\tkinter\__init__.py", line 4490, in sash_place
return self.sash("place", index, x, y)
File "C:\Program Files\Python310\lib\tkinter\__init__.py", line 4464, in sash
self.tk.call((self._w, 'sash') + args)) or ()
_tkinter.TclError: wrong # args: should be ".!panedwindow2 sashpos index ?newpos?"
所以经过大量的测试,我设法让它和这个一起工作
import tkinter as tk
from tkinter import ttk
class PanedTest(tk.Tk):
def __init__(self, master = None) -> None:
super().__init__(master)
self.style = ttk.Style()
self.style.configure('TPanedwindow', background='black')
self.style.configure('Clicked.TPanedwindow', background='blue')
self.style.configure('Sash', sashthickness = 8)
self.bind_class('TPanedwindow', '<Button-1>', lambda e : e.widget.configure(style = 'Clicked.TPanedwindow'))
self.bind_class('TPanedwindow', '<B1-Motion>', lambda e : e.widget.sash(0, (e.x if str(e.widget.cget('orient')) == 'horizontal' else e.y)))
self.bind_class('TPanedwindow', '<ButtonRelease-1>', lambda e : e.widget.configure(style = 'TPanedwindow'))
self.paned1 = ttk.PanedWindow()
self.paned1.pack()
self.frame1 = ttk.Frame(self.paned1, width = 200, height = 200)
self.paned1.add(self.frame1)
self.frame2 = ttk.Frame(self.paned1, width = 200, height = 200)
self.paned1.add(self.frame2)
self.paned2 = ttk.PanedWindow(orient = 'horizontal')
self.paned2.pack()
self.frame3 = ttk.Frame(self.paned2, width = 200, height = 200)
self.paned2.add(self.frame3)
self.frame4 = ttk.Frame(self.paned2, width = 200, height = 200)
self.paned2.add(self.frame4)
if __name__ == "__main__":
app = PanedTest()
app.mainloop()
我现在可以拖动窗格窗口,但它也给予这个错误
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Program Files\Python310\lib\tkinter\__init__.py", line 1921, in __call__
return self.func(*args)
File "paned_test.py", line 48, in <lambda>
self.bind_class('TPanedwindow', '<B1-Motion>', lambda e : e.widget.sash(0, (e.x if str(e.widget.cget('orient')) == 'horizontal' else e.y)))
File "C:\Program Files\Python310\lib\tkinter\__init__.py", line 4463, in sash
return self._getints(
File "C:\Program Files\Python310\lib\tkinter\__init__.py", line 1467, in _getints
return tuple(map(self.tk.getint, self.tk.splitlist(string)))
TypeError: splitlist() argument must be str, bytes or bytearray, not int
下面是两个脚本之间的区别
self.bind_class('TPanedwindow', '<B1-Motion>', lambda e : e.widget.sash_place(0, e.x, e.y))
vs
self.bind_class('TPanedwindow', '<B1-Motion>', lambda e : e.widget.sash(0, (e.x if str(e.widget.cget('orient')) == 'horizontal' else e.y)))
为什么只有第二个函数起作用,而不是专门针对我要做的事情的函数?
哦,把e.widget.cget('orient')
转换成str只是因为结果是<class '_tkinter.Tcl_Obj'>
。
1条答案
按热度按时间xfyts7mz1#
这可能是
tkinter
上的一个bug。对于使用e.widget.sash_place(0, e.x, e.y)
的第一个代码,它只是在内部调用self.sash('place', index, x, y)
,这会引发参数数量无效错误,因为.sash()
只需要两个参数,index
和pos
(即index
和pos
)。如何在第二个代码块中使用.sash()
。但是在
.sash()
内部,它在self.tk.call(...)
的结果上调用self._getints()
,self.tk.call(...)
是一个整数,但是self._getints()
需要一个字符串。这就是第二个错误的含义。为了避免第二个错误,可以直接使用
e.widget.tk.call()
而不是.sash()
: