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
.
添加回答
舉報