使用PyGObject正确地构建和突出显示GtkPopoverMenu [英] Properly structure and highlight a GtkPopoverMenu using PyGObject

查看:192
本文介绍了使用PyGObject正确地构建和突出显示GtkPopoverMenu的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图用 Gtk.PopoverMenus 来举例说明正确的 Gtk.HeaderBar ,它显示使用不同的小部件。我查看了很多示例和代码,但无法弄清楚,如何使用 Gtk.ModelButton



特别是这句对我来说毫无意义:


当通过action-name和action-target属性指定动作时,按钮的作用(即它是否是普通的,检查或单选按钮)由动作类型决定,并且不必用角色属性明确指定。




无论如何,这里是我尝试在PopoverMenu中使用正常的小部件,导致突出显示不一致(整行应该突出显示):



所以我的问题是: ModelButtons 如何分类, ar正确 PopoverMenu -widgets?



以下是Python代码:

from gi.repository import Gtk,Gio

class HeaderBarWindow(Gtk.Window):

def __init __(self):
Gtk.Window .__ init __(self,title =HeaderBar& PopoverMenu)
self.set_border_width(10)
self.set_default_size(400,400)
builder = Gtk.Builder()
objects = builder.add_objects_from_file(popovermenu_layout.xml ,(pom_options,))
pom_opt = builder.get_object(pom_options)
builder.connect_signals(self)

hb = Gtk.HeaderBar()
hb.set_show_close_button(True)
hb.props.title =HeaderBar& PopoverMenu
self.set_titlebar(hb)

on onclick(button,popovermenu):

切换相应的popovermenu。

如果popovermenu.get_visible():
popovermenu.hide()
else:
popovermenu.show_all()

button_opt = Gtk.Button()
icon = Gio.ThemedIcon(name =format-justify-fill-symbolic)
image = Gtk.Image.new_from_gicon(icon,Gtk.IconSize.BUTTON)
button_opt.add(image)
hb.pack_end(button_opt)
pom_opt.set_relative_to(button_opt)
button_opt.connect(clicked,on_click,pom_opt)

self.add(Gtk.TextView())

def print_something(self,modelbutton,event):
print(你按下了一个按钮)

def night_mode_switcher(self,switch,state):
Gtk.Settings.get_default()。set_property(gtk-application-prefer-dark-theme,state)

win = HeaderBarWindow()
win.connect(delete-event,Gtk.main_quit)
win.show_all()
Gtk.main()

以下是PopoverMenu的模型:

 < interface> ; 
< object class =GtkPopoverMenuid =pom_options>
< child>
< object class =GtkBox>
< property name =visible> True< / property>
< property name =margin> 10< / property>
< property name =orientation> vertical< / property>
< child>
< object class =GtkModelButtonid =mb_print>
< property name =visible> True< / property>
< property name =texttranslatable =yes>列印< / property>
< property name =can_focus> True< / property>
< property name =receiving_default> True< / property>
< signal name =button-press-eventhandler =print_somethingswapped =no/>
< / object>
< / child>
< child>
< object class =GtkCheckButtonid =checkbutton1>
< property name =labeltranslatable =yes> checkbutton< / property>
< property name =visible> True< / property>
< property name =can_focus> True< / property>
< property name =receiving_default> False< / property>
< property name =draw_indicator> True< / property>
< / object>
< / child>
< child>
< object class =GtkBoxid =box1>
< property name =visible> True< / property>
< property name =can_focus> False< / property>
< child>
< object class =GtkSwitchid =switch1>
< property name =visible> True< / property>
< property name =can_focus> True< / property>
< signal name =state-sethandler =night_mode_switcherswapped =no/>
< property name =margin_start> 9< / property>
< property name =margin_end> 9< / property>
< / object>
<包装>
< property name =expand> False< / property>
< property name =fill> True< / property>
< property name =position> 0< / property>
< / packing>
< / child>
< child>
< object class =GtkModelButtonid =mb_night>
< property name =visible> True< / property>
< property name =can_focus> False< / property>
< property name =margin_start> 9< / property>
< property name =margin_end> 9< / property>
< / object>
<包装>
< property name =expand> True< / property>
< property name =fill> True< / property>
< property name =position> 1< / property>
< / packing>
< / child>
< / object>
< / child>
< / object>
< / child>
< / object>
< / interface>


