在我之前的问题(actually the answer)中,我可以找到一种方法来创建Gtk.PopoverMenu
,其中包含ModelButtons
(正常和切换)。但我真的很想如何以这种方式创建一个单选按钮。
Older examples使用Gtk.ActionGroups
,但自GTK 3.10起他们have been deprecated。我不知道如何构建Gio.ActionGroup
(https://lazka.github.io/pgi-docs/#Gio-2.0/interfaces/ActionGroup.html#Gio.ActionGroup):
action_group = Gio.ActionGroup()
NotImplementedError: ActionGroup can not be constructed
和
action_group = Gio.ActionGroup.new()
AttributeError: type object 'ActionGroup' has no attribute 'new'
Gio.ActionMap
(https://lazka.github.io/pgi-docs/#Gio-2.0/interfaces/ActionMap.html#Gio.ActionMap):
actionmap = Gio.ActionMap()
NotImplementedError: ActionMap can not be constructed
和
actionmap = Gio.ActionMap.new()
AttributeError: type object 'ActionMap' has no attribute 'new'
我不确定为什么会这样:
actionmap = Gio.ActionMap.add_action(self, action_yes)
actionmap = Gio.ActionMap.add_action(self, action_no)
希望有人可以帮助我,让我把它排在脑后:
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)
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("actionmap_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)
action_print = Gio.SimpleAction.new("print", None)
action_print.connect("activate", self.print_something)
app.add_action(action_print)
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)
action_yes = Gio.SimpleAction.new("yes", None)
action_yes.connect("activate", self.print_something)
app.add_action(action_yes)
action_no = Gio.SimpleAction.new("no", None)
action_no.connect("activate", self.print_something)
app.add_action(action_no)
actionmap = Gio.ActionMap.add_action(self, action_yes)
actionmap = Gio.ActionMap.add_action(self, action_no)
#action_group = Gio.ActionGroup.new()
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)
XML接口:
<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>
<child>
<object class="GtkModelButton" id="mp_yes">
<property name="visible">True</property>
<property name="action-name">app.yes</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="label" translatable="yes">Yes</property>
</object>
</child>
<child>
<object class="GtkModelButton" id="mp_no">
<property name="visible">True</property>
<property name="action-name">app.no</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="label" translatable="yes">No</property>
</object>
</child>
</object>
</child>
</object>
</interface>
还有另一个example here。但它也没有显示如何正确地做无线电。如上面的例子所示,切换似乎很简单。
答案 0 :(得分:2)
我最近与mgedmin进行了交谈,他有一个放射性行动组(https://github.com/gtimelog/gtimelog/blob/da38b1ac9fc8b81a2b92884a755f311a99e22d0e/mockup.py)的工作示例。我相应地调整了我的例子。请注意XML接口的不同结构。
的Python:
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gio, Gtk, GLib
import sys
class MainApplication(Gtk.Application):
def __init__(self):
Gtk.Application.__init__(self,
application_id="needs.dots",
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)
app.add_window(self.window)
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")
button_settings.set_menu_model(\
self.builder.get_object('options-menu'))
# Add radiobutton group that includes all actions that
# are named ***.radiogroup, 'radio-two' is the default
# choice.
detail_level = Gio.SimpleAction.new_stateful("radiogroup", \
GLib.VariantType.new("s"), \
GLib.Variant("s", "radio-two"))
detail_level.connect("activate", self.radio_response)
self.window.add_action(detail_level)
# 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 radio_response(self, act_obj, act_lbl):
# Not sure if this is the correct way of doing this.
# but it seems to work.
act_obj.set_state(act_lbl)
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)
UI-文件:
<interface>
<menu id="options-menu">
<section>
<item>
<attribute name="label">Print Message</attribute>
<attribute name="action">app.print</attribute>
</item>
</section>
<section>
<item>
<attribute name="label">Night Mode</attribute>
<attribute name="action">app.toggle</attribute>
</item>
</section>
<section>
<item>
<attribute name="label">Choice 1</attribute>
<attribute name="action">win.radiogroup</attribute>
<attribute name="target">radio-one</attribute>
</item>
<item>
<attribute name="label">Choice 2</attribute>
<attribute name="action">win.radiogroup</attribute>
<attribute name="target">radio-two</attribute>
</item>
<item>
<attribute name="label">Choice 3</attribute>
<attribute name="action">win.radiogroup</attribute>
<attribute name="target">radio-three</attribute>
</item>
</section>
</menu>
</interface>
生成的界面:
答案 1 :(得分:0)
我修改了几周前我做过的一些代码。这可能会有所帮助。与您尝试做的相比,它有点简单,但另一方面,它有效。
还有很多额外的代码。 RadioMenuButtons在MyPopup函数中创建。它使用btndef
参数调用,该参数包含元组列表。如果元组有多个元素,那么它会生成一个单选按钮组。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# test_gtk3_popover.py
#
# Copyright 2015 John Coppens <john@jcoppens.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301, USA.
#
#
from gi.repository import Gtk
class MyPopup(Gtk.MenuButton):
def __init__(self, btndefs):
super(MyPopup, self).__init__()
self.menu = Gtk.Menu()
self.set_popup(self.menu)
self.set_label(">")
self.set_direction(Gtk.ArrowType.RIGHT)
for btndef in btndefs:
if len(btndef) == 1: # This is a normal button
item = Gtk.MenuItem()
item.set_label(btndef[0])
item.show()
self.menu.append(item)
else:
group = None
for radiodef in btndef: # It's a selection of radiobuttons
item = Gtk.RadioMenuItem(label = radiodef)
if group == None:
group = item
else:
item.set_property("group", group)
item.show()
self.menu.append(item)
class MainWindow(Gtk.Window):
def __init__(self):
super(MainWindow, self).__init__()
self.set_size_request(200, -1)
self.connect("destroy", lambda x: Gtk.main_quit())
self.hbox = Gtk.Box(orientation = Gtk.Orientation.HORIZONTAL)
self.entry = Gtk.Entry()
self.popup = MyPopup( (("String", "String no case", "Hexadecimal"),
("Regexp",)) )
self.hbox.pack_start(self.entry, True, True, 0)
self.hbox.pack_start(self.popup, False, True, 0)
self.add(self.hbox)
self.show_all()
def run(self):
Gtk.main()
def main():
mw = MainWindow()
mw.run()
return 0
if __name__ == '__main__':
main()