Skip to content

Comments

Merging from Develop branch#2785

Open
FedericoSpada wants to merge 36 commits intomasterfrom
develop
Open

Merging from Develop branch#2785
FedericoSpada wants to merge 36 commits intomasterfrom
develop

Conversation

@FedericoSpada
Copy link
Collaborator

Version 5.3.0

TomSchimansky and others added 30 commits July 11, 2023 14:15
Updated the README to include developer contact information and improved formatting.
Added a predefined App to display all available widgets, similar to complex_example.py, but directly available in the downloaded version of the library, so that any user can see it without the need to download a separate file.
Co-authored-by: Anustuv Pal <anustuv@gmail.com>
Co-authored-by: LYMwyh <122608577+LYMwyh@users.noreply.github.com>
Prevents triggering a bug on Tk canvas, where float parameters use locally-aware parsing and thus might expect a different decimal point character

Fixes #571
CTkScrollableFrame was not fully removed when its destroy() method was invoked.
Changes:
1. The renaming method in the `CTkTabview` class has been altered. Instead of removing the old name from the `_name_list` and appending the new name at the end, the new name now replaces the old name at the same index in the `_name_list`. This change makes the renaming process more efficient.
2. Code has been added to update the `_current_name` attribute if the old name matches the current name. This is a crucial change as it ensures that the connection to the frame is not lost when a tab is renamed.
Merge pull request #2784 from bibo19842003/patch-1
Co-authored-by: gdx <gdx>
Looks like there was a leftover variable waiting to be replaced from a copy-paste.
Fixed issue #1899 by resetting the minsize
Adding two methods to the class CTkTabview":
"index" to return the index (position) of the current tab or the tab entered as an attribute.
"len" method to return the number of defined tabs

