填充窗口
再次步骤中,我们使用Gtk::Builder实例将Gtk::Builder UI文件和我们的应用程序窗口类相关联。
我们的简单UI文件为窗口设定了一个标题,并将一个Gtk::Stack文件放入了窗口中。
为了在我们的应用程序中使用这个文件,我们重访Gtk::ApplicationWindow子类,并在ExampleAppWindow::create()成员函数中调用Gtk::Builder::create_from_resource()和Gtk::Builder::get_widget_derived()以获取我们的Gtk::ApplicationWindow子类的实例。更多有关的get_widget_derived()的信息,请参见使用派生部件小节。
你可能已经注意到了,我们使用_from_resource()变体方法读取UI文件。现在,我们要使用GLib资源功能将这个UI文件放入二进制中。通常我们通过在.gresource.xml文件中列出所有资源来完成此操作。该文件必须被转换为C源文件,并将其与其他源文件一并编译链接到应用程序中去。为此,我们使用了glib-compile-resources实用程序:
$ glib-compile-resources --target=resources.c --generate-source exampleapp.gresource.xml
我们的应用程序现在看起来像这样:
File: exampleapplication.h (For use with gtkmm 4)
#include "../step1/exampleapplication.h" // Equal to the corresponding file in step1
File: exampleappwindow.h (For use with gtkmm 4)
#ifndef GTKMM_EXAMPLEAPPWINDOW_H_ #define GTKMM_EXAMPLEAPPWINDOW_H_ #include <gtkmm.h> class ExampleAppWindow : public Gtk::ApplicationWindow { public: ExampleAppWindow(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& refBuilder); static ExampleAppWindow* create(); void open_file_view(const Glib::RefPtr<Gio::File>& file); protected: Glib::RefPtr<Gtk::Builder> m_refBuilder; }; #endif /* GTKMM_EXAMPLEAPPWINDOW_H */
File: main.cc (For use with gtkmm 4)
#include "../step1/main.cc" // Equal to the corresponding file in step1
File: exampleappwindow.cc (For use with gtkmm 4)
#include "exampleappwindow.h" #include <stdexcept> ExampleAppWindow::ExampleAppWindow(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& refBuilder) : Gtk::ApplicationWindow(cobject), m_refBuilder(refBuilder) { } //static ExampleAppWindow* ExampleAppWindow::create() { // Load the Builder file and instantiate its widgets. auto refBuilder = Gtk::Builder::create_from_resource("/org/gtkmm/exampleapp/window.ui"); auto window = Gtk::Builder::get_widget_derived<ExampleAppWindow>(refBuilder, "app_window"); if (!window) throw std::runtime_error("No \"app_window\" object in window.ui"); return window; } void ExampleAppWindow::open_file_view(const Glib::RefPtr<Gio::File>& /* file */) { }
File: exampleapplication.cc (For use with gtkmm 4)
#include "exampleapplication.h" #include "exampleappwindow.h" #include <iostream> #include <exception> ExampleApplication::ExampleApplication() : Gtk::Application("org.gtkmm.examples.application", Gio::Application::Flags::HANDLES_OPEN) { } Glib::RefPtr<ExampleApplication> ExampleApplication::create() { return Glib::make_refptr_for_instance<ExampleApplication>(new ExampleApplication()); } ExampleAppWindow* ExampleApplication::create_appwindow() { auto appwindow = ExampleAppWindow::create(); // Make sure that the application runs for as long this window is still open. add_window(*appwindow); // A window can be added to an application with Gtk::Application::add_window() // or Gtk::Window::set_application(). When all added windows have been hidden // or removed, the application stops running (Gtk::Application::run() returns()), // unless Gio::Application::hold() has been called. // Delete the window when it is hidden. appwindow->signal_hide().connect(sigc::bind(sigc::mem_fun(*this, &ExampleApplication::on_hide_window), appwindow)); return appwindow; } void ExampleApplication::on_activate() { try { // The application has been started, so let's show a window. auto appwindow = create_appwindow(); appwindow->present(); } // If create_appwindow() throws an exception (perhaps from Gtk::Builder), // no window has been created, no window has been added to the application, // and therefore the application will stop running. catch (const Glib::Error& ex) { std::cerr << "ExampleApplication::on_activate(): " << ex.what() << std::endl; } catch (const std::exception& ex) { std::cerr << "ExampleApplication::on_activate(): " << ex.what() << std::endl; } } void ExampleApplication::on_open(const Gio::Application::type_vec_files& files, const Glib::ustring& /* hint */) { // The application has been asked to open some files, // so let's open a new view for each one. ExampleAppWindow* appwindow = nullptr; auto windows = get_windows(); if (windows.size() > 0) appwindow = dynamic_cast<ExampleAppWindow*>(windows[0]); try { if (!appwindow) appwindow = create_appwindow(); for (const auto& file : files) appwindow->open_file_view(file); appwindow->present(); } catch (const Glib::Error& ex) { std::cerr << "ExampleApplication::on_open(): " << ex.what() << std::endl; } catch (const std::exception& ex) { std::cerr << "ExampleApplication::on_open(): " << ex.what() << std::endl; } } void ExampleApplication::on_hide_window(Gtk::Window* window) { delete window; }
File: exampleapp.gresource.xml (For use with gtkmm 4)
<?xml version="1.0" encoding="UTF-8"?> <gresources> <gresource prefix="/org/gtkmm/exampleapp"> <file preprocess="xml-stripblanks">window.ui</file> </gresource> </gresources>
File: window.ui (For use with gtkmm 4)
<?xml version="1.0" encoding="UTF-8"?> <interface> <object class="GtkApplicationWindow" id="app_window"> <property name="title" translatable="yes">Example Application</property> <property name="default-width">600</property> <property name="default-height">400</property> <property name="hide-on-close">True</property> <child> <object class="GtkBox" id="content_box"> <property name="orientation">vertical</property> <child> <object class="GtkStack" id="stack"/> </child> </object> </child> </object> </interface>