[Attached is a small script demonstrating the issue]
[Please note, I misunderstood the problem slightly here in my original post. The problem is more general: buttons that are children of a panel that is itself a child of the mainform will not have their click events processed until the form closes…a new demo script showing that is now attached in addition to the original demo script]
Quick Overview of Problem
In Rhino 8, if I make a custom panel and add it to my main form like single control, the click events on child controls of the custom panel are not processed until the entire dialog is closed. The same form can run in Rhino7 or Rhino6 and the clicks will be processed normally.
I have a large project (large for me) that uses custom panels, and I guess I need to know if this is how Rhino8 will be going forward or is it unintended behavior. Also, if it is unintended behavior, I guess a rough time estimate of it getting fixed might be nice as that would help me know if I should redesign my project to not use custom panels or if I should wait for the fix.
Long-Winded Context That’s Probably Unnecessary
I used custom panels to make dealing with DynamicLayout easier for my brain to understand so I can probably re-work everything…just…ugh…it’s gonna be a lot work.
I designed my project in Rhino 7 because there was some problem or problems with the Rhino8 editor. I think autocomplete was often not working and then randomly working, but honestly I can’t remember the exact reason, but as I do all my stuff in python2 for compatibility reasons, I didn’t think it would be an issue.
[this is the original script when I thought it was custom panels] custom panel demo.py (1.7 KB)
[this is the new script showing that it is just panels in general] buttons in a panel.py (1.6 KB)
So, actually, the problem is NOT custom panels, but just having buttons be children of a panel that is itself a child of the main form. I re-worked the original demo to not use a custom panel object, but just a regular panel. My guess is that this is not intended behavior.
Admittedly I have not used Rhino 7 so idk the nuances of what has changed…
Old Response
Given that your form is Modal you can of course add self.Close() after the button click if you would like that behavior…
Or you can use an Eto.Forms.Form for a non modal dialog that will process the button clicks prior to form close like so:
#! python 2
import rhinoscriptsyntax as rs
import Rhino
import Eto
import Eto.Drawing as drawing
import Eto.Forms as forms
class MyEtoForm(forms.Form):
def __init__(self):
self.Width = 300
self.Height = 210
self.Padding = drawing.Padding(10)
self.Title = "Rhino 8 Custom Panel Demo"
self.label = forms.Label(Text="In Rhino 8, if buttons are children of a Panel object, their clicks will not be not processed until after the form is closed.\n\nIf you run this in Rhino 7, the button clicks will process normally.\n")
self.btn1 = forms.Button(Text="Button 1")
self.btn1.Click += self.HandleClick
self.btn2 = forms.Button(Text="Button 2")
self.btn2.Click += self.HandleClick
buttons = [self.btn1, self.btn2]
self.button_panel = forms.Panel()
self.button_panel.BackgroundColor = drawing.Colors.Red
layout_panel = forms.DynamicLayout()
layout_panel.DefaultSpacing = drawing.Size(5,5)
layout_panel.BeginHorizontal()
layout_panel.Add(None)
for button in buttons:
layout_panel.Add(button)
layout_panel.EndHorizontal()
self.button_panel.Content = layout_panel
layout = forms.DynamicLayout()
layout.DefaultSpacing = drawing.Size(5,5)
layout.AddRow(self.label)
layout.AddRow(self.button_panel)
self.Content = layout
def HandleClick(self, sender, e):
# Rhino.RhinoApp.WriteLine
if sender is self.btn1:
Rhino.RhinoApp.WriteLine("You clicked Button 1")
elif sender is self.btn2:
Rhino.RhinoApp.WriteLine("You clicked Button 2")
# Create and show the Eto form
def EstablishForm():
main_form = MyEtoForm()
main_form.Owner = Rhino.UI.RhinoEtoApp.MainWindow
main_form.Show()
if __name__ == "__main__":
EstablishForm()
EDIT:
Okay actually I think it’s working it’s just that print doesn’t call during the subscribed function but Rhino.RhinoAppWriteLine WILL call and print the message as expected.
So change your function here like so:
def HandleClick(self, sender, e):
if sender is self.btn1:
Rhino.RhinoApp.WriteLine("You clicked Button 1")
elif sender is self.btn2:
Rhino.RhinoApp.WriteLine("You clicked Button 2")
If you replace that print statement with a function call it should work perfectly fine regardless of modal/non-modal.
I remember this really messed with me when I switched to the new Script Editor and now I just always use Rhino.RhinoApp.WriteLine for consistent debugging messages.
print still works outside of a class if I recall correctly…
I was running the form semi-modally, which worked fine in Rhino 7 but not Rhino 8. There was no need for it to be semi-modal, so, on a whim, I made it run just modal, and it worked. (At some point, I thought it might need to be semi-modal, but, in the end, it wasn’t necessary.)
Funny thing was, my little demo still didn’t work, and probably an hour or so ago, I replaced the print statements with rs.MessageBoxes and that did work, so I realized it was print statements that were not working, but I didn’t know about the Rhino.RhinoApp.WriteLine thing in Rhino8, so thanks for that tidbit.