问题描述
我正在学习PyGobject(pygtk3),在pygtk popover tutorial处给出的示例包括一些用于菜单项的XML文件。我不想在我的pygtk程序中使用xml或glade .ui。因此创建了具有3个菜单项的菜单。这个例子效果很好,但看起来更像是hack。托管弹出窗口的切换按钮需要手动激活/停用,如本例中的功能/方法所示。有没有更好的方法来使按钮切换和菜单/隐藏显示有这样的切换?我在观看Michael B. Popover Tutorial - Youtube时有一些想法,我们确实需要更多的pygtk / pygobject教程以及一些实用的示例,以使更多的人加入自由软件。
#!/usr/bin/python3
import gi
gi.require_version("Gtk","3.0")
from gi.repository import Gtk
class PopoverWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self,title="Popover Demo")
self.set_border_width(10)
self.set_default_size(300,200)
outerBox = Gtk.Box(spacing=6,orientation=Gtk.Orientation.VERTICAL)
self.add(outerBox)
#Menu button which will have popover
self.menuButton = Gtk.ToggleButton.new_with_label("Click Me")
self.menuButton.connect("toggled",self.on_click_me_clicked)
outerBox.pack_start(self.menuButton,False,True,0)
self.popover = Gtk.Popover()
vBox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
#popover menu adding items with buttons in vBox container
vBox = Gtk.Box(spacing=1,orientation=Gtk.Orientation.VERTICAL)
vBox.set_border_width(5)
menu_item_button1=Gtk.ModelButton()
menu_item_button1.set_label("Menu Item 1")
menu_item_button1.connect("clicked",self.start_menu_item1_function)
vBox.pack_start(menu_item_button1,5)
menu_item_button2=Gtk.ModelButton()
menu_item_button2.set_label("Menu Item 2")
menu_item_button2.connect("clicked",self.start_menu_item2_function)
vBox.pack_start(menu_item_button2,5)
#add quit menu item
menu_item_button3=Gtk.ModelButton()
menu_item_button3.set_label("Quit")
menu_item_button3.connect("clicked",Gtk.main_quit)
vBox.pack_start(menu_item_button3,5)
#put the buttons in popover menu using vBox container
self.popover.add(vBox)
self.popover.set_position(Gtk.PositionType.BottOM)
def start_menu_item1_function(self,button):
#on selection of the menu in the popover
#we need to manually toggle the button
self.menuButton.set_active(False)
print("1st menu item selected")
def start_menu_item2_function(self,button):
#on selection of the menu in the popover
#we need to manually toggle the button
self.menuButton.set_active(False)
print("2nd menu item selected")
# to make toggle button hide the show/hide the menu
def on_click_me_clicked(self,button):
if button.get_active():
self.popover.set_modal(False)
self.popover.set_relative_to(button)
self.popover.show_all()
self.popover.popup()
else:
self.popover.popdown()
win = PopoverWindow()
win.connect("destroy",Gtk.main_quit)
win.show_all()
Gtk.main()
解决方法
Menu Popover使用XML文件,但是我只需要手动菜单项就不需要XML。找到了解决方案,但必须将gtk.Window放入Gtk.ApplicationWindow
#!/usr/bin/python3
import gi
# Popover menubutton without MENU XML
# manual Menu Items without XML using menu model
# Needs Application Window for Gtk.MenuButton + menuModel
gi.require_version("Gtk","3.0")
from gi.repository import Gtk,Gio
class PopoverWindow(Gtk.ApplicationWindow):
def __init__(self,*args,**kwargs):
Gtk.Window.__init__(self,title="Popover Demo")
self.set_border_width(10)
self.set_default_size(300,200)
outerbox = Gtk.Box(spacing=6,orientation=Gtk.Orientation.VERTICAL)
#Menu button which will have popover
self.menuButton = Gtk.MenuButton()
self.menuButton.set_label("Click Me!")
# Put the button in the container box
outerbox.pack_start(self.menuButton,False,True,0)
self.add(outerbox)
# Creating menu items Using Menu model
menuModel = Gio.Menu()
# menmodel items have (label) and action name with win.XX or app.XX
menuModel.append("Item 1 - label 1","win.XX")
menuModel.append("About Your Computer","win.About_Your_Computer")
menuModel.append("Asif Ali Rizvan","win.riz")
# menu is set as the menu of the menubutton
self.menuButton.set_menu_model(menuModel)
# the set action XX from win.XX,skip the win. prefix
#1st menu item
about_action = Gio.SimpleAction.new("XX",None)
about_action.connect("activate",self.item1_XX_method)
self.add_action(about_action)
# 2nd menu item
about_action = Gio.SimpleAction.new("About_Your_Computer",self.about_your_computer_function)
self.add_action(about_action)
# 3rd menu item
riz_action = Gio.SimpleAction.new("riz",None)
riz_action.connect("activate",self.riz_callback)
self.add_action(riz_action)
def item1_XX_method(self,action,parameter):
print("Menu Item 1 Selected")
def about_your_computer_function(self,parameter):
print("Your Computer is an Electronic Device.")
def riz_callback(self,parameter):
print("You clicked \"Asif Ali Rizvan\"")
win = PopoverWindow()
win.connect("destroy",Gtk.main_quit)
win.show_all()
Gtk.main()
,
在这里使用带有Menumodel的Popover,在第35行添加了36行注释,并添加了2行popover代码。
#!/usr/bin/python3
import gi
# Popover menubutton without MENU XML
# manual Menu Items without XML using menu model
# Needs Application Window for Gtk.MenuButton + menuModel
gi.require_version("Gtk","win.riz")
# menu is set as the menu of the menubutton
#self.menuButton.set_menu_model(menuModel)
# USE POPOVER instead
popover = Gtk.Popover.new_from_model(self.menuButton,menuModel)
self.menuButton.set_popover(popover)
# the set action XX from win.XX,Gtk.main_quit)
win.show_all()
Gtk.main()
,
最后通过使用ModelButton的正常菜单项和框式容器内的小部件,最终获得了更好的Popover + MenuButton +手动菜单项。 MenuModel不像带有带有窗口小部件的容器的弹出框那样丰富,可以在此处看到:
#!/usr/bin/python3
import gi
# Popover menu button without MENU XML
# popover menu with different widgets
# using vbox container inside popover
# GPL3+ (C) Asif Ali Rizvan <fast.rizwaan@gmail.com>
gi.require_version("Gtk",Gio
class PopoverWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self,title="Popover Demo")
self.set_border_width(10)
self.set_default_size(400,300)
# box0 is the main box container which will hold the mb0
box0 = Gtk.Box(spacing=6,orientation=Gtk.Orientation.VERTICAL)
self.add(box0)
# mb0 is Gtk.MenuButton which will include the coming popover
mb0 = Gtk.MenuButton()
mb0.set_label("Click Me")
box0.pack_start(mb0,0)
# Create popover
popover = Gtk.Popover()
# vbox container for adding items in Popover menu
vbox = Gtk.Box(spacing=1,orientation=Gtk.Orientation.VERTICAL)
vbox.set_border_width(5)
# 1st Gtk Entry widget
menu_item_1= Gtk.Entry()
#menu_item_1.set_text("Hello World")
vbox.pack_start(menu_item_1,5)
# 2nd Gtk Toggle Button Widget
menu_item_2= Gtk.ToggleButton()
menu_item_2.set_label("Toggle Button")
menu_item_2.connect("toggled",self.call_menu_item2_function)
vbox.pack_start(menu_item_2,5)
# hbox is horzitontal box container for adding items sidewise
# in vbox of Popover menu.
# we are packing container with widgets inside container (hbox in vbox)
hbox = Gtk.Box(spacing=1,orientation=Gtk.Orientation.HORIZONTAL)
hbox.set_border_width(0)
# 3rd Gtk Button
menu_item_3=Gtk.Button()
menu_item_3.set_label("Menu Item 3")
menu_item_3.connect("clicked",self.call_menu_item3_function)
hbox.pack_start(menu_item_3,5)
# 4th Add quit menu item
menu_item_4=Gtk.CheckButton()
menu_item_4.set_label("Quit")
menu_item_4.connect("clicked",Gtk.main_quit)
hbox.pack_start(menu_item_4,5)
# add hbox (horizontal box) in vbox (vertical box container of popover)
vbox.pack_start(hbox,0)
# add the vbox container with hbox+widgets and other widgets
# in popover menu
popover.add(vbox)
popover.set_position(Gtk.PositionType.BOTTOM)
# add the popover inside mb0 Gtk.MenuButton()
mb0.set_popover(popover)
# show the widgets
popover.show_all()
def call_menu_item2_function(self,button):
print("Menu Item 2 button Toggled")
def call_menu_item3_function(self,button):
print("Menu item 3 Button Clicked")
win = PopoverWindow()
win.connect("destroy",Gtk.main_quit)
win.show_all()
Gtk.main()