Python 在菜单中显示gtk.日历?
我想构造一个上下文菜单,其中包含一个用于选择日期的菜单项。(用例是在树状视图中选择一组项目,然后为所有项目设置一个新的截止日期。) 因为menuitem是Gtk.Bin,所以我可以指定任何小部件来代替标签。然而,我似乎无法与小部件交互。如果单击菜单上的任意位置,菜单项将获得单击。因此,我无法选择特定的日期,也无法浏览月份或年份。如何使日历获得鼠标活动 此外,日历的外部还有多余的填充物,当鼠标悬停在日历上时,它会变成橙色。如何删除填充和/或不突出显示橙色Python 在菜单中显示gtk.日历?,python,ubuntu,gtk,pygtk,Python,Ubuntu,Gtk,Pygtk,我想构造一个上下文菜单,其中包含一个用于选择日期的菜单项。(用例是在树状视图中选择一组项目,然后为所有项目设置一个新的截止日期。) 因为menuitem是Gtk.Bin,所以我可以指定任何小部件来代替标签。然而,我似乎无法与小部件交互。如果单击菜单上的任意位置,菜单项将获得单击。因此,我无法选择特定的日期,也无法浏览月份或年份。如何使日历获得鼠标活动 此外,日历的外部还有多余的填充物,当鼠标悬停在日历上时,它会变成橙色。如何删除填充和/或不突出显示橙色 #!/usr/bin/env python
#!/usr/bin/env python
import gobject
import pygtk
pygtk.require('2.0')
import gtk
import time
class ContextMenu(gtk.Menu):
def __init__(self):
gtk.Menu.__init__(self)
def add_calendar_submenu_item(self, text, callback, uuids, data=None):
calendar = gtk.Calendar()
calendar.show()
calendar_item = gtk.MenuItem()
calendar_item.add(calendar)
calendar_item.show()
submenu = gtk.Menu()
submenu.append(calendar_item)
submenu_item = gtk.MenuItem("%s..." %(text))
submenu_item.set_submenu(submenu)
submenu_item.show()
submenu_item.connect("activate", self.on_calendar_activate)
self.append(submenu_item)
def on_calendar_activate(self, widget):
print "activate"
if __name__ == "__main__":
class CalendarExample:
def __init__(self):
window = gtk.Window(gtk.WINDOW_TOPLEVEL)
window.set_title("Calendar Example")
window.set_border_width(5)
window.set_size_request(200, 100)
window.set_resizable(False)
window.stick()
window.connect("destroy", lambda x: gtk.main_quit())
menu = ContextMenu()
menu.add_calendar_submenu_item("date", self.on_date, ['123'])
root_menu = gtk.MenuItem("Calendar Menu")
root_menu.show()
root_menu.set_submenu(menu)
vbox = gtk.VBox(False, 10)
window.add(vbox)
vbox.show()
menu_bar = gtk.MenuBar()
vbox.pack_start(menu_bar, False, False, 2)
menu_bar.append (root_menu)
menu_bar.show()
button = gtk.Button("Push Me")
button.connect("clicked", self.on_menu_push, menu)
vbox.pack_start(button, False, True, 10)
button.show()
window.show()
def on_menu_push(self, widget, menu):
menu.popup(None, None, None, 0, 0)
def on_action(self, widget, uuids, text):
print "Item %s pressed" %(text)
def on_date(self, widget, uuids, text):
print "Calendar activated with %s" %(text)
CalendarExample()
gtk.main()
[更新]
我想要的是类似于Ubuntu的指示器菜单日期/时间日历的东西
正如在评论中已经提到的,菜单不是为容纳任意小部件而设计的。本节也讨论了这一点。您必须使用弹出窗口选项。你试图模拟的Ubuntu中的时钟小程序使用弹出窗口。您可以使用
xwininfo
验证这一点。如果您显示了日历,然后选择它(对于xwininfo
实用程序),您可以看到它是一个单独的窗口,与面板不同。此外,这可以通过查看。显示的时钟小程序是一个on,显示/隐藏带有日历的弹出窗口(更准确地说,它是一个自定义小程序,扩展了
GtkWindow
,并在创建时适当地扩展)。基于您的代码的相同想法的粗略实现如下(请原谅我有限的python知识):
#/usr/bin/env python
导入gobject
进口pygtk
pygtk.require('2.0')
进口gtk
导入时间
类日历示例:
定义初始化(自):
窗=gtk.window(gtk.window_顶层)
窗口。设置标题(“日历示例”)
窗口。设置边框宽度(5)
窗口。设置大小请求(200100)
window.set_可调整大小(False)
window.stick()
window.connect(“销毁”,lambda x:gtk.main_quit())
vbox=gtk.vbox(假,10)
添加窗口(vbox)
#可以使用WINDOW_POPUP创建下面的窗口,但尝试模拟与窗口相同的属性
#在applet中。
校准窗口=gtk窗口(gtk窗口顶层)
校准窗口。设置装饰(假)
校准窗口。设置可调整大小(错误)
校准窗口。设置类型提示(gtk.gdk.window类型提示)
cal_window.stick()
cal_vbox=gtk.vbox(假,10)
cal_window.add(cal_vbox)
cal_vbox.pack_start(gtk.Calendar(),True,False,0)
校准包装启动(gtk按钮(“虚拟位置”),真、假、0)
toggle_button=gtk.ToggleButton(“显示日历”)
vbox.pack_start(切换_按钮,False,True,10)
切换按钮。连接(“切换”,自开切换,校准窗口)
#跟踪窗口的移动以移动日历窗口
连接(“配置事件”,self.on\u窗口\u配置,切换按钮,校准窗口)
window.show_all()
#无屏幕外校正的日历窗口坐标:
#窗口原点(x,y)
# |
#五
# ---------------------------------
#|主窗口|
# | |
# | |
#|切换按钮(x,y)|
#|(相对于父窗口)|
# | | |
#|V|
# | ......................... |
#日历| |切换按钮||
#窗户的| | ||
#(x,y)--+>|
#|(日历窗口将在此处)|
# | |
# | |
# ---------------------------------
#日历窗口的屏幕坐标:
#x=窗口的原点x+切换按钮的相对x
#y=窗口的原点y+切换按钮的相对y+切换按钮的高度
#“切换”回调,显示和隐藏日历窗口。
def on_切换(自身、切换按钮、校准窗口):
如果切换_按钮。使_处于活动状态():
rect=切换_按钮。获取_分配()
主窗口=切换按钮。获取顶级()
[win\u x,win\u y]=主窗口。获取窗口()。获取原点()
cal_x=win_x+rect.x
cal_y=win_y+矩形y+矩形高度
[x,y]=自我应用屏幕协调校正(校准x,校准y,校准窗口,切换按钮)
校准窗口移动(x,y)
cal_window.show_all()
切换按钮。设置标签(“隐藏日历”)
其他:
cal_window.hide_all()
切换按钮。设置标签(“显示日历”)
#主窗口的“配置事件”回调,尝试将日历窗口与主窗口一起移动。
def on_window_config(自身、小部件、事件、切换按钮、校准窗口):
#也许找到visiblilty的更好方法
如果cal_window.get_mapped():
rect=切换_按钮。获取_分配()
cal_x=事件x+矩形x
cal_y=事件y+矩形y+矩形高度
[x,y]=自我应用屏幕协调校正(校准x,校准y,校准窗口,切换按钮)
校准窗口移动(x,y)
#此函数“尝试”更正日历窗口位置,以便在
#主窗口的一部分不在屏幕上。
#已知错误:如果主窗口在日历窗口之前部分脱离屏幕
#已实现,则get_allocation()将返回1x1的rect,在这种情况下
#计算将失败,且不会应用更正
def应用屏幕协调校正(自我、x、y、小部件、相对小部件):
修正的_y=y
修正的x=x
#!/usr/bin/env python
import gobject
import pygtk
pygtk.require('2.0')
import gtk
import time
class CalendarExample:
def __init__(self):
window = gtk.Window(gtk.WINDOW_TOPLEVEL)
window.set_title("Calendar Example")
window.set_border_width(5)
window.set_size_request(200, 100)
window.set_resizable(False)
window.stick()
window.connect("destroy", lambda x: gtk.main_quit())
vbox = gtk.VBox(False, 10)
window.add(vbox)
# Could have used WINDOW_POPUP to create below window, but trying to emulate the same properties as the window
# in applet.
cal_window = gtk.Window(gtk.WINDOW_TOPLEVEL)
cal_window.set_decorated(False)
cal_window.set_resizable(False)
cal_window.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DOCK)
cal_window.stick()
cal_vbox = gtk.VBox(False, 10)
cal_window.add(cal_vbox)
cal_vbox.pack_start(gtk.Calendar(), True, False, 0)
cal_vbox.pack_start(gtk.Button("Dummy locations"), True, False, 0)
toggle_button = gtk.ToggleButton("Show Calendar")
vbox.pack_start(toggle_button, False, True, 10)
toggle_button.connect("toggled", self.on_toggle, cal_window)
# Track movements of the window to move calendar window as well
window.connect("configure-event", self.on_window_config, toggle_button, cal_window)
window.show_all()
# Calendar window co ordinates without off-screen correction:
# Window origin (x, y)
# |
# V
# ---------------------------------
# | Main Window |
# | |
# | |
# |Toggle button's (x, y) |
# |(relative to parent window) |
# | | |
# | V |
# | ......................... |
# Calendar | | Toggle Button | |
# window's | | | |
# (x, y)---+> ......................... |
# |(Calendar window will be here) |
# | |
# | |
# ---------------------------------
# Calendar Window's screen coordinates:
# x = Window's origin x + Toggle Button's relative x
# y = Window's origin y + Toggle Button's relative y + Toggle Button's height
# "toggle" callback which shows & hides calendar window.
def on_toggle(self, toggle_button, cal_window):
if toggle_button.get_active():
rect = toggle_button.get_allocation()
main_window = toggle_button.get_toplevel()
[win_x, win_y] = main_window.get_window().get_origin()
cal_x = win_x + rect.x
cal_y = win_y + rect.y + rect.height
[x, y] = self.apply_screen_coord_correction(cal_x, cal_y, cal_window, toggle_button)
cal_window.move(x, y)
cal_window.show_all()
toggle_button.set_label("Hide Calendar")
else:
cal_window.hide_all()
toggle_button.set_label("Show Calendar")
# "configure-event" callback of main window, try to move calendar window along with main window.
def on_window_config(self, widget, event, toggle_button, cal_window):
# Maybe better way to find the visiblilty
if cal_window.get_mapped():
rect = toggle_button.get_allocation()
cal_x = event.x + rect.x
cal_y = event.y + rect.y + rect.height
[x, y] = self.apply_screen_coord_correction(cal_x, cal_y, cal_window, toggle_button)
cal_window.move(x, y)
# This function "tries" to correct calendar window position so that it is not obscured when
# a portion of main window is off-screen.
# Known bug: If the main window is partially off-screen before Calendar window
# has been realized then get_allocation() will return rect of 1x1 in which case
# the calculations will fail & correction will not be applied
def apply_screen_coord_correction(self, x, y, widget, relative_widget):
corrected_y = y
corrected_x = x
rect = widget.get_allocation()
screen_w = gtk.gdk.screen_width()
screen_h = gtk.gdk.screen_height()
delta_x = screen_w - (x + rect.width)
delta_y = screen_h - (y + rect.height)
if delta_x < 0:
corrected_x += delta_x
if corrected_x < 0:
corrected_x = 0
if delta_y < 0:
corrected_y = y - rect.height - relative_widget.get_allocation().height
if corrected_y < 0:
corrected_y = 0
return [corrected_x, corrected_y]
if __name__ == "__main__":
CalendarExample()
gtk.main()