我需要在主应用程序窗口中包含不同小部件的网格。由于我刚接触Gtk,因此我决定从创建一个简单的布局开始,以便我可以更好地理解其背后的逻辑。
以下图像是我要获取的布局:
如您所见,我已经有一个菜单 ((Archivo | Preferencias | Ayuda)] >>和[toolbar (Nuevo | Abrir | Deshacer | Pantalla completa)。]]。
因此,在红色矩形中,我试图获取scrolledwindow
(假设我在大列中具有图像名称列表),绿色线将是separator,最后,“蓝色”矩形将是一个小部件,用于在选择滚动窗口的图像时显示图像。下图是当前输出。请注意,滚动窗口位于工具栏的右下方,占据所有垂直空间和宽度的99%,而左侧宽度的1%则是在窗口的右边缘显示分隔符的位置(因此,白色部分在工具栏的右侧)
最后,如果要运行它,这是此UI的代码。 网格是在Window类的初始化中构建的。
application.py
# -*- encoding: utf-8 -*- # Author: # Diego Suárez García, [email protected] # ## ## ## ## ## ## ## ## ## ## ## ## # ## ## ## ## ## ## ## ## ## ## ## ## # # ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ # # # # application.py : # # # # ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ # ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## import json import sys import gi gi.require_version('Gtk', '3.0') from gi.repository import Gtk from gi.repository import Gio from gi.repository import Gdk # Constants MENU_FILE = "menubar.ui" ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## # ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ # # ~ Window Class ~ # # ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ # ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## class Window(Gtk.ApplicationWindow): def __init__(self, app): # Main window initialization super(Window, self).__init__(title="FreeComet 1.0", application=app) self.set_default_size(800, 600) # The project filename self.project_filename = None # The grid to attach the toolbar grid = Gtk.Grid() # The toolbar toolbar = self.__create_toolbar() toolbar.set_hexpand(True) # with extra horizontal space # The Toolbar Actions undo_action = Gio.SimpleAction.new("undo", None) undo_action.connect("activate", self.undo_callback) self.add_action(undo_action) fullscreen_action = Gio.SimpleAction.new("fullscreen", None) fullscreen_action.connect("activate", self.fullscreen_callback) self.add_action(fullscreen_action) new_action = Gio.SimpleAction.new("new-project", None) new_action.connect("activate", self.new_project_callback) self.add_action(new_action) open_project_action = Gio.SimpleAction.new("open-project", None) open_project_action.connect("activate", self.open_project_callback) self.add_action(open_project_action) # The scrolledwindow scrolled_window = Gtk.ScrolledWindow() scrolled_window.set_border_width(10) scrolled_window.set_vexpand(True) scrolled_window.set_hexpand(False) # there is always the scrollbar (otherwise: AUTOMATIC - only if needed # - or NEVER) scrolled_window.set_policy( Gtk.PolicyType.ALWAYS, Gtk.PolicyType.ALWAYS) # a horizontal separator hseparator = Gtk.Separator(orientation=Gtk.Orientation.HORIZONTAL) # a vertical separator vseparator = Gtk.Separator(orientation=Gtk.Orientation.VERTICAL) # Build grid grid.add(toolbar) grid.attach(scrolled_window, 0, 1, 1, 1) grid.attach(vseparator, 1, 1, 1, 1) grid.attach(Gtk.Button(), 2, 1, 1, 1) # Add the grid to the window self.add(grid) def __create_toolbar(self): # Toolbar initialization (primary toolbar of the application) toolbar = Gtk.Toolbar() toolbar.get_style_context().add_class(Gtk.STYLE_CLASS_PRIMARY_TOOLBAR) # Button for the 'new' action new_button = Gtk.ToolButton.new_from_stock(Gtk.STOCK_NEW) new_button.set_property("has-tooltip", True) new_button.connect("query-tooltip", self.new_project_tooltip_callback) new_button.set_is_important(True) toolbar.insert(new_button, 0) new_button.set_action_name("win.new-project") # Button for the 'open' action open_button = Gtk.ToolButton.new_from_stock(Gtk.STOCK_OPEN) open_button.set_property("has-tooltip", True) open_button.connect("query-tooltip", self.open_project_tooltip_callback) open_button.set_is_important(True) toolbar.insert(open_button, 1) open_button.set_action_name("win.open-project") # Button for the 'undo' action undo_button = Gtk.ToolButton.new_from_stock(Gtk.STOCK_UNDO) undo_button.set_property("has-tooltip", True) undo_button.connect("query-tooltip", self.undo_tooltip_callback) undo_button.set_is_important(True) toolbar.insert(undo_button, 2) undo_button.set_action_name("win.undo") # Button for the 'fullscreen/leave fullscreen' action self.fullscreen_button = Gtk.ToolButton.new_from_stock( Gtk.STOCK_FULLSCREEN) self.fullscreen_button.set_property("has-tooltip", True) self.fullscreen_button.connect("query-tooltip", self.fullscreen_tooltip_callback) self.fullscreen_button.set_is_important(True) toolbar.insert(self.fullscreen_button, 3) self.fullscreen_button.set_action_name("win.fullscreen") # return the complete toolbar return toolbar ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## # ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ # # ~ Callbacks ~ # # ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ # ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## # # # # Toolbar Tooltips Callbacks # # # # def new_project_tooltip_callback(self, widget, x, y, keyboard_mode, tooltip): tooltip.set_text("Crear un nuevo proyecto") tooltip.set_icon_from_stock("gtk-new", Gtk.IconSize.MENU) return True def open_project_tooltip_callback(self, widget, x, y, keyboard_mode, tooltip): tooltip.set_text("Abrir un proyecto existente") tooltip.set_icon_from_stock("gtk-open", Gtk.IconSize.MENU) return True def undo_tooltip_callback(self, widget, x, y, keyboard_mode, tooltip): tooltip.set_text("Deshacer la última acción") tooltip.set_icon_from_stock("gtk-undo", Gtk.IconSize.MENU) return True def fullscreen_tooltip_callback(self, widget, x, y, keyboard_mode, tooltip): tooltip.set_text("Modo pantalla completa") tooltip.set_icon_from_stock("gtk-fullscreen", Gtk.IconSize.MENU) return True # # # # Toolbar Callbacks # # # # def new_project_callback(self, action, parameter): print("You clicked \"New Project\".") def open_project_callback(self, action, parameter): # Create a filechooserdialog to open: # The arguments are: title of the window, parent_window, action, # (buttons, response) open_project_dialog = Gtk.FileChooserDialog("Seleccione un proyecto", self, Gtk.FileChooserAction.OPEN, (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, Gtk.ResponseType.ACCEPT)) # Not only local files can be selected in the file selector open_project_dialog.set_local_only(False) # Connect the dialog with the callback function open_response_callback_response() open_project_dialog.connect("response", self.__open_project_callback_response) # Show the dialog open_project_dialog.show() def __open_project_callback_response(self, dialog, response_id): open_project_dialog = dialog if response_id == Gtk.ResponseType.ACCEPT: # Filename we get from the FileChooserDialog self.project_filename = open_project_dialog.get_filename() dialog.destroy() # Read project #data = json.load(self.project_filename) def undo_callback(self, action, parameter): print("You clicked \"Undo\".") def fullscreen_callback(self, action, parameter): # check if the state is the same as Gdk.WindowState.FULLSCREEN, which # is a bit flag is_fullscreen = self.get_window().get_state( ) & Gdk.WindowState.FULLSCREEN != 0 if not is_fullscreen: self.fullscreen_button.set_stock_id(Gtk.STOCK_LEAVE_FULLSCREEN) self.fullscreen() else: self.fullscreen_button.set_stock_id(Gtk.STOCK_FULLSCREEN) self.unfullscreen() ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## # ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ # # ~ Application Class ~ # # ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ # ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## class Application(Gtk.Application): def __init__(self): super(Application, self).__init__() def do_activate(self): self._win_main = Window(self) self._win_main.show_all() def do_startup(self): # FIRST THING TO DO: do_startup() Gtk.Application.do_startup(self) # The Application Menubar builder = Gtk.Builder() try: builder.add_from_file(MENU_FILE) except: print("ERROR: " + MENU_FILE +" not found") sys.exit() self.set_menubar(builder.get_object("menubar")) # [2] The Menubar Actions new_project_action = Gio.SimpleAction.new("new", None) new_project_action.connect("activate", self.new_project_callback) self.add_action(new_project_action) open_project_action = Gio.SimpleAction.new("open", None) open_project_action.connect("activate", self.open_project_callback) self.add_action(open_project_action) save_action = Gio.SimpleAction.new("save", None) save_action.connect("activate", self.save_callback) self.add_action(save_action) save_as_action = Gio.SimpleAction.new("save-as", None) save_as_action.connect("activate", self.save_as_callback) self.add_action(save_as_action) quit_action = Gio.SimpleAction.new("quit", None) quit_action.connect("activate", self.quit_callback) self.add_action(quit_action) # # # # Menubar Callbacks # # # # def new_project_callback(self, action, parameter): print("You clicked \"New\"") def open_project_callback(self, action, parameter): self._win_main.open_project_callback(action, parameter) def save_callback(self, action, parameter): print("You clicked \"Save\"") def save_as_callback(self, action, parameter): print("You clicked \"Save as..\"") def quit_callback(self, action, parameter): self.quit() if __name__ == "__main__": app = Application() app.run(sys.argv)
menubar.ui
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<menu id="menubar">
<submenu>
<attribute name="label" translatable="yes">_Archivo</attribute>
<section>
<item>
<attribute name="label" translatable="yes">Nuevo</attribute>
<attribute name="action">app.new</attribute>
</item>
<item>
<attribute name="label" translatable="yes">Abrir...</attribute>
<attribute name="action">app.open</attribute>
<attribute name="accel"><Primary>o</attribute>
</item>
</section>
<section>
<item>
<attribute name ="label" translatable="yes">Guardar</attribute>
<attribute name="action">app.save</attribute>
<attribute name="accel"><Primary>s</attribute>
</item>
<item>
<attribute name ="label" translatable="yes">Guardar Como...</attribute>
<attribute name="action">app.save-as</attribute>
<!--<attribute name="accel"><Primary>a</attribute>-->
</item>
</section>
<section>
<item>
<attribute name ="label" translatable="yes">Salir</attribute>
<attribute name="action">app.quit</attribute>
<attribute name="accel"><Primary>q</attribute>
</item>
</section>
</submenu>
<submenu>
<attribute name="label" translatable="yes">_Preferencias</attribute>
<section>
<item>
<attribute name="label" translatable="yes">_Idioma</attribute>
<attribute name="action">app.language</attribute>
</item>
</section>
</submenu>
<submenu>
<attribute name="label" translatable="yes">A_yuda</attribute>
<section>
<item>
<attribute name="label" translatable="yes">Acerca de FreeComet</attribute>
<attribute name="action">app.about</attribute>
</item>
</section>
</submenu>
</menu>
</interface>
我需要在主应用程序窗口中包含不同小部件的网格。由于我刚接触Gtk,所以我决定从创建一个简单的布局开始,以便我可以更好地理解其背后的逻辑。 ...
这是您可能要查看的快速汇总的.ui文件。附带说明,我可以将所有小部件都放在.ui文件中,因为我可以在Glade中查看层次结构。