1 回答
TA贡献1859条经验 获得超6个赞
您有两个问题,都与您的类依赖于全局数据这一事实有关:您正在使用bind_all它有效地创建全局绑定,并且您对普通和占位符使用相同的样式,但样式是全局的。
第一个问题是您对bind_all. 每次创建实例时,bind_all该实例的绑定都会替换前一个实例的绑定。两个实例都将继承一个绑定,该绑定仅调用最后创建的实例的_normal和方法。_cursor
作为一般经验法则,像这样的类应该始终只在其自身上创建绑定。您需要更改self.bind_all为仅self.bind.
self.bind('<Key>', self._normal)
self.bind('<Button-1>', self._cursor)
第二个问题是您对样式的使用。您在两种状态下的两个小部件都使用单一样式,但由于样式是全局的,因此当您更改一个小部件中的样式时,它会影响另一个小部件。
您不应该重新配置单一样式,而应该配置两种样式并在它们之间切换。例如,您可以my.TEntry为正常情况创建一个样式,并placeholder.TEntry为您想要显示占位符时创建一个样式。
首先在方法中配置样式__init__:
def __init__(self, master, placeholder, **kwargs):
# style for ttk widget
self.s = ttk.Style()
self.s.configure('my.TEntry', foreground='black', font=(0, 0, 'normal'))
self.s.configure('placeholder.TEntry', foreground='grey', font=(0, 0, 'bold'))
接下来,无需重新配置样式定义,只需交换小部件上的样式即可。例如,_clear看起来像这样:
def _clear(self, *args): # method to remove the placeholder
if self.get() == self.text and self.__has_placeholder:
self.configure(style="my.TEntry")
...
同样,_add应该看起来像这样:
def _add(self, *args): # method to add placeholder
if self.get() == '' and not self.__has_placeholder: # if no text add placeholder
self.configure(style="placeholder.TEntry")
...
最后,您的逻辑有一个错误,可能是由于误解了绑定的工作原理。当您绑定到 时<Key>,该绑定发生在默认绑定之前。因此,您检查条目self._add是否为空的位置发生在插入您刚刚键入的密钥之前。因此,代码认为条目小部件是空的,并将样式切换为具有占位符。因此,它添加占位符文本,然后发生键的默认处理并插入键。
该特定问题至少有三种解决方案。
您可以绑定 on
<KeyRelease>
而不是,<Key>
因为它将在默认绑定插入字符后触发。您可以在默认绑定之后添加自定义绑定标签,以便首先发生默认绑定,然后再发生您的绑定。
你可以坚持使用
bind_all
. 在这种情况下,您只需要进行一次绑定,而不是每个小部件一次,并且您需要调整您的函数以使用event.widget
而不是self
.
添加回答
举报