GtkFileChooserDialog не действует как модальный

У меня есть пользовательский GtkFileChooserDialog, созданный с помощью Glade. Свойство Modal помечено. У меня также есть GtkFileChooserButton, который использует этот GtkFileChooserDialog в качестве своего диалога:

class ImgChooserBttWithCapture(Gtk.FileChooserButton):
    """
    The custom Gtk.FileChooserButton and Gtt.FileChooserDialog with a button for call capture app
    """

    def __init__(self, cap_app_path):
        self.builder = Gtk.Builder.new_from_file(
            UIS_PATH + 'images_chooser_dialog.xml')
        self.chooser_dialog = self.builder.get_object('icd_photo_chsrdialog')

        super().__init__(dialog=self.chooser_dialog)
        self.cap_app_path = cap_app_path
        self.set_title('Selecione uma imagem')
        self.set_halign(Gtk.Align.START)
        self.set_valign(Gtk.Align.FILL)
        self.set_hexpand(True)
        self.set_tooltip_text('Clique para escolher uma nova imagem')
        self.set_local_only(False)

        handlers = {'onCaptureButtonClicked': self._on_capture_button_clicked}

        self.builder.connect_signals(handlers)

    def _on_capture_button_clicked(self, button):

        try:
            subprocess.call([self.cap_app_path])
        except (subprocess.CalledProcessError, subprocess.TimeoutExpired, FileNotFoundError) as ex:

            self.builder.add_from_file(UIS_PATH + 'information_window.xml')
            msg_dialog = self.builder.get_object('iw_messagedialog')

            msg_dialog.set_title('Erro')
            msg_dialog.set_markup(
                '<span size="12000"><b>Não foi possível abrir o aplicativo</b></span>')

            msg_dialog.format_secondary_markup(
                'O aplicativo de captura não está disponível.\nVerifique o caminho para o aplicativo de caputura em configurações.\n' + '<span foreground="red"><u>' + str(ex) + '</u></span>')

            msg_dialog.set_property('message-type', Gtk.MessageType.ERROR)
            msg_dialog.set_transient_for(self.chooser_dialog)
            self.builder.get_object('iw_message_image').set_from_file(
                'views/uis/images/message_error.png')

            msg_dialog.run()
            msg_dialog.destroy()

Но, когда я нажимаю на кнопку, диалог не является модальным, то есть я могу взаимодействовать с другим окном.


person Matheus Saraiva    schedule 05.10.2016    source источник
comment
Вполне возможно, что модальность на самом деле не соблюдается, если вы также не установите свойство transient-for.   -  person Jussi Kukkonen    schedule 06.10.2016
comment
Я добавил self.chooser_dialog.set_transient_for(parent) под self.chooser_dialog = self.builder.get_object('icd_photo_chsrdialog'). parent передается через конструктор def __init__(self, cap_app_path, parent):. Но проблема остается. parent — это GtkApplicationWindow   -  person Matheus Saraiva    schedule 06.10.2016
comment
Хотя я могу взаимодействовать с другим окном (родительским окном), GtkFileChooserDialog продолжается перед родительским окном. Но я могу взаимодействовать с кнопками, меню и другими компонентами родительского окна, даже если она находится в фоновом режиме. Я думаю, что это ошибка версии 3.20, потому что я запускал тот же код в версии 3.18, и он работал отлично. Как я мог обойти это?   -  person Matheus Saraiva    schedule 06.10.2016
comment
Какой диалог не является модальным, диалог выбора файла или диалог сообщения?   -  person andlabs    schedule 07.10.2016
comment
Диалог выбора файла. Диалог сообщения является модальным. Но диалог выбора файла не является модальным.   -  person Matheus Saraiva    schedule 07.10.2016
comment
Возможным решением этой проблемы является set_sensitive(False) в окне parent при нажатии на GtkFileChooserButton и set_sensitive(True) при закрытии GtkFileChooserDialog. Но я еще не тестировал.   -  person Matheus Saraiva    schedule 07.10.2016


Ответы (1)


Подойдет ли вам захват указателя?

//pass all events to window apart LEAVE_NOTIFY_MASK 
MainWindow->set_events(GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_MOTION_MASK | GDK_BUTTON1_MOTION_MASK | GDK_BUTTON2_MOTION_MASK | GDK_BUTTON3_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK | GDK_FOCUS_CHANGE_MASK | GDK_STRUCTURE_MASK | GDK_PROPERTY_CHANGE_MASK | GDK_VISIBILITY_NOTIFY_MASK | GDK_PROXIMITY_IN_MASK | GDK_PROXIMITY_OUT_MASK | GDK_SUBSTRUCTURE_MASK | GDK_SCROLL_MASK | GDK_TOUCH_MASK | GDK_SMOOTH_SCROLL_MASK | GDK_TOUCHPAD_GESTURE_MASK);
MainWindow->set_modal(true);
auto display = MainWindow->get_display();
auto window = MainWindow->get_window();
auto grabSuccess = display->get_default_seat()->grab(window, Gdk::SEAT_CAPABILITY_ALL, true);
if(grabSuccess != Gdk::GRAB_SUCCESS)
{
    std::clog<<"grab failed: "<<grabSuccess<<std::endl;
}
person pan-mroku    schedule 07.10.2016
comment
Модальным должно быть не MainWindow, а GtkFileChooserDialog, которое она вызывает. Паллиатив Я установил parent (MainWindow) на set_sensitive(False), когда нажимается GtkFileChooserButton, и set_sensitive(True), когда GtkFileChooserDialog скрыт. Но мне пришлось использовать событие button-release-event из GtkFileChooserButton, т.к. с button-press-event не получилось. - person Matheus Saraiva; 07.10.2016
comment
MainWindow в моем коде — это ваш self.chooser_dialog. Диалоги являются подклассом Windows. Окно должно быть реализовано, чтобы захватить указатель. - person pan-mroku; 10.10.2016
comment
Это не то, для чего предназначены захваты, и попытка сделать это таким образом сломается, если какой-либо из элементов управления в дочернем диалоговом окне захвата (например, поля со списком). - person andlabs; 11.10.2016