desktopColorPicker - fires colorSelected unexpectedly

I want the desktopColorPicker to close upon selecting a color.

On the mouseUp event I open the colorPicker:

Sub MouseUp(x As Integer, y As Integer) Handles MouseUp
  If picker = Nil Then
    picker = New DesktopColorPicker
    AddHandler picker.colorSelected, AddressOf setColour
  End If
  
  Var l As Integer = Self.Left + Self.width/2
  Var t As Integer = Self.top + Self.height/2
  
  Var prompt As String = "select colour"
  picker.Show(clr, prompt, l, t)
End Sub

So that the colorSelected event calls the following

Private Sub setColour(sender as desktopColorPicker, selColour as Color)
  If picker <> Nil And picker.isvisible Then
    picker.Close
  End If
  
  clr = selColour
  Self.refresh
End Sub

On first click, the colorPicker opens briefly and closes again, somehow the colorSelected event is triggered (incorrectly) and triggers the picker.close line in the setColour method.

On second click, the colorPicker opens correctly and waits for a color to be selected, then closes again (correctly).

How can I get the picker to behave consistently?

Example project attached.

I think I’ve fixed it with a timer and a boolean property -

Sub MouseUp(x As Integer, y As Integer) Handles MouseUp
  If picker = Nil Then
    picker = New DesktopColorPicker
    AddHandler picker.closed, AddressOf closeColorPanel
    AddHandler picker.colorSelected, AddressOf setColour
  End If
  
  Var l As Integer = Self.Left + Self.width/2
  Var t As Integer = Self.top + Self.height/2
  
  Var prompt As String = "select colour"
  
  bDisplayComplete = False
  picker.Show(clr, prompt, l, t)
  timer.CallLater(1, AddressOf displayComplete) //sets bDisplayComplete = true
End Sub

Now the event still fires but is ignored until the timer fires.

I think you’re trying to solve the wrong problem. Color pickers on macOS aren’t supposed to close when a color is selected so that users can try out different color choices without constantly re-opening the picker. Go try a photo editing app.

3 Likes

Why don’t you use the recently added ColorPicker Control instead ?

Add one to your window and use that instead.

image
This is its icon from Xojo 2023r3.1.

Of course, I do not found it in the documentation nor in the release notes, after a 15 minutes search.

Fortunately, in this case my memory served well. (it is not always the case nowadays).

Think different… I added an instance of the ColorPicker Control to a window, right-click the mouse on its icon and ask for help:
Here you are:

https://documentation.xojo.com/api/user_interface/desktop/desktopcolorpicker.html#desktopcolorpicker

It may be appropriate in the context of a drawing app - but it is frustrating in other apps - Xojo for example where to insert a color takes 2 clicks rather than one (and then there is a frustrating delay whilst the text is added to the IDE - but that’s another issue). MS Word, Excel, Powerpoint for example, all use a single click for color selection.

This example is using the DesktopColorPicker

1 Like

I may be walking beside my shoes, but if so, why:

picker = New DesktopColorPicker

“Obviously” (for me), the Control is not used (none was copied into the window from the Controls pane)…; else, DesktopColorPicker1 would be used…

That’s not an expression I’d heard before. I do know: “walk a mile in your enemies shoes, firstly to understand and secondly so that you’re now a mile away and you have his shoes!”

But, back to the point - yes you are right I could have dragged the control to the window/container. I was updating from an earlier MBS control where the control was contained in a property so naturally just continued the same.

The result is the same whichever way - I still need to add a timer to stop the open/close flash effect on first click.

Well, it has been translated straight from a french expression :sweat_smile:.

While I think the same as you (the “new” async version is bad), closing the color picker directly is certainly not a good thing. Just imagine when the user moves an RGB slider to adjust a colour and the picker closes during that.

For my needs of a synchronous picker, but I’m not sure it’d suit yours, I show a modal dialog before showing the picker. The modal dialog, which has a label “Please choose a colour”, is therefore shown underneath the picker and prevents interaction with the remaining app (thus making the picker synchronous). Once the user closes the picker, the modal dialog closes as well.
I know it’s a workaround against the new way the picker works, but Apple shouldn’t have decided we all need an asynchronous picker in the first place.

That’s a good point - and probably the main reason it is asynch. Luckily for this app the colour choice is not subtle, but it might be a problem for a different app.