解决方案

我设法解决大部分问题。最重要的是,似乎必须使用 Gtk.Application Gtk.ApplicationWindow 。我不能说我完全理解为什么,但是这可以以 Gio.SimpleActions Actions c>到应用程序。 Gtk.Builder 解析菜单的 XML ,并且可以简单地使用 set_popover -method。然后对于在XML中定义的每个动作(不要忘记XML中的 app。 -prefix)a Gio.SimpleAction (没有 app。 -prefix作为名称)并添加到应用程序中。我有一个正常的按钮,和一个checkbutton工作。仍然挣扎着单选按钮,但这可能是另一个问题。



以下是Python代码:

<$ p $ g $ g $ g $ g $ g $ g $ g $ g $ g $ g $ g $ g $ g $ g $ g $ g $ g $ g $ g $ g $ g $ g $ g $ g
def __init __(self):
Gtk.Application .__ init __(self,
application_id =needs.dot,
flags = Gio.ApplicationFlags.FLAGS_NONE)
# https://developer.gnome.org/gio/unstable/GApplication.html#g-application-id-is-valid
self.connect(activate,self.activate_window)

def activate_window(self,app):

Gtk.Application的激活信号将MainApplication类
传递给窗口,窗口被设置为该窗口的窗口。

self.window = Gtk.ApplicationWindow()
self.window.set_default_size(500,400)

self.hb = Gtk.HeaderBar()
self.hb.set_show_close_button(True)
self.hb.props.title =HeaderBar& PopOverMenu
self.window.set_titlebar(self.hb)
$ b button_settings = Gtk.MenuButton()
icon = Gio.ThemedIcon(name =format-justify-fill-符号)
image = Gtk.Image.new_from_gicon(icon,Gtk.IconSize.BUTTON)
button_settings.add(image)
self.hb.pack_end(button_settings)

self.builder = Gtk.Builder()
self.builder.add_from_file(popovermenu_layout.xml)
pom_options = self.builder.get_object(pom_options)
button_settings。 set_popover(pom_options)
#self.builder.connect_signals(self)#因为使用操作而不需要

app.add_window(self.window)

# XML名称的第一部分已被删除:
#< property name =action-name> app.print< / property>
#becomes只是打印 。
action_print = Gio.SimpleAction.new(print,None)
action _print.connect(activate,self.print_something)
app.add_action(action_print)

#app.toggle变成 - > toggle
action_toggle = Gio.SimpleAction.new_stateful(toggle,None,GLib.Variant.new_boolean(False))
action_toggle.connect(change-state,self.toggle_toggled)
app.add_action(action_toggle)

btn = Gtk.Button(Button)
self.window.add(btn)
self.window.show_all()

def print_something(self,action,variable):
print(something)

def toggle_toggled(self,action,state):
action.set_state (状态)
Gtk.Settings.get_default().set_property(gtk-application-prefer-dark-theme,状态)

def on_action_quit_activated(self,action):
self.app.quit()


if __name__ ==__main__:

创建MainApplication类的一个实例,继承自
Gtk.Application。

app = MainApplication()
app.run(sys.argv)

和XML文件菜单:

 < interface> 
< object class =GtkPopoverMenuid =pom_options>
< child>
< object class =GtkBox>
< property name =visible> True< / property>
< property name =margin> 10< / property>
< property name =orientation> vertical< / property>
< child>
< object class =GtkModelButtonid =mb_print>
< property name =visible> True< / property>
< property name =action-name> app.print< / property>
< property name =can_focus> True< / property>
< property name =receiving_default> True< / property>
< / object>
< / child>
< child>
< object class =GtkModelButtonid =mp_toggle>
< property name =visible> True< / property>
< property name =action-name> app.toggle< / property>
< property name =can_focus> True< / property>
< property name =receiving_default> True< / property>
< / object>
< / child>
< / object>
< / child>
< / object>
< / interface>


