PySimpleGUI / PySimpleGUI

Python GUIs for Humans! PySimpleGUI is the top-rated Python application development environment. Launched in 2018 and actively developed, maintained, and supported in 2024. Transforms tkinter, Qt, WxPython, and Remi into a simple, intuitive, and fun experience for both hobbyists and expert users.
https://www.PySimpleGUI.com
Other
13.44k stars 1.83k forks source link

[Question] Coding of ColorChooserButton update #5584

Open macdeport opened 2 years ago

macdeport commented 2 years ago

Type of Issue (Enhancement, Error, Bug, Question)

Question


Environment

Operating System

Mac version ('10.10.5', ('', '', ''), 'x86_64')

PySimpleGUI Port (tkinter, Qt, Wx, Web)

tkinter


Versions

Python version (sg.sys.version)

3.9.13 (main, May 21 2022, 02:31:38) [Clang 7.0.2 (clang-700.1.81)]

PySimpleGUI Version (sg.__version__)

4.60.0.35

GUI Version (tkinter (sg.tclversion_detailed), PySide2, WxPython, Remi)

8.6.12


Your Experience In Months or Years (optional)

15 Years Python programming experience 20 Years Programming experience overall Yes Have used another Python GUI Framework? (tkinter, Qt, etc) (yes/no is fine)


Troubleshooting

These items may solve your problem. Please check those you've done by changing - [ ] to - [X]

Detailed Description

https://github.com/PySimpleGUI/PySimpleGUI/issues/3505#event-6772260331 I wanted to modify the test harness of the color chooser button https://github.com/PySimpleGUI/PySimpleGUI/issues/3505#event-6772260331 to show the select color in the button. But this update of the color is only done when I click on this window. How to modify this code so that the update is done easily ?

Code To Duplicate

import PySimpleGUI as sg

layout = [  [sg.Text('Color Chooser Test')],
            [sg.Input(key='-COLOR1-',enable_events=True),
             sg.ColorChooserButton('Color',key='-COLOR1b-')],
            [sg.Input(key='-COLOR2-'),
             sg.ColorChooserButton('blue',default_color='blue')],
            [sg.Input(key='-COLOR3-'),
             sg.ColorChooserButton('#112233',default_color='#112233')],
            [sg.Button('Go'), sg.Button('Exit')]  ]

window = sg.Window('Color chooser Test', layout)

while True:
    event, values = window.read()
    print(event, values)
    if event == sg.WIN_CLOSED or event == 'Exit':
        break
    if event == '-COLOR1-':
        window['-COLOR1b-'].update(button_color=values[event])

window.close()

Screenshot, Sketch, or Drawing

jason990420 commented 2 years ago

Following is my code for it

import PySimpleGUI as sg

def Column(color, key_index):
    layout = [
        [sg.Input(color, size=10, key=f'IN {key_index}', enable_events=True, disabled=True),
         sg.ColorChooserButton(button_text=color, target=f'IN {key_index}', size=7, default_color=color, button_color=(sg.theme_button_color_text(), color), key=f'Button {key_index}')],
    ]
    return sg.Column(layout)

sg.theme('DarkBlue3')
sg.set_options(font=('Courier New', 16))

layout = [
    [Column(color, i)] for i, color in enumerate((sg.theme_button_color_background(), 'blue', '#112233'))] + [
    [sg.Push(), sg.Button('Exit'), sg.Push()]
]
window = sg.Window('Color chooser Test', layout, finalize=True)

while True:

    event, values = window.read()

    if event in (sg.WIN_CLOSED, 'Exit'):
        break
    if event.startswith('IN'):
        element, key_index = event.split(' ')
        color = values[event]
        if color != 'None':
            window[f'Button {key_index}'].update(text=color, button_color=(sg.theme_button_color_text(), color))
            window[f'Button {key_index}'].default_color =  color
        else:   # or it will be 'None' in Inout element
            window[event].update(window[f'Button {key_index}'].get_text())

window.close()

image

Note: Something found when I built the code

macdeport commented 2 years ago

Thanks for your nice piece of code as always.

However, this code has exactly the same behavior on my macOS machine as mine (more embryonic): macOS can be "blamed" (sorry for Mike hairs ;-) ).

