15

我有两个 GTK 窗口

  1. 运行动画的普通(主)窗口,在由gtk_widget_add_tick_callback().

  2. 在某个时候,会创建运行模态循环的辅助窗口:

    void show_modal() 
    {
       GtkWindow* gw = gtkwindow(this);
    
       if( parent() )
         gtk_window_set_transient_for(gw, gtkwindow( parent() ));
    
    
       gtk_widget_show(GTK_WIDGET(gw));
       gtk_window_set_modal(gw,TRUE);
       gtk_window_set_keep_above(gw,TRUE);
       this->update_window_state(gool::WINDOW_SHOWN);
    
       while( this->is_valid_window() )
       {
          if(this->_window_state == WINDOW_HIDDEN) break;
          if(this->_window_state == WINDOW_STATE_NA) break;
          gtk_main_iteration(); // gtk_main_iteration_do(true);
       }
    }
    

问题:主窗口中的动画工作正常,直到show_modal()被调用。它显示为功能gtk_main_iteration();添加的块刻度gtk_widget_add_tick_callback()。一旦我关闭辅助窗口并while() {gtk_main_iteration();}退出循环,主窗口中的动画就会再次开始运行。

关于如何在 GTK 中制作“动画友好”模式循环的任何想法?

更新:它不仅显示为gtk_main_iteration();块,而且显示为“当前”以外的任何窗口的任何更新 - 它们只是被冻结。这种 GTK 行为的原因是什么?

更新#2:

gtk_dialog_run();行为完全一样gtk_main_iteration();- 锁定除活动窗口之外的任何进程中的任何窗口上的任何更新。

4

2 回答 2

1

It seems to be by definition: link

gboolean gtk_main_iteration (void); Runs a single iteration of the mainloop. If no events are waiting to be processed GTK+ will block until the next event is noticed. If you don’t want to block look at gtk_main_iteration_do() or check if any events are pending with gtk_events_pending() first.

The explanation suggests to use gtk_main_iteration_do(FALSE) if you don't want blocking:

gboolean gtk_main_iteration_do (gboolean blocking); Runs a single iteration of the mainloop. If no events are available either return or block depending on the value of blocking: TRUE if you want GTK+ to block if no events are pending

As for gtk_dialog_run: it also blocks by design link

gint gtk_dialog_run (GtkDialog *dialog); Blocks in a recursive main loop until the dialog either emits the “response” signal, or is destroyed.[...]

I read about people solving this using multiple threads: handle the GUI in the main thread and do background work in another one. There's an article about it here that might be useful.

于 2017-03-16T12:20:28.693 回答
0

我假设这show_modal是从主要上下文中的回调或其他活动中调用的。您可以尝试使用invokesignal_idle将模态窗口添加到主上下文中。

这样执行show_modal就会结束。

#include <gtkmm.h>
#include <string>

int main()
{
    auto Application = Gtk::Application::create();
    Gtk::Window window;
    Gtk::Window* window2;
    Gtk::Button button;
    window.add(button);

    //I hope timeout behaves similar to ticks. I have no idea how animations in GTK work
    int i=0;
    Glib::MainContext::get_default()->signal_timeout().connect([&]()->bool{
            button.set_label(std::to_string(i++));
            return true;
        }, 1000);

    button.signal_clicked().connect([&]{
            Glib::MainContext::get_default()->invoke([&]()->bool{
                    window2 = new Gtk::Window;
                    window2->set_modal(true);
                    window2->set_keep_above(true);
                    window2->signal_delete_event().connect([&](GdkEventAny* any_event)->bool{
                            delete window2;
                            return false;
                        });
                    window2->show_all();
                    return false;
                });
        });

    window.show_all();

    return Application->run(window);
}
于 2017-10-03T16:13:01.440 回答