Button that needs a 2nd click to approve action #2613
Replies: 6 comments
-
@chess-levin Few things you need to consider here: No need to use timer or threading at all. Also, from customtkinter import CTk, CTkButton
class ApprovalButton(CTkButton):
def __init__(self,
master: CTk,
confirm_text: str = None,
confirm_fg_color: str = None,
confirm_hover_color: str = None,
**kwargs):
self.confirm_text = confirm_text
self.confirm_fg_color = confirm_fg_color
self.confirm_hover_color = confirm_hover_color
self.callback = kwargs.pop("command", None)
kwargs["command"] = self._command
super().__init__(master, **kwargs)
self.text = kwargs["text"]
self.fg_color = kwargs["fg_color"]
self.hover_color = kwargs["hover_color"]
self._user_confirm: bool = False
self.bind("<ButtonRelease-1>", self._on_click)
def _on_click(self, e=None):
if not self._user_confirm:
self._user_confirm = True
self.configure(text=self.confirm_text,
fg_color=self.confirm_fg_color,
hover_color=self.confirm_hover_color)
self._on_enter() # Enforce hover redrawing.
else:
self._user_confirm = False
self.configure(text=self.text,
fg_color=self.fg_color,
hover_color=self.hover_color)
def _command(self):
if self.callback and self._user_confirm:
self.callback()
if __name__ == "__main__":
app = CTk()
app.configure(width=500, height=300)
btn = ApprovalButton(app,
text="Proceed",
fg_color = "green",
hover_color = "darkgreen",
confirm_text= "Confirm?",
confirm_fg_color= "#BB0000",
confirm_hover_color = "#880000",
command = lambda: print("Callback example.")
)
btn.place(relx=0.5, anchor="center", rely=0.5)
app.mainloop() Output: ctk_button_hover_redraw.mp4Also, if you want to get default colors for any widget, you can use from customtkinter import ThemeManager
button_colors = ThemeManager.theme["CTkButton"]
print(button_colors) Output:
Hope, the given information would be helpful to you. Let me know what you expect more from the above code or need any further help in this case. |
Beta Was this translation helpful? Give feedback.
-
Hi @dipeshSam, thanks for this comprehensive feedback. At the first glance I can't find the auto-reset feature in your code, that kicks in after a few seconds waiting in vain for the 2nd click. That was the reason I'm used threading.Timer for. |
Beta Was this translation helpful? Give feedback.
-
Could you please elaborate how or what functionalities you're looking for? |
Beta Was this translation helpful? Give feedback.
-
Here is the working class based on your code. The button changes color to
|
Beta Was this translation helpful? Give feedback.
-
@chess-levin I see. Introducing this feature is way easier. Also, NO need to use threading, again. Use from customtkinter import CTk, CTkButton
class ApprovalButton(CTkButton):
def __init__(self,
master: CTk,
confirm_text: str = None,
confirm_fg_color: str = None,
confirm_hover_color: str = None,
confirm_delay_ms: int = None,
**kwargs):
self.confirm_text = confirm_text
self.confirm_delay_ms = confirm_delay_ms
self.confirm_fg_color = confirm_fg_color
self.confirm_hover_color = confirm_hover_color
self.callback = kwargs.pop("command", None)
kwargs["command"] = self._command
super().__init__(master, **kwargs)
self.text = kwargs["text"]
self.fg_color = kwargs["fg_color"]
self.hover_color = kwargs["hover_color"]
self._user_confirm: bool = False
self.bind("<ButtonRelease-1>", self._on_click)
def _on_click(self, e=None):
if not self._user_confirm:
self._user_confirm = True
self.configure(text=self.confirm_text,
fg_color=self.confirm_fg_color,
hover_color=self.confirm_hover_color)
# Enforce hover redrawing.
self._on_enter()
# Calling reset function after certain time.
self.after(self.confirm_delay_ms, self._normal_back)
else:
self._normal_back()
def _normal_back(self):
if self._user_confirm:
self._user_confirm = False
self.configure(text=self.text,
fg_color=self.fg_color,
hover_color=self.hover_color)
def _command(self):
if self.callback and self._user_confirm:
self.callback()
if __name__ == "__main__":
app = CTk()
app.configure(width=500, height=300)
btn = ApprovalButton(app,
text="Proceed",
fg_color = "green",
hover_color = "darkgreen",
confirm_text= "Confirm?",
confirm_fg_color= "#BB0000",
confirm_hover_color = "#880000",
confirm_delay_ms = 1000,
command = lambda: print("Callback example.")
)
btn.place(relx=0.5, anchor="center", rely=0.5)
app.mainloop() Let me know what changes you wish further. |
Beta Was this translation helpful? Give feedback.
-
That works great. Thanks again for your support. |
Beta Was this translation helpful? Give feedback.
-
I've developed a button that needs a 2nd click before it performs the registered command. I've borrowed this idea from Insomnia tool. They used this feature to make sure the user doesn't accidentally delete something when clicking delete.
There is still an issue left in my code I couldn't solve. Maybe one of you guys could help?
While clicking the button for the 1st time, the mouse hovers over the button. That triggers the mouse over color (mode) and that leads to a quick change of the color to red and back to the old color of the mouse over mode. But I want the color to stay in red (or darkred).
When I then move the mouse away from the button (after 1st click) and move it back again the color stays red.
How can I get rid of the initial color flickering?
Beta Was this translation helpful? Give feedback.
All reactions