2012-06-21 27 views
8

calendar-menu-screenshotHiển thị gtk.Calendar trong menu?

Tôi muốn tạo một menu ngữ cảnh với mục menu để chọn ngày. (Trường hợp sử dụng đang chọn một loạt các mục trong một lần xem trang và sau đó đặt ngày hết hạn mới cho tất cả các mục.)

Vì một menuitem là Gtk.Bin, tôi có thể chỉ định bất kỳ tiện ích nào thay cho nhãn. Tuy nhiên, tôi không thể hiển thị tương tác với tiện ích. Nếu tôi nhấp vào bất kỳ nơi nào trên menu, menuitem sẽ nhận được nhấp chuột. Vì vậy, tôi không thể chọn một ngày cụ thể, cũng không thể điều hướng tháng hoặc năm. Làm cách nào để lịch có được hoạt động của chuột?

Ngoài ra, có đệm không liên quan xung quanh bên ngoài lịch và khi được di chuột qua nó sẽ chuyển thành màu cam. Làm thế nào tôi có thể loại bỏ các padding và/hoặc không làm nổi bật màu da cam?

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

[Cập nhật]

gì tôi sẽ là một cái gì đó giống như ngày đơn chỉ số của Ubuntu/thời gian lịch.

Ubuntu Calendar

+0

Thật xấu xí, vì không có mục menu nào khác, tại sao bạn chỉ cần đặt Lịch bên trong cửa sổ bật lên? – saeedgnu

+0

Bạn cũng có thể đặt nhiều nút hoặc thậm chí một thanh công cụ trong cửa sổ bật lên đó (nếu bạn muốn có nhiều hành động hơn trong cửa sổ bật lên) – saeedgnu

+0

Tôi đã thử một cách tiếp cận cửa sổ bật lên trước tiên, nhưng nhận được menu bật lên được định vị chính xác. , đặc biệt là xem xét kích thước của trình đơn có thể khác nhau tùy thuộc vào tùy chọn ngôn ngữ và phông chữ của người dùng, v.v. Tôi giữ nó như là một lựa chọn dự phòng nếu không thể thực hiện ở trên để làm việc. – bryce

Trả lời

6

Như đã đề cập bởi ilius trong các ý kiến, thực đơn không được thiết kế để giữ phụ tùng tùy ý. Nó cũng đã được thảo luận trong this SO post. Bạn sẽ phải đi với tùy chọn cửa sổ bật lên.
Ứng dụng đồng hồ trong Ubuntu mà bạn đang cố gắng mô phỏng sử dụng cửa sổ bật lên. Bạn có thể xác minh điều này bằng cách sử dụng xwininfo. Nếu bạn đã hiển thị lịch rồi chọn nó (đối với tiện ích xwininfo), bạn có thể thấy rằng đó là một cửa sổ riêng biệt và không giống như cửa sổ.
Hơn nữa, điều này có thể được xác nhận bằng cách xem source. Ứng dụng đồng hồ được hiển thị là toggle button có trên toggle hiển thị/ẩn cửa sổ bật lên có lịch (chính xác hơn là tiện ích tùy chỉnh CalendarWindow mở rộng GtkWindowadds GtkCalendar một cách thích hợp khi được tạo). Việc triển khai thô của cùng một ý tưởng dựa trên mã của bạn như sau (Vui lòng tha thứ cho kiến ​​thức trăn giới hạn của tôi):

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

Hy vọng điều này sẽ hữu ích!

+0

Điều này giúp, với c quá ... –