Modifying the "get" method: it now returns the name of the selected tab, or an empty string if no tab is selected. If an index is defined, it returns the name associated with that index.
… redundant object creation (#2680)

Co-authored-by: Dariusz Klofik <darek@merge.pl>
Co-authored-by: ElectricCandlelight <ecandlelight@gmail.com>
Added missing attributes to the cget() method for all widgets.
Fixed some attribute names and positions within the method.
Fixes #1212, #2615, #2756
Added the possibility to specify border_width and border_color to the CTkLabel, so that there is no need to use CTkButton as a Static Label if a border is needed.
By default, it is still hidden as before.
Fixes #2612
Implemented the MouseWheel scroll detection for the CTkSlider to update its value based on the new attribute scroll_step.
Added the management of MouseWheel scroll detection to CTkScrollbar, even when the command function is not provided. In this way, at least the widget is responsive.
Fixed MouseWheel scroll detection on CTkScrollbar that didn't work on Linux systems.
Fixes #2388, #2777 and replace #2365

Co-Authored-By: Saul Velazquez <141290146+save-27@users.noreply.github.com>
- Added missing attributes to the configure() method for all widgets.
- Allowed changing a CTkButton image using configure even if the widget was created without any image.
- Prevented warning when an image is set to "" with configure() to delete it.
- Fixed CTkCheckbox hover_color for the blue theme, which was hiding the hover effect when checked.
Fixes #1215, #1750, #2494 and replaces #2412, #2719

Co-Authored-By: Shubham25dec <107737999+shubham25dec@users.noreply.github.com>
Co-Authored-By: fred Jose Diaz <33442727+fredmain@users.noreply.github.com>
Added set(), index(), len() methods for those widgets that were suitable to use them.
Fixes #1862
FedericoSpada and others added 5 commits January 17, 2026 19:33
- CTkButton triggers the command when the Mouse Button is released, allowing the user to cancel the click by releasing the button outside the widget
- CTkEntry and CTkTextbox lose focus when you click somewhere else
- Clicking the Dropdown button again closes the menu for CTkComboBox and CTkOptionMenu
Fixes #2126, #2257, #2386, #2722 and replaces #2251, #2736

Co-Authored-By: Jan Görl <JanPanthera@outlook.de>
Co-Authored-By: Rivka Sternbuch <210291359+riki-sternbuch@users.noreply.github.com>
- Properly managed textvariable attribute for CTkEntry
- Properly justified Label and Image inside CTkButton
- Added gold theme and standardized spacing and case for the others
Fixes #1981, #2743 and replaces #2077, #2173, #2741

Co-Authored-By: federicomassi <5929004+federicomassi@users.noreply.github.com>
Co-Authored-By: Pedro Perdigão <91698253+p3rdigas@users.noreply.github.com>
Co-Authored-By: Nerogar <3390934+nerogar@users.noreply.github.com>
- Reported all previous changes in the CHANGELOG.md file
- Added guidelines to dev-proces.md file
- Little improvements to the Showroom App
After additional testing, some special cases have emerged that break some of the new features that have been introduced with the last commits.
These changes should solve most of the problems.
@qwertyzen
Copy link

This branch has some good features and bug fixes. I only have issue with one. The new feature where mouse-wheel affects CTkSlider value is undesirable behavior. A parent widget or root may bind mouse-wheel for other functions. So changing the new slider value with mouse-wheel also performs the other action.

In my app, I have used bind mouse-wheel to the root window to change a specific slider in the GUI. So I can change this slider with the pointer being anywhere in the window. This feature was requested by users.

@FedericoSpada
Copy link
Collaborator Author

Hi,
Yours is a very specific case that we can't consider while implementing a new feature.
Moreover, the MouseWheel was already used for the scrollbars, so your design would break already if you ever need to add a CTkScrollbar, CTkTextbox, or CTkScrollableFrame.

I would suggest improving your callback so that it doesn't perform its action if it detects that the mouse wheel was moved over a CTkSlider or CTkScrollbar. Something similar to the following:

def mousewheel_event(self, event: tk.Event) -> None:
    skip = False
    widget = event.widget
    while widget is not None:
        if isinstance(widget, (CTkSlider, CTkScrollbar)):
            skip = True
            break
        widget = widget.master

    if not skip:
        #your actual operation here

In this way, you would benefit from the new change: if the user scrolls the wheel over a Slider or Scrollbar, its value gets updated. If, instead, he/she scrolls elsewhere, a specific Slider would move as before.

@qwertyzen
Copy link

qwertyzen commented Feb 24, 2026

Since you mentioned other widgets that bind to mouse-wheel, I tried out an experiment to see how the slider scrolling behaves in a general context. Please have a look at the following example code. This could be an EQ panel in a music app. This will demonstrate the point I was trying to make about this not being a good feature.

import customtkinter as ctk

root = ctk.CTk()
root.geometry('300x400')

sfr = ctk.CTkScrollableFrame(root)
sfr.pack(fill='both', expand='True')
sfr.grid_columnconfigure(0, weight=1)
for i in range(20):
    sl = ctk.CTkSlider(sfr)
    sl.grid(row=i, column=0, sticky='ew', padx=10, pady=10)

root.mainloop()

Scrolling on a specific slider does not reliably modify that slider. Instead, the frame also scrolls and modifies other sliders. If I intend to scroll the window, it also modifies the sliders. Do you think this is reliable behavior?

As a GUI framework you cannot say what is or is not standard GUI practice. As a basic feature, tkinter gives me the ability to bind <mouse-wheel> to the root widget to implement any feature. So I am doing very standard stuff here. Every app have their own unique features and requirements. As an app developer I don't want to hack/fight against the framework (as your solution suggests). A slider is a slider, not a scroller. If an app wants it to scroll, the app developer will add the scroll to it.

If you want the feature, add a new widget called CTkScrollingSlider, so it's explicit. Messing with the default slider will break apps and cause pain to your users.

@FedericoSpada
Copy link
Collaborator Author

You are right: this is unwarranted behavior that I didn't anticipate. But the problem is and was already present, if you add any scrollable object inside CTkScrollableFrame, like CTkTextbox, CTkScrollbar, and another instance of CTkScrollableFrame itself.
I will improve the MouseWheel callback for CTkScrollableFrame so that it works properly.

The change on the Slider was requested in #2777, and I agree with the proposer that it is expected to use the MouseWheel on a slider to change its value. As a library user, I don't want to implement the Scroll behavior each time I use the widget.

tk.Text itself uses by default the MouseWheel event to scroll its view. Binding a callback to the MouseWheel for the entire window will cause problems in any case and with both frameworks. As a developer, it should be our job to find the best solution given the tools we have available.

If other scrollable widgets are placed inside CTkScrollableFrame, the MouseWheel event would be triggered on all of them, making them move at the same time.
With these improvement, the CTkScrollableFrame doesn't change its view if it detects that the mouse is over a child scrollable widget.
@qwertyzen
Copy link

qwertyzen commented Feb 25, 2026

Hi @FedericoSpada please check the example program I provided in the above comment against your latest commit Improved scroll behavior for CTkScrollableFrame.

This behavior is also unreliable. Now what happens is that the sliders consume the mouse scroll and the scrollable frame stops scrolling as soon as a slider arrives under the mouse pointer and the slider value changes. In this example the ScrollableFrame mouse scrolling is completely untenable. The expectation is that the ScrollableFrame should have priority of the scrolling action.

Please think deeply about this feature and I would like to know what @TomSchimansky thinks about this. I personally think

  • Yes, a library developer should intentionally bind mouse-wheel to each Slider they want to scroll.
  • Otherwise, provide a separate widget called CTkScrollingSlider to add this as a feature. Optionally, make it opt-in/opt-out, example CTkSlider(parent, update_on_scroll=False, ...).
  • This feature does not align with the philosophy of customtkinter and tkinter.
  • Don't add a feature for 1000s based on an issue by 1 user. There needs to be community agreement. Please have a committee. Lot's of users rely on customtkinter being stable and deterministic.

P.S: I am aware that cross-platform mouse-scroll is an issue in tkinter with <mouse-wheel>, <Button-4>, <Button-5>, and the event values and attributes being different for each platform. So a user has to implement scrolling for each platform separately. You can provide a custom event <<CTkMouseWheel>> that abstracts away these differences. Then the user or the library just has to bind to this event to get cross-platform scrolling behavior. This would much better align with customtkinter's philosophy.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.