Невозможно использовать SaveFileDialog из .Net с pythonnet

У меня есть некоторые проблемы с использованием класса SaveFileDialog .Net в Python 3.4 с пакетом pythonnet. Выше вы увидите небольшой пример кода, демонстрирующий эту проблему. Сам код работает довольно хорошо, пока не сработает событие нажатия кнопки, и SaveFileDialog не должен отображаться с помощью «dialog.ShowDialog()», приложение зависает, и вообще ничего не происходит. Протестировал тот же код с интерпретатором IronPython, и он работал нормально. Я уже искал в Интернете некоторые ответы, но не нашел ничего, связанного с этой проблемой.

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())

person Marcel S.    schedule 10.05.2017    source источник
comment
Хорошо, я добился некоторого прогресса в своей проблеме. Я попытался запустить тот же код, который я разместил выше, с помощью spyder, который поставляется с WinPython (см. ‹winpython.github.io›< /а>). Но если я попытаюсь скомпилировать его с помощью pyinstaller, ошибка снова появится. Так почему это работает только со spyder?   -  person Marcel S.    schedule 12.05.2017
comment
см. мой ответ ниже - я проверил, и он отлично работает!   -  person denfromufa    schedule 16.05.2017


Ответы (1)


Вам необходимо установить состояние подразделения потока STA, как описано в этом выпуске:

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()

И вывод здесь:

start thread
set thread apartment STA
so far so good
Never reaches this point
person denfromufa    schedule 15.05.2017
comment
Спасибо, у меня это отлично работает :) Я также могу создать .exe с помощью pyinstaller. Не могли бы вы дать мне краткое объяснение, почему я сделал это именно так? - person Marcel S.; 16.05.2017
comment
Для требования STA взгляните на ответы на этот вопрос: по умолчанию">stackoverflow.com/questions/4659220/ - person denfromufa; 16.05.2017
comment
Еще раз спасибо за ваш ответ. Это поможет мне. - person Marcel S.; 16.05.2017