Отображение gtk.Calendar в меню?

calendar-menu-screenshot

Я хочу построить контекстное меню с пунктом меню для выбора даты. (Вариант использования: выбор набора элементов в виде дерева и установка новой даты выполнения для всех элементов.)

Поскольку пункт меню является Gtk.Bin, я могу указать любой виджет вместо метки. Тем не менее, я не могуinteract с виджетом. Если я щелкаю в любом месте меню, пункт меню получает щелчок. Таким образом, я не могу выбрать конкретную дату, ни перемещаться по месяцам или годам. Как я могу заставить календарь получать мышиную активность?

Кроме того, вокруг календаря есть посторонние отступы, а при наведении на них он становится оранжевым. Как я могу удалить отступы и / или не сделать оранжевую подсветку?

#!/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 Calendar

 bryce23 июн. 2012 г., 20:42
В Ubuntu на стандартном дисплее даты / времени появляется меню с интерактивным меню. Я думаю, что это выглядит хорошо, но эстетика и уместность, конечно, кажется,possibleи поэтому я хотел бы знать, как это сделать.
 saeedgnu22 июн. 2012 г., 20:29
Вы также можете поместить много кнопок или даже панель инструментов в это всплывающее окно (если вы хотите иметь больше действий во всплывающем окне)
 saeedgnu22 июн. 2012 г., 20:49
Меню не должно содержать большие виджеты, особенно когда они взаимодействуют (и не толькоactivateing Пункты меню). Даже если вам удастся заставить его работать, это не стандартно и приятно.
 saeedgnu22 июн. 2012 г., 20:27
Это уродливо, поскольку больше нет пунктов меню, почему вы просто помещаете Календарь во всплывающее окно?
 bryce22 июн. 2012 г., 20:45
Сначала я попытался использовать подход всплывающего окна, но правильное расположение всплывающего меню выглядело бы слишком сложным, особенно учитывая, что размеры меню могут различаться в зависимости от языка, предпочтений пользователя и шрифта и так далее. Я оставляю это как запасной вариант, если вышеописанное не может быть выполнено.

Ответы на вопрос(1)

Решение Вопроса

Ilius в комментариях меню не предназначено для хранения произвольных виджетов. Это также обсуждалось вэтот ТАК пост, Вам придется пойти с опцией всплывающего окна.
Апплет часов в Ubuntu, который вы пытаетесь эмулировать, использует всплывающее окно. Вы можете проверить это используяxwininfo, Если у вас есть календарь, выберите его (дляxwininfo утилита) вы можете видеть, что это отдельное окно, а не то же самое, что и панель.
Кроме того, это можно подтвердить, посмотрев наисточник, Апплет часов, который показанКнопка-переключатель который натумблер показывает / скрывает всплывающее окно с календарем (точнее, это пользовательский виджетCalendarWindow который расширяетсяGtkWindow а такжедобавляетGtkCalendar соответственно при создании). Грубая реализация той же идеи на основе вашего кода выглядит следующим образом (извините за мои ограниченные знания Python):

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

Надеюсь это поможет!

 13 апр. 2015 г., 02:44
Это помогает, с т тоже ...

Ваш ответ на вопрос