Modeless Form Close Button Crashes

Hi,

I’m doing quite a bit of wheel spinning trying to close a modeless form with a close button instead of the user clicking the “X”. I’ve pasted in some sample code below. I’ve tried a self.Close(), which crashes Rhino and tried what is in the pasted code below with no success. Can someone tell me what I am doing wrong?

I posted something similar back in May and never got an answer: ETO Modeless Form Close Button

Eric

Test():
        print ("Hi")
       
    # Form Closed event handler
    def OnFormClosed(self, sender, e):
        print("the form has closed")
        # Dispose of the form and remove it from the sticky dictionary
        if sc.sticky.has_key('sample_modeless_form'):
            form = sc.sticky['sample_modeless_form']
            if form:
                form.Dispose()
                form = None
            sc.sticky.Remove('sample_modeless_form')

    # Close button click handler
    def OnCloseButtonClick(self, sender, e):
        print("the form has closed")
        # Dispose of the form and remove it from the sticky dictionary
        if sc.sticky.has_key('sample_modeless_form'):
            form = sc.sticky['sample_modeless_form']
            if form:
                form.Close()
                form.Dispose()
                form = None
            sc.sticky.Remove('sample_modeless_form')


    # OK button click handler
    def OnOKButtonClick(self, sender, e):
        print("clicked")



    ## End of Dialog Class ##


def Test():
    
    # See if the form is already visible
    if sc.sticky.has_key('sample_modeless_form'):
        return

    # Create and show form
    form = ETOModelessForm()
    form.Owner = Rhino.UI.RhinoEtoApp.MainWindow
    form.Show()
    
    # Add the form to the sticky dictionary so it
    # survives when the main function ends.
    sc.sticky['sample_modeless_form'] = form

if __name__ == '__main__':
    Test()

Hi @eric.bunn,

Does this work any better?

def OnCloseButtonClick(self, sender, e):
    self.Close()

– Dale

Dale,

I did a test this morning, putting in self.Close() as well as stripping out the Sticky Code and the form closes normally without crashing Rhino. If I reactivate the Sticky Code Rhino Crashes. I’ve pasted the code below. I’ve also posted a video of the Rhino crashing and not crashing after stripping out the Sticky code. The crash is about 1/3 of the way in the video after pushing the Cancel Button.

Any help would be greatly appreciated.

Eric

Rhino Modeless With Close Button (crashes).py (2.9 KB)

# Imports
import Rhino
import scriptcontext as sc
import Rhino.UI
import Eto.Drawing as drawing
import Eto.Forms as forms

# SampleEtoRoomNumber dialog class
class ETOModelessForm(forms.Form):

    # Dialog box Class initializer
    def __init__(self):
        # Initialize dialog box
        self.Title = 'Identify Assembly Components'
        self.Padding = drawing.Padding(10)
        self.Resizable = False
         #FormClosed event handler
        self.Closed += self.OnFormClosed
#        self.ClientSize = drawing.Size(300, 400) #sets the (Width, Height)(Optional only)

        # Create controls for the dialog
        self.m_label = forms.Label(Text = 'Enter Your Name:')
        self.m_textbox = forms.TextBox(Text = None)

        # Create the default button
        self.DefaultButton = forms.Button(Text = 'OK')
        self.DefaultButton.Click += self.OnOKButtonClick

        # Create the abort button
        self.AbortButton = forms.Button(Text = 'Cancel')
        self.AbortButton.Click += self.OnCloseButtonClick

        # Create a table layout and add all the controls
        layout = forms.DynamicLayout()
        
        #Sets spacing between controls(pixels)
        layout.Spacing = drawing.Size(5, 5)
        
        #Textbox 1
        layout.AddRow(self.m_label, self.m_textbox)
        layout.AddRow(None)

        #Buttons
        layout.AddRow(self.DefaultButton, self.AbortButton)

        # Set the dialog content
        self.Content = layout
     
    # Form Closed event handler
    def OnFormClosed(self, sender, e):
        print("the form has closed")
        # Dispose of the form and remove it from the sticky dictionary
        if sc.sticky.has_key('sample_modeless_form'):
            form = sc.sticky['sample_modeless_form']
            if form:
                form.Dispose()
                form = None
            sc.sticky.Remove('sample_modeless_form')

    # Close button click handler
    def OnCloseButtonClick(self, sender, e):
        self.Close()
        print("the form has closed")
        # Dispose of the form and remove it from the sticky dictionary
        if sc.sticky.has_key('sample_modeless_form'):
            form = sc.sticky['sample_modeless_form']
            if form:
                form.Dispose()
                form = None
            sc.sticky.Remove('sample_modeless_form')
        

    # OK button click handler
    def OnOKButtonClick(self, sender, e):
        print("clicked")

def Test():
    
    # See if the form is already visible
    if sc.sticky.has_key('sample_modeless_form'):
        return

    # Create and show form
    form = ETOModelessForm()
    form.Owner = Rhino.UI.RhinoEtoApp.MainWindow
    form.Show()
    
    # Add the form to the sticky dictionary so it
    # survives when the main function ends.
    sc.sticky['sample_modeless_form'] = form

if __name__ == '__main__':
    Test()

Hi @eric.bunn, you cannot dispose an already closed modeless form. Just remove:

form.Dispose()

to prevent the crash.

_
c.

Awesome. I’ll try it out.

Thanks,

Eric

Clement,

Just so I understand this. I disabled form.Dispose() and this solved the issue. Can you explain to me when one would want to use Dispose? I’m unsure of it’s purpose now.

Also, since I have two functions that handle closing the form, one for the ‘X’ and another for the button, do I need to have the Sticky Code in each function or is it only necessary in the function “OnFormClosed”? See below.

# Form Closed event handler
def OnFormClosed(self, sender, e):
    print("the form has closed")
    # Dispose of the form and remove it from the sticky dictionary
    if sc.sticky.has_key('sample_modeless_form'):
        form = sc.sticky['sample_modeless_form']
        if form:
            #form.Dispose()
            form = None
        sc.sticky.Remove('sample_modeless_form')

# Close button click handler
def OnCloseButtonClick(self, sender, e):
    self.Close()
    print("the form has closed")
    # Dispose of the form and remove it from the sticky dictionary
    if sc.sticky.has_key('sample_modeless_form'):
        form = sc.sticky['sample_modeless_form']
        if form:
#                form.Dispose()
            form = None
        sc.sticky.Remove('sample_modeless_form')

Hi @eric.bunn,

self.Close() triggers your event OnFormClosed() when you click the close button. So you can put your sticky code only there and do not have to do it in the OnCloseButtonClick() function.

I guess this only is usable for modal forms if you want to cleanup memory references after closing it.

_
c.

Thanks for explaining Clement. Appreciate it. I will remove the code from the close button.

Eric