4

GTKのargv処理を使おうとしていますが、メインループに問題があるようです。

私の目標は、GTKがオプション(など--display)を削除した後、ウィンドウを開く前にコマンドラインを解析することです。これは、アプリをCLIのみのインターフェイスでも使用できるようにし、両方のバリアントでGlibなどを使用するためです。command_lineシグナルハンドラでウィンドウを開こうとしているのはそのためです。

これは期待どおりに機能し、ウィンドウを閉じると終了します。

#include <gtkmm.h>
int main(int argc, char **argv) {
    auto app = Gtk::Application::create(argc, argv, "my.app");
    Gtk::ApplicationWindow win;
    return app->run(win);
}

ただし、フラグを追加するだけで、HANDLES_COMMAND_LINE次のことが破壊されます。ウィンドウが表示されることはありません。

#include <gtkmm.h>
int on_cmd(const Glib::RefPtr<Gio::ApplicationCommandLine> &) {
    return 0;
}
int main(int argc, char **argv) {
    auto app = Gtk::Application::create(argc, argv, "my.app",
                 Gio::APPLICATION_HANDLES_COMMAND_LINE);
    app->signal_command_line().connect(sigc::ptr_fun(on_cmd), false);
    Gtk::ApplicationWindow win;
    return app->run(win);
}

だから私はcommand_lineハンドラーが実際に戻ることを想定されていないのだろうか?しかし、ドキュメントにはrun、メインループを開始すると書かれています。メインループが終了するのを待つだけの方法が見つからなかったので、手動でクランクします。ウィンドウが再び表示されていますが、もちろん、閉じた後もループは続行されます。これは、そのコードで最も問題が少ないものです。

#include <gtkmm.h>
int on_cmd(const Glib::RefPtr<Gio::ApplicationCommandLine> &,
           Glib::RefPtr<Gtk::Application> &app) {
    Gtk::ApplicationWindow win(app);
    // app->run(win); --- lands here again -> stack overflow.
    win.show();
    // This looks very wrong but seems to work?!
    while(true)
        Glib::MainContext::get_default()->iteration(true);
    // never reach this
    return 0;
}
int main(int argc, char **argv) {
    auto app = Gtk::Application::create(argc, argv, "my.app",
                 Gio::APPLICATION_HANDLES_COMMAND_LINE);
    app->signal_command_line().connect(
      sigc::bind(sigc::ptr_fun(on_cmd), app), false);
    return app->run();
}

(gtkmm-3.0バージョン3.5.13)

4

1 に答える 1

7

結局のところ、キーはアプリケーションで呼び出しactivateています。HANDLES_COMMAND_LINEが指定されていないときに実行されるデフォルトのハンドラは、自動的にそれを行います。

私の 2 番目の例は、1 行だけ欠けていました。

#include <gtkmm.h>
int on_cmd(const Glib::RefPtr<Gio::ApplicationCommandLine> &,
  Glib::RefPtr<Gtk::Application> &app) {
    app->activate(); // <----
    return 0;
}
int main(int argc, char **argv) {
    auto app = Gtk::Application::create(argc, argv, "my.app",
                 Gio::APPLICATION_HANDLES_COMMAND_LINE);
    app->signal_command_line().connect(
      sigc::bind(sigc::ptr_fun(on_cmd), app), false);
    Gtk::ApplicationWindow win;
    return app->run(win);
}

これは、Glib を使用してコマンド ラインを解析するサブクラス化されたアプリケーションです。--gui存在する場合は、ウィンドウを開き、ウィンドウが閉じられた後にのみ終了します。

を使用gtk_get_option_groupすると GTK オプション (およびヘルプ) が追加されるため、適用可能なすべてのオプションが実際に表示され、GTK オプションの削除--help-allに依存する必要はありません。 . アプリケーション コンストラクターに引数が与えられた場合、GTK オプションは削除されますが、例外として、ハンドラーはそれらを見ることはありませんが、ヘルプを表示することはできます. どちらの方法でも問題はないようです)gtk_main(argc, argv)run(argc, argv)--help-gtk

#include <gtkmm.h>
struct MyApp : Gtk::Application {
    MyApp() : Gtk::Application("my.app",
      Gio::APPLICATION_HANDLES_COMMAND_LINE) {}
    int on_command_line(const Glib::RefPtr<Gio::ApplicationCommandLine> &cmd) {
        // parse arguments:
        Glib::OptionContext ctx;
        Glib::OptionGroup group("options", "main options");
        bool show_gui = false;
        Glib::OptionEntry entry;
        entry.set_long_name("gui");
        entry.set_description("show the gui.");
        group.add_entry(entry, show_gui);
        ctx.add_group(group);
        // add GTK options, --help-gtk, etc
        Glib::OptionGroup gtkgroup(gtk_get_option_group(true));
        ctx.add_group(gtkgroup);
        int argc;
        char **argv = cmd->get_arguments(argc);
        ctx.parse(argc, argv);
        // maybe show the gui
        if(show_gui)
            activate();
        return 0;
    }
    Gtk::ApplicationWindow *main;
    void on_activate() {
        // can't use Gtk::manage, so we have to keep
        // the reference or the main loop quits.
        main = new Gtk::ApplicationWindow();
        add_window(*main);
        main->show();
    }
};
int main(int argc, char **argv) {
    return MyApp().run(argc, argv);
}
于 2012-12-13T18:39:05.527 に答える