This behavior is also similar to the one of the combobox button which remains selected (if it has been used) before a click in the concerned window... still on macOS.

PySimpleGUI commented 2 years ago

Is this not a duplicate issue?

PySimpleGUI commented 2 years ago

For chooser buttons that you want events for, one approach that's worked well in the past is similar to Jason's except the Inputs are made invisible. This allows you to do whatever you want without the user interfering. You can still have another Input element for the user as well.

Which bug is showing up for you on this one? Can you add a link to it?

I've been working this 8.6.12 problem in the background... contacting friends that know tkinter well, getting advice for approach, etc. It's starting to impact so many areas, particularly on the Mac but I'm struggling to determine if there is a single root cause that's in 8.6.12. The Window not appearing, for example, is difficult to pin to the same 8.6.12 problem, but does appear to be 8.6.12 specific.

PySimpleGUI commented 2 years ago

Checked in version 4.60.0.37. I added expand_x and expand_y to all buttons now... this includes the shortcut buttons and the chooser buttons.

For Buttons in a Column the column needs to have expand_x set as well. This is why they did not expand when manually performed.

import PySimpleGUI as sg

def Column(color, key_index):
    layout = [
        [sg.Input(color, size=10, key=f'IN {key_index}', enable_events=True, disabled=True),
         sg.ColorChooserButton(button_text=color, target=f'IN {key_index}',  expand_x=True, default_color=color, button_color=(sg.theme_button_color_text(), color), key=f'Button {key_index}')],
    ]
    return sg.Column(layout, expand_x=True)

sg.theme('DarkBlue3')
sg.set_options(font=('Courier New', 16))

layout = [
    [Column(color, i)] for i, color in enumerate((sg.theme_button_color_background(), 'blue', '#112233'))] + [
    [sg.Push(), sg.Button('Exit'), sg.Push()]
]
window = sg.Window('Color chooser Test', layout, finalize=True, resizable=True)

while True:

    event, values = window.read()

    if event in (sg.WIN_CLOSED, 'Exit'):
        break
    if event.startswith('IN'):
        element, key_index = event.split(' ')
        color = values[event]
        if color != 'None':
            window[f'Button {key_index}'].update(text=color, button_color=(sg.theme_button_color_text(), color))
            window[f'Button {key_index}'].default_color =  color
        else:   # or it will be 'None' in Inout element
            window[event].update(window[f'Button {key_index}'].get_text())

window.close()
macdeport commented 2 years ago

@PySimpleGUI @jason990420

https://github.com/PySimpleGUI/PySimpleGUI/issues/5584#issue-1265281563

But this update of the color is only done when I click on this window.

Yes, it is a bug for macOS user(s): color updating of widget triggered by a click or also cursor hover corners of resizeable PSG window (https://github.com/PySimpleGUI/PySimpleGUI/issues/5584#issuecomment-1151334246) (!) Perhaps triggered by the next event?

PySimpleGUI commented 2 years ago

But this update of the color is only done when I click on this window.

When does the print of event and value happen?

PySimpleGUI commented 2 years ago

The moment you close the color chooser dialog, you should see the event printed that indicates the input element was updated. Do you see this event? Or is it delayed until you focus the window?

ColorChooserExample

macdeport commented 2 years ago

The moment you close the color chooser dialog, you should see the event printed that indicates the input element was updated. Do you see this event?

Definitely yes with smart sg.Print()

floating-screenshot-215055

floating-screenshot-214901

Print event OK => stable state with white background and if click anywhere on window ⬇︎

floating-screenshot-215026

PySimpleGUI commented 2 years ago

Wait, which program are you running?

As you can see, I'm running your original simple program.

For debugging these kinds of things, the simpler the better. No debug print window please. Just use stdout like I shows in my screen capture. We're getting all sorts of extra things involved for no reason.

Just use your first example, when there first button changes. Can you run that and tell me the order of events that you see? Or, do a screen capture like I did so everything is visible... code, stdout, window.

Jason's example has so many added bells and whistles that are confusing the situation. I'm after the simple question of when is the event generated that fills in the Input element. You can use this even simpler example to try to narrow down what's happening.

import PySimpleGUI as sg

layout = [[sg.Input(key='-COLOR1-',enable_events=True), sg.ColorChooserButton('Color',key='-COLOR1b-')],
            [sg.Button('Go'), sg.Button('Exit')]  ]

window = sg.Window('Color chooser Test', layout)

while True:
    event, values = window.read()
    print(event, values)
    if event == sg.WIN_CLOSED or event == 'Exit':
        break
    if event == '-COLOR1-':
        window['-COLOR1b-'].update(button_color=values[event])

window.close()
macdeport commented 2 years ago

floating-screenshot-224225

PySimpleGUI commented 2 years ago

Pefrect! Very good.

Lemme make sure I have the right order over actions happening:

If you do nothing further, the window remains as the first window shown with the white color.

It's only after you click the window that the button changes to green?

Is it normal for the 3 colors in the upper left of the window to change to the gray colors as shown in the first window?

I don't recall this error being reported before... that a partial button update happens when a dialog box is closed.

There is a chance that changing the button to a FileBrowse button will have a similar effect.

Can you try this test? Thanks for your help and patience. You've been such a great help with debugging. It's super-appreciated! image image

import PySimpleGUI as sg

layout = [[sg.Input(key='-COLOR1-',enable_events=True), sg.FileBrowse('Browse',key='-COLOR1b-')],
            [sg.Button('Go'), sg.Button('Exit')]  ]

window = sg.Window('Color chooser Test', layout)

while True:
    event, values = window.read()
    print(event, values)
    if event == sg.WIN_CLOSED or event == 'Exit':
        break
    if event == '-COLOR1-':
        window['-COLOR1b-'].update(button_color='blue')

window.close()
macdeport commented 2 years ago

You have the right order over actions happening

Is it normal for the 3 colors in the upper left of the window to change to the gray colors as shown in the first window?

These colors correspond to a screen shot not currently in focus

PySimpleGUI commented 2 years ago

The test I'm looking for is a different dialog box... it's the file browse dialog box, not the color chooser dialog box. (i.e. the code in the comment)

macdeport commented 2 years ago

Can you try this test? Thanks for your help and patience. You've been such a great help with debugging. It's super-appreciated!

Sorry for my mistake. I run the right test: your are right about your Filebrowse behavior expectation but I was unable to make a screen shot of "white state" (I have seen) in this case...

PySimpleGUI commented 2 years ago

To be clear.... The FileBrowse dialog box exhibits these behaviors:

The button does not turn blue until you click on the window to focus it.

Did I get these right?

macdeport commented 2 years ago

The FileBrowse dialog box exhibits these behaviors (macOS):

button text white on black / button text (hover) text black on white filebrowse-1

√ You click the "Browse" button and the OS File Browse dialog box opens filebrowse-2

√ You choose a file & click "OK" to close the dialog √ You see the event printed and values line of text printed -COLOR1- {'-COLOR1-': '/System/Library/Fonts/Menlo.ttc', '-COLOR1b-': '/System/Library/Fonts/Menlo.ttc'} √ The Input element changes to the file chosen button text black on white

button text white on blue if the mousse cursor is moved filebrowse-3

The same window with focus filebrowse-4

Does the synopsis is clear in each step?

PySimpleGUI commented 2 years ago

Thank you so much!

button text white on blue if the mousse cursor is moved

Is this different than with the Color Chooser? For that one, I thought a click of the window was required.

Can you also refresh my memory as to whether this problem is limited to 8.6.12 only?

@Chr0nicT is still waiting on his M1 to arrive. I'm meeting with him tomorrow and Sunday and will make sure he's up to date on this problem as well as the latest on the other Mac issues.

macdeport commented 2 years ago

Is this different than with the Color Chooser? For that one, I thought a click of the window was required.

The behavior of FileBrowse is slightly different because in the case of Color Chooser the triggering was produced by a click inside the window instead of moving the mouse (?)

Can you also refresh my memory as to whether this problem is limited to 8.6.12 only?

I have only tested with 8.6.12...

I wish you a pleasant and fruitful working session with @Chr0nicT