创建这个类的两个实例会创建奇怪的行为tkinter python

创建这个类的两个实例会创建奇怪的行为tkinter python,python,class,oop,tkinter,placeholder,Python,Class,Oop,Tkinter,Placeholder,我创建了一个自定义占位符条目类,该类继承自ttk.entry。问题是,它只与实例化一起工作一次,如果我为同一个条目创建两个实例,它将开始显示一些奇怪的效果 类及其用法: 将tkinter作为tk导入 从tkinter导入ttk 类占位符条目(ttk.Entry): ''' 自定义现代占位符输入框,采用位置参数主控符和占位符\n 使用acquire()从条目小部件获取输出\n 使用SHOW()插入条目小部件\n 使用remove()从条目小部件中删除\n 使用length()获取小部件中文本的长度

我创建了一个自定义占位符条目类,该类继承自
ttk.entry
。问题是,它只与实例化一起工作一次,如果我为同一个条目创建两个实例,它将开始显示一些奇怪的效果

类及其用法:

将tkinter作为tk导入
从tkinter导入ttk
类占位符条目(ttk.Entry):
'''
自定义现代占位符输入框,采用位置参数主控符和占位符\n
使用acquire()从条目小部件获取输出\n
使用SHOW()插入条目小部件\n
使用remove()从条目小部件中删除\n
使用length()获取小部件中文本的长度\n
错误1:绑定到此类时可能存在错误\n
错误2:配置或配置方法的异常行为
'''
定义初始化(自身、主控、占位符,**kwargs):
#ttk小部件的样式
self.s=ttk.Style()
self.s.configure('my.TEntry'))
#初始输入框
ttk.Entry.\uuuuu init\uuuuuuuuuuuuu(self,master,style='my.TEntry',**kwargs)
self.text=占位符
self._有_占位符=假#占位符标志
#如果框为空,则添加占位符
self._add()
#小部件的绑定
self.bind(“”,self.\u清除)
self.bind(“”,self.\u add)
self.bind_all('',self._normal)
self.bind_all(“”,self._光标)
def_clear(self,*args):#删除占位符的方法
如果self.get()==self.text和self.\u有占位符:#获得焦点时移除占位符
self.delete(0,tk.END)
self.s.configure('my.TEntry',前台='black',
字体=(0,0,'normal'))
self.u有_占位符=False#将标志设置为False
def_add(self,*args):#添加占位符的方法
如果self.get()==''而不是self.u有u占位符:35;如果没有文本,则添加占位符
self.s.configure('my.TEntry',前台='grey',
字体=(0,0,'粗体')
self.insert(0,self.text)#插入占位符
self.icursor(0)#将插入光标移动到entrybox的开头
self.u有u占位符=True#将标志设置为True
def_normal(self,*args):#将文本设置为normal属性的方法
self._add()#如果为空,则添加占位符
如果self.get()==self.text和self.\u有\u占位符:#如果开始键入,请清除占位符
self.bind(“”,self.\u清除)
self.icursor(-1)#将插入光标保持在末尾
其他:
self.s.configure('my.TEntry',前台='black',
字体=(0,0,'normal')#设置普通字体
def acquire(self):#获取文本的自定义方法
如果self.get()==self.text和self.\u有\u占位符:
返回“无”
其他:
返回self.get()
def SHOW(self、index、string):#要插入到条目中的自定义方法
自清
self.insert(索引、字符串)
def remove(self、first、last):#从条目中删除的自定义方法
如果self.get()!=self.text:
self.delete(第一个,最后一个)
self._add()
elif self.acquire()==self.text而非self.\u有\u占位符:
self.delete(第一个,最后一个)
self._add()
def长度(自身):
如果self.get()==self.text和self.\u有\u占位符:
返回0
其他:
返回len(self.get())
def_游标(self,*args):#当占位符存在时,不允许用户移动游标的方法
如果self.get()==self.text和self.\u有\u占位符:
自我约束(0)
#MRE
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
root=tk.tk()
e1=占位符条目(根,“第一个条目”)
e1.pack()
e2=占位符条目(根,“第二个条目”)
e2.pack()
root.mainloop()
在这里单击其中一个条目并将焦点更改为下一个条目时,您可以注意到两个实例之间存在某种链接的“行为”?虽然只有一个实例可以很好地工作。这是我的第一个OOP项目,所以我不确定出了什么问题


提前感谢:D

您有两个问题,都与您的类依赖于全局数据这一事实有关:您使用的是有效创建全局绑定的
bind\u all
,并且您对普通和占位符使用相同的样式,但样式是全局的

第一个问题是使用
bind\u all
。每次创建实例时,该实例的
bind\u all
将替换上一个实例的绑定。这两个实例都将继承一个绑定,该绑定只调用上次创建的实例的
\u normal
\u cursor
方法

一般来说,这样的类应该只在自身上创建绑定。您需要将
self.bind\u all
更改为just
self.bind

self.bind('<Key>', self._normal)
self.bind('<Button-1>', self._cursor)
接下来,不必重新配置样式定义,只需在小部件上交换样式即可。例如,
\u clear
的外观如下:

def _clear(self, *args):  # method to remove the placeholder
    if self.get() == self.text and self.__has_placeholder:  
        self.configure(style="my.TEntry")
        ...
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")
        ...
类似地,
\u add
应该如下所示:

def _clear(self, *args):  # method to remove the placeholder
    if self.get() == self.text and self.__has_placeholder:  
        self.configure(style="my.TEntry")
        ...
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")
        ...
最后,您的逻辑中有一个bug,可能是由于对绑定如何工作的误解。当您绑定到
时,该绑定发生在默认绑定之前。因此,您的签入
self.\u add
检查条目是否为空发生在您刚刚键入的密钥插入之前。因此,代码认为条目小部件为空,并将样式切换为具有占位符。因此,它会添加占位符文本,然后执行键的默认处理并插入键

这个问题至少有三种解决方案

  • 您可以使用
    而不是
    进行绑定,因为在默认bindi插入字符后,将触发该操作