2

I've got some issues using the SaveFileDialog class of .Net in Python 3.4 with the pythonnet package. Above you will see a little sample of code to demonstrate that issue. The code itself works pretty fine until the event of the button click gets fired and the SaveFileDialog should be showed with "dialog.ShowDialog()" the Application freezes and nothing happens at all. Tested the same code with the IronPython interpreter and it worked fine. I have already searched the web for some answers but found nothing related with that issue

import clr
clr.AddReference("System.Windows.Forms")
clr.AddReference("System.Drawing")
from System.Windows.Forms import Form, Application, Button, SaveFileDialog 
from System.Drawing import Point

class TestForm(Form):
    def __init__(self):
        self.button = Button()
        self.addButton()

    def addButton(self):
        self.button.Location = Point(50,50)
        self.button.Text = "Save s.th"
        self.Controls.Add(self.button)
        self.button.Click += self.buttonClick

    def buttonClick(self, sender, event):
        dialog = SaveFileDialog()
        dialog.FileName = "test one"
        dialog.Title = "Test One"
        print("so far so good")
        dialog.ShowDialog()
        print("Never reaches this point")
Application.Run(TestForm())
denfromufa
  • 5,610
  • 13
  • 81
  • 138
stranger0612
  • 301
  • 1
  • 2
  • 12
  • 1
    Ok, I made some kind of progress with my issue. I tried to lunch the same code that I posted above with spyder which comes with "WinPython" (see ). But if I try to compile it with "pyinstaller" the error appears again. So why works it only with spyder? – stranger0612 May 12 '17 at 12:49
  • see my answer below - I tested and it works great! – denfromufa May 15 '17 at 21:01

1 Answers1

1

You need to set STA thread apartment state like described in this issue:

https://github.com/pythonnet/pythonnet/pull/197

import clr
clr.AddReference("System.Windows.Forms")
clr.AddReference("System.Drawing")
from System.Windows.Forms import Form, Application, Button, SaveFileDialog 
from System.Drawing import Point
from System.Threading import Thread, ThreadStart, ApartmentState

class TestForm(Form):
    def __init__(self):
        self.button = Button()
        self.addButton()

    def addButton(self):
        self.button.Location = Point(50,50)
        self.button.Text = "Save s.th"
        self.Controls.Add(self.button)
        self.button.Click += self.buttonClick

    def buttonClick(self, sender, event):
        dialog = SaveFileDialog()
        dialog.FileName = "test one"
        dialog.Title = "Test One"
        print("so far so good")
        dialog.ShowDialog()
        print("Never reaches this point")


def app_thread():
    app = TestForm()
    Application.Run(app)


def main():
    print('start thread')
    thread = Thread(ThreadStart(app_thread))
    print('set thread apartment STA')
    thread.SetApartmentState(ApartmentState.STA)
    thread.Start()
    thread.Join()


if __name__ == '__main__':
    main()

And output is here:

start thread
set thread apartment STA
so far so good
Never reaches this point
denfromufa
  • 5,610
  • 13
  • 81
  • 138
  • 1
    Thank you, it works fine for me :) I can build an .exe with pyinstaller as well. Do you mind to give me a short explanation why I have do it that way? – stranger0612 May 16 '17 at 05:08
  • 1
    For STA requirement have a look at this question's answers: http://stackoverflow.com/questions/4659220/why-are-winforms-applications-stathread-by-default – denfromufa May 16 '17 at 11:31
  • 1
    Once again thank you for your answer. This will help me. – stranger0612 May 16 '17 at 14:21