I am trying to make an example of a proper Gtk.HeaderBar with Gtk.PopoverMenus that shows how the different widgets are used. I looked at a lot of examples and code, but can't figure out, how to work the Gtk.ModelButton.

Especially this sentence makes no sense to me:

When the action is specified via the "action-name" and "action-target" properties, the role of the button (i.e. whether it is a plain, check or radio button) is determined by the type of the action and doesn't have to be explicitly specified with the "role" property.

In any case, here is my attempt to just use normal widgets in the PopoverMenu, leading to inconsistent highlighting (the whole row should be highlighted):

So my question is: How are ModelButtons subclassed, so they appear as proper PopoverMenu-widgets?

Here is the Python code:

from gi.repository import Gtk, Gio

class HeaderBarWindow(Gtk.Window):

    def __init__(self):
        Gtk.Window.__init__(self, title="HeaderBar & PopoverMenu")
        self.set_border_width(10)
        self.set_default_size(400, 400)
        builder = Gtk.Builder()
        objects = builder.add_objects_from_file("popovermenu_layout.xml", ("pom_options", ""))
        pom_opt = builder.get_object("pom_options")
        builder.connect_signals(self)

        hb = Gtk.HeaderBar()
        hb.set_show_close_button(True)
        hb.props.title = "HeaderBar & PopoverMenu"
        self.set_titlebar(hb)

        def on_click(button, popovermenu):
            """
            Toggles the respective popovermenu.
            """
            if popovermenu.get_visible():
                popovermenu.hide()
            else:
                popovermenu.show_all()

        button_opt = Gtk.Button()
        icon = Gio.ThemedIcon(name="format-justify-fill-symbolic")
        image = Gtk.Image.new_from_gicon(icon, Gtk.IconSize.BUTTON)
        button_opt.add(image)
        hb.pack_end(button_opt)
        pom_opt.set_relative_to(button_opt)
        button_opt.connect("clicked", on_click, pom_opt)

        self.add(Gtk.TextView())

    def print_something(self, modelbutton, event):
        print("you pressed a button")

    def night_mode_switcher(self, switch, state):
        Gtk.Settings.get_default().set_property("gtk-application-prefer-dark-theme", state)

win = HeaderBarWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()

And here is the model for the PopoverMenu:

<interface>
    <object class="GtkPopoverMenu" id ="pom_options">
      <child>
        <object class="GtkBox">
          <property name="visible">True</property>
          <property name="margin">10</property>
          <property name="orientation">vertical</property>
          <child>
            <object class="GtkModelButton" id="mb_print">
              <property name="visible">True</property>
              <property name="text" translatable="yes">Print</property>
              <property name="can_focus">True</property>
              <property name="receives_default">True</property>
              <signal name="button-press-event" handler="print_something" swapped="no"/>
            </object>
          </child>
          <child>
            <object class="GtkCheckButton" id="checkbutton1">
              <property name="label" translatable="yes">checkbutton</property>
              <property name="visible">True</property>
              <property name="can_focus">True</property>
              <property name="receives_default">False</property>
              <property name="draw_indicator">True</property>
            </object>
          </child>
          <child>
              <object class="GtkBox" id="box1">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <child>
                  <object class="GtkSwitch" id="switch1">
                    <property name="visible">True</property>
                    <property name="can_focus">True</property>
                    <signal name="state-set" handler="night_mode_switcher" swapped="no"/>
                    <property name="margin_start">9</property>
                    <property name="margin_end">9</property>
                  </object>
                  <packing>
                    <property name="expand">False</property>
                    <property name="fill">True</property>
                    <property name="position">0</property>
                  </packing>
                </child>
                <child>
                  <object class="GtkModelButton" id="mb_night">
                    <property name="text" translatable="yes">Night Mode</property>
                    <property name="visible">True</property>
                    <property name="can_focus">False</property>
                    <property name="margin_start">9</property>
                    <property name="margin_end">9</property>
                  </object>
                  <packing>
                    <property name="expand">True</property>
                    <property name="fill">True</property>
                    <property name="position">1</property>
                  </packing>
                </child>
              </object>
          </child>
        </object>
      </child>
    </object>
</interface>

解决方案

I managed to solve most of what my question was. Most importantly it seems that one has to use Gtk.Application and Gtk.ApplicationWindow. I can't say that I fully understand why, but that makes it possible to add Actions in the form of Gio.SimpleActions to the application. Gtk.Builder parses the XML of the menu, and one can simply add it tot the menu using the set_popover-method. Then for each action defined in the XML (don't forget the app.-prefix in the XML) a Gio.SimpleAction is created (without the app.-prefix as name) in the Python-code and added to the application. I got a normal button, and a checkbutton to work. Still struggling with the radiobutton, but that might be another question.

Here is the Python-code:

from gi.repository import Gio, Gtk, GLib
import sys


class MainApplication(Gtk.Application):

    def __init__(self):
        Gtk.Application.__init__(self,
                                 application_id="needs.dot",
                                 flags=Gio.ApplicationFlags.FLAGS_NONE)
        #https://developer.gnome.org/gio/unstable/GApplication.html#g-application-id-is-valid
        self.connect("activate", self.activate_window)

    def activate_window(self, app):
        """
        The activate signal of Gtk.Application passes the MainApplication class
        to the window. The window is then set as a window of that class.
        """
        self.window = Gtk.ApplicationWindow()
        self.window.set_default_size(500, 400)

        self.hb = Gtk.HeaderBar()
        self.hb.set_show_close_button(True)
        self.hb.props.title = "HeaderBar & PopOverMenu"
        self.window.set_titlebar(self.hb)

        button_settings = Gtk.MenuButton()
        icon = Gio.ThemedIcon(name="format-justify-fill-symbolic")
        image = Gtk.Image.new_from_gicon(icon, Gtk.IconSize.BUTTON)
        button_settings.add(image)
        self.hb.pack_end(button_settings)

        self.builder = Gtk.Builder()
        self.builder.add_from_file("popovermenu_layout.xml")
        pom_options = self.builder.get_object("pom_options")
        button_settings.set_popover(pom_options)
        #self.builder.connect_signals(self) #Not needed because of using actions?

        app.add_window(self.window)

        #Connects to the action. The first part of the XML name is left away:
        #<property name="action-name">app.print</property>
        #becomes simply "print".
        action_print = Gio.SimpleAction.new("print", None)
        action_print.connect("activate", self.print_something)
        app.add_action(action_print)

        #app.toggle becomes -> toggle
        action_toggle = Gio.SimpleAction.new_stateful("toggle", None, GLib.Variant.new_boolean(False))
        action_toggle.connect("change-state", self.toggle_toggled)
        app.add_action(action_toggle)

        btn = Gtk.Button("Button")
        self.window.add(btn)
        self.window.show_all()

    def print_something(self, action, variable):
        print("something")

    def toggle_toggled(self, action, state):
        action.set_state(state)
        Gtk.Settings.get_default().set_property("gtk-application-prefer-dark-theme", state)

    def on_action_quit_activated(self, action):
        self.app.quit()


if __name__ == "__main__":
    """
    Creates an instance of the MainApplication class that inherits from
    Gtk.Application.
    """
    app = MainApplication()
    app.run(sys.argv)

and the XML-file for the menu:

<interface>
    <object class="GtkPopoverMenu" id ="pom_options">
      <child>
        <object class="GtkBox">
          <property name="visible">True</property>
          <property name="margin">10</property>
          <property name="orientation">vertical</property>
          <child>
            <object class="GtkModelButton" id="mb_print">
              <property name="visible">True</property>
              <property name="action-name">app.print</property>
              <property name="can_focus">True</property>
              <property name="receives_default">True</property>
              <property name="label" translatable="yes">Print</property>
            </object>
          </child>
          <child>
            <object class="GtkModelButton" id="mp_toggle">
              <property name="visible">True</property>
              <property name="action-name">app.toggle</property>
              <property name="can_focus">True</property>
              <property name="receives_default">True</property>
              <property name="label" translatable="yes">Night Mode</property>
            </object>
          </child>
        </object>
      </child>
    </object>
</interface>

这篇关于使用PyGObject正确地构建和突出显示GtkPopoverMenu的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