在菜单中显示gtk.Calendar? [英] Showing a gtk.Calendar in a menu?

查看:137
本文介绍了在菜单中显示gtk.Calendar?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



I想要用选择日期的菜单项来构建上下文菜单。 (用例是在treeview中选择一堆项目,然后为所有项目设置一个新的截止日期。)

由于menuitem是一个Gtk.Bin,我可以指定任何小部件来代替标签。不过,我似乎无法与小部件进行交互。如果我点击菜单上的任何位置,菜单项会获得点击。所以,我无法选择特定的日期,也不能浏览数月或数年。我怎样才能使日历获得鼠标活动?



此外,日历外部还有其他外部填充,当它悬停时,它会变成橙色。

 #!/ usr / bin / env python $ b如何删除填充和/或不做橙色突出显示? 
$ b导入gobject
导入pygtk
pygtk.require('2.0')
导入gtk
导入时间


class ContextMenu(gtk.Menu):
def __init __(self):
gtk.Menu .__ init __(self)
$ b def add_calendar_submenu_item(self,text,callback,uuids,data =)
calendar = gtk.Calendar()
calendar.show()
calendar_item = gtk.MenuItem()
calendar_item.add(日历)
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):
打印激活


如果__name__ ==__main__:
class CalendarExample:
def __init __(self):
window = gtk.Window (gtk.WINDOW_TOPLEVEL)
window.set_title(日历示例)
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 (菜单)

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,菜单)
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):
打印Item%s pressed%(text)

def on_date(self,widget,uuids,text):
print%s激活的日历%(text)

CalendarExample()
gtk.main()



<更新]



我的目标与Ubuntu的指标菜单日期/时间日历类似。



解决方案

如已经说过的在评论中 ilius 中,菜单不是为了保存任意小部件而设计的。这也已在这个SO贴子中讨论过。您将不得不使用弹出式窗口选项。

您尝试模拟的Ubuntu中的时钟小程序使用弹出式窗口。您可以使用 xwininfo 来验证。如果你已经显示日历然后选择它(对于 xwininfo 实用程序),你可以看到它是一个单独的窗口,不同于面板。

此外,可以通过查看来源进行确认。显示的时钟小程序是切换按钮 切换用日历显示/隐藏弹出窗口(更精确的说它是一个自定义小部件 CalendarWindow ,它扩展了 GtkWindow 添加 GtkCalendar 适当时创建)。基于你的代码的原理实现如下(请原谅我有限的Python知识):

 #!/ usr / bin / env python 

导入gobject
导入pygtk
pygtk.require('2.0')
导入gtk
导入时间

class CalendarExample:
def __init __(self):
window = gtk.Window(gtk.WINDOW_TOPLEVEL)
window.set_title(Calendar Example)
窗口。 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)

#可以用WINDOW_POPUP创建下面窗口,但试图模拟与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(切换,self.on_toggle,cal_window)

#跟踪窗口移动日历窗口的移动以及
window.connect(configure-event,self.on_window_config,toggle_button,cal_window)
window.show_all()

日历窗口坐标不带屏幕外校正:
#窗口原点(x,y)
#|
#V
#---------------------------------
#|主窗口|
#| |
#| |
#|切换按钮的(x,y)|
#|(相对于父窗口)|
#| | |
#| V |
#| ......................... |
#日历| |切换按钮| |
#窗口的| | | |
#(x,y) - +> ......................... |
#|(日历窗口将在这里)|
#| |
#| |
#---------------------------------
#日历窗口的屏幕坐标:
#x =窗口原点x +切换按钮的相对位置x
#y =窗口原点y +切换按钮的相对位置y +切换按钮的高度

#toggle回调显示&隐藏日历窗口。
def on_toggle(self,toggle_button,cal_window):
如果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(隐藏日历)
else:
cal_window.hide_all()
toggle_button.set_label(显示日历)

#configure-event回调主窗口,尝试移动日历窗口随着主窗口。
def on_window_config(self,widget,event,toggle_button,cal_window):
#如果是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)

#该函数试图更正日历窗口位置,以避免当
#主窗口不在屏幕上。
#已知错误:如果在日历窗口
#已经实现之前主窗口部分离屏,则get_allocation()将返回1x1的正数,在这种情况下,
#计算将失败并且放大;更正将不会被应用
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
如果corrected_x < 0:
corrected_x = 0
if delta_y< 0:
correction_y = y - rect.height - relative_widget.get_allocation()。height
如果corrected_y < 0:
correction_y = 0
return [corrected_x,corrected_y]

if __name__ ==__main__:
CalendarExample()
gtk.main )

希望这有助于您!


I want to construct a context menu with a menu item for selecting a date. (The use case is selecting a bunch of items in a treeview and then setting a new due date for all the items.)

Since a menuitem is a Gtk.Bin, I can specify any widget in place of a label. However, I can't seem to interact with the widget. If I click anywhere on the menu, the menuitem gets the click. So, I can't select a particular date, nor navigate months or years. How can I make the calendar get the mouse activity?

Also, there is extraneous padding around the outside of the calendar, and when hovered over it turns orange. How can I remove the padding and/or not do the orange highlight?

#!/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()

[Update]

What I'm going for is something akin to Ubuntu's indicator menu date/time calendar.

解决方案

As already mentioned by ilius in the comments, menu is not designed to hold arbitrary widget. It has also been discussed in this SO post. You will have to go with the pop-up window option.
The clock applet in Ubuntu which you are trying to emulate uses pop-up window. You can verify this using xwininfo. If you have the calendar displayed then select it (for xwininfo utility) you can see that it is a separate window and not the same as the panel.
Further, this can be confirmed by looking at the source. The clock applet which is shown is a toggle button which on toggle shows/hides the pop-up window with calendar (more precise it is a custom widget CalendarWindow which extends GtkWindow and adds GtkCalendar appropriately when created). A crude implementation of the same idea based on your code is as follows (Please pardon my limited python knowledge):

#!/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()

Hope this helps!

这篇关于在菜单中显示gtk.Calendar?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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