窗口模拟器
Tofloor
poster avatar
vala2012
deepin
2013-03-13 12:13
Author
以前看见软件班的有 智能小车玩, 让我羡慕的不得了, 然后室友回来吹, 哎, 我们网络班的没有得玩, 好吧, 我模拟, 连他们的编译环境也模拟了. 用的 win-tc 作为模拟他们的编译环境, 写了一些.h的头文件模拟他们的智能小车函数, 然后生成可执行脚本, 用 c++ builder 写的界面, 这个界面读取脚本解释, 让小车动起来,其实就是动画, 然后状态栏,显示 智能小车的 闪灯效果, 哈哈哈, 我也能玩啦. :  :  :  :
现在这个模拟环境:
将这个 pygtk window想象成一个桌面环境或者一个浏览器吧 又或者想象成一个裸机, 只提供了一些实模式的绘制函数.. ...
里面的一个个矩形就是窗体.
中间的小红点模拟的是窗体内的button.
你点击运动一下.

模拟器的好处就是可以模拟一切,  解释脚本, 生成你想要的效果. nes模拟器也是要分析nes文件,然后根据模拟环境: CPU, , 等等来运行nes. 好处不多说, 看bochs等等就知道,模拟技术的强大, 本人不懂,就是随便玩玩.
可以模拟窗口的栈效果,还有向绘制端发送消息,告诉它 绘制那个窗口, 窗口要多大, 在什么位置等等一些东西.
昨天晚上太无聊,花了十多分钟写一个简单的demo测试一下. 详情可以看安卓的窗口管理器分析.
复制代码, 运行看看.
  1. #!coding:utf-8
  2. import gtk
  3. class LdmpGdiSer(gtk.Button):
  4.     def __init__(self):
  5.         gtk.Button.__init__(self)
  6.         self.__init_values()
  7.         self.__init_events()
  8.         self.__init_settings()
  9.     def __init_values(self):
  10.         self.title_h = 20
  11.         self.wms = Wms()
  12.         self.wms.windows_list.append(create_window(0, 0, 100, 100, "深度影音"))
  13.         self.wms.windows_list.append(create_window(120, 100, 100, 100, "明天会更好"))
  14.         self.wms.windows_list.append(create_window(320, 200, 100, 100, "窗口测试"))
  15.         self.wms.windows_list.append(create_window(230, 130, 100, 100, "浏览器"))
  16.     def __init_events(self):
  17.         self.add_events(gtk.gdk.ALL_EVENTS_MASK)
  18.         self.connect("expose-event", self.__ldmp_gdi_expose_event)
  19.         self.connect("motion-notify-event", self.__ldmp_gdi_motion_notify_event)
  20.         self.connect("button-press-event", self.__ldmp_gdi_button_press_event)
  21.         self.connect("button-release-event", self.__ldmp_gdi_button_release_event)
  22.     def __init_settings(self):
  23.         self.set_label("窗口模拟器")
  24.     def __ldmp_gdi_expose_event(self, widget, event):
  25.         cr = widget.window.cairo_create()
  26.         rect = widget.allocation
  27.         #
  28.         # draw window.
  29.         for win in self.wms.windows_list:
  30.             cr.set_source_rgb(0, 0, 1)
  31.             cr.rectangle(win.x_root, win.y_root, win.width, win.title_height)
  32.             cr.fill()
  33.             cr.set_source_rgb(0, 0, 0)
  34.             cr.rectangle(win.x_root, win.y_root, win.width, win.height)
  35.             cr.stroke()
  36.             cr.set_source_rgb(1, 0, 0)
  37.             cr.rectangle(win.x_root + 10, win.y_root + 30, 50, 20)
  38.             cr.fill()
  39.         #
  40.         return True
  41.     def __ldmp_gdi_motion_notify_event(self, widget, event):
  42.         self.__ldmp_gdi_wms_motion(widget, event)
  43.     def __ldmp_gdi_button_press_event(self, widget, event):
  44.         self.__ldmp_gdi_wms_press(widget, event)
  45.     def __ldmp_gdi_button_release_event(self, widget, event):
  46.         self.__ldmp_gdi_wms_release(widget, event)
  47.     def __ldmp_gdi_wms_motion(self, widget, event):
  48.         display_x_root = event.x
  49.         display_y_root = event.y
  50.         for win in self.wms.windows_list:
  51.             if win.press_check:
  52.                 win.x_root +=  display_x_root - win.press_save_x_root
  53.                 win.y_root += display_y_root - win.press_save_y_root
  54.                 win.press_save_x_root = display_x_root
  55.                 win.press_save_y_root = display_y_root
  56.                 self.queue_draw()
  57.     def __ldmp_gdi_wms_press(self, widget, event):
  58.         display_x_root = event.x
  59.         display_y_root = event.y
  60.         for win in self.wms.windows_list:
  61.             if (win.x_root <= display_x_root <= win.x_root + win.width and
  62.                (win.y_root <= display_y_root <= win.y_root + win.title_height)):
  63.                 print "你现在点击的是:", win.title, "的窗口标题栏"
  64.                 win.press_check = True
  65.                 # 保存按下的 x, y 坐标.
  66.                 win.press_save_x_root = display_x_root
  67.                 win.press_save_y_root = display_y_root
  68.             elif (win.x_root <= display_x_root <= win.x_root + win.width and
  69.                (win.y_root <= display_y_root <= win.y_root + win.height)):
  70.                 print "你现在点击的是:", win.title, "的窗口内部"
  71.     def __ldmp_gdi_wms_release(self, widget, event):
  72.         for win in self.wms.windows_list:
  73.             win.press_check = False
  74.             
  75.         
  76. def create_window(x_root, y_root, w, h, title=""):
  77.     gdi_win = GdiWindow()
  78.     gdi_win.title = title
  79.     gdi_win.x_root = x_root
  80.     gdi_win.y_root = y_root
  81.     gdi_win.width  = w
  82.     gdi_win.height = h
  83.     gdi_win.press_check = False
  84.     gdi_win.press_save_x_root = 0
  85.     gdi_win.press_save_y_root = 0
  86.     gdi_win.type = None # 普通窗口, dock, menu.
  87.     return gdi_win
  88.    
  89. class GdiWindow(object):
  90.     def __init__(self):
  91.         self.title  = ""
  92.         self.title_height = 20
  93.         self.x_root = 0
  94.         self.y_root = 0
  95.         self.width  = 0
  96.         self.height = 0
  97. class Wms(object):
  98.     def __init__(self):
  99.         self.windows_list = []
  100. if __name__ == "__main__":
  101.     ldmp_gdi_ser = LdmpGdiSer()
  102.     win = gtk.Window(gtk.WINDOW_TOPLEVEL)
  103.     win.add(ldmp_gdi_ser)
  104.     win.set_size_request(500, 500)
  105.     win.show_all()
  106.     gtk.main()
Copy the Code
选区_015.png
Reply Favorite View the author
All Replies
lovesnow
deepin
2013-03-14 06:16
#1
  上面程序没有实现层叠的效果 , 可拉伸, 每个小窗口里可以放任意gtk容器或控件,

看看这个
深度截图20130313222002.png
  1. import gtk, gobject
  2. import sys
  3. _print = lambda *args: None
  4. _print = lambda *args: sys.stdout.write(' '.join([str(i) for i in args]) + '\n')
  5. try: import i18n
  6. except: from gettext import gettext as _
  7. class GtkMdiTabbar(gtk.Notebook):
  8.     homogeneous_tabs = False
  9.     def __init__(self):
  10.         self.__gobject_init__()
  11.         self.set_scrollable(True)
  12.         self.popup_enable()
  13.         self.set_homogeneous_tabs(self.homogeneous_tabs)
  14.         self.unset_flags(gtk.CAN_FOCUS)
  15.         ##
  16.         self._is_action_jn = False
  17.         ##
  18.         #self.connect("grab-focus", self.on_focus)
  19.         #self.connect("focus-tab", self.on_focus_tab)
  20.         self.connect("create-window", self.on_create_window)
  21.         self.connect("page-reordered", self.on_page_reordered)
  22.         self.connect("change-current-page", self.on_change_current_page)
  23.         self.connect("select-page", self.on_select_page)
  24.         self.connect("switch-page", self.on_switch_page)
  25.         pass
  26.     def add(self, child):
  27.         p = gtk.EventBox()
  28.         child.tab = p
  29.         p.p = child
  30.         label = gtk.Label(child.title)
  31.         self.append_page(p, label)
  32.         self.set_tab_detachable(p, True)
  33.         self.show_all()
  34.         pass
  35.     def action_tab(self, child):
  36.         n = self.page_num(child.tab)
  37.         self._is_action_jn = True
  38.         self.set_current_page(n)
  39.         pass
  40.     def get_child_by_n(self, n):
  41.         p = self.get_nth_page(n)
  42.         if p:
  43.             return p.p
  44.         return
  45.     def get_n_by_child(self, child):
  46.         return  self.page_num(child.tab)
  47.     def on_focus_tab(self, widget, *args):
  48.         _print('on_focus_tab:', widget, args)
  49.         pass
  50.     def remove(self, child):
  51.         p = self.page_num(child.tab)
  52.         if p:
  53.             self.remove_page(p)
  54.             pass
  55.         pass
  56.     def on_focus(self, *args):
  57.         _print('on_focus:', args)
  58.         pass
  59.     def on_create_window(self, page, x, y, *args):
  60.         # when a detachable tab is dropped on the root window.
  61.         _print('on_create_window:', page, x, y, args)
  62.         pass
  63.     def on_page_reordered(self, widget, child, page_num, *args):
  64.         _print('on_page_reordered:', widget, child, page_num, args)
  65.         pass
  66.     def on_change_current_page(self, widget, offset, *args):
  67.         _print('on_change_current_page:', widget, offset, args)
  68.         pass
  69.     def on_switch_page(self, widget, page, page_num, *args):
  70.         if self._is_action_jn:
  71.             self._is_action_jn = False
  72.             return
  73.         _print('on_switch_page:', widget, page, page_num, args)
  74.         self.get_nth_page(page_num).p.action()
  75.         pass
  76.     def on_select_page(self, widget, move_focus, *args):
  77.         _print('on_select_page:', widget, move_focus, args)
  78.         pass
  79. class GtkMdiWindow(gtk.EventBox):
  80.     __gtype_name__ = 'GtkMdiWindow'
  81.     __gsignals__ = {
  82.         'switch': (gobject.SIGNAL_RUN_LAST, None, ()),
  83.     }   
  84.     bg_title = gtk.gdk.Color('#377F0C')
  85.     fg_title = gtk.gdk.Color('#ffffff')
  86.     defalut_max = False
  87.     def __init__(self, child=gtk.Alignment(), title="", icon=None,
  88. skiptaskbar=False):
  89.         self.__gobject_init__()
  90.         self.title = title
  91.         self.icon = icon
  92.         self._is_in_move = False
  93.         self._is_in_resize_rb = False
  94.         self._is_max = False
  95.         self._is_min = False
  96.         ##
  97.         self._old_x = 0
  98.         self._old_y = 0
  99.         self.modify_bg(gtk.STATE_NORMAL, self.bg_title)
  100.         ##
  101.         self._child = child
  102.         self.child_focus = child.child_focus
  103.         self.child_get = child.child_get
  104.         self.child_get_property = child.child_get_property
  105.         self.child_notify = child.child_notify
  106.         self.children = child.children
  107.         self.child_set = child.child_set
  108.         self.child_set_property = child.child_set_property
  109.         self.child_type = child.child_type
  110.         ##
  111.         self.unset_flags(gtk.CAN_FOCUS)
  112.         self.connect("set_focus_child", self.on_focus)
  113.         self.connect("grab_focus", self.on_focus)
  114.         ## move, resize
  115.         self.connect("event", self.on_title_event)
  116.         ##
  117.         self.vbox1 = gtk.VBox(False, 0)
  118.         ## MDI Window Border
  119.         self.vbox1.set_border_width(3)
  120.         #self.vbox1.connect("set_focus_child", self.on_focus)
  121.         #self.vbox1.connect("grab_focus", self.on_focus)
  122.         #self.vbox1.connect("expose_event", self.on_focus)
  123.         #self.vbox1.connect("focus", self.on_focus)
  124.         ## simulate MDI Window Title
  125.         self.titlebar = gtk.HBox(False, 0)
  126.         self.titlebar.unset_flags(gtk.CAN_FOCUS)
  127.         self.titlebar.show()
  128.         self.icon_label = gtk.Label("")
  129.         self.icon_label.modify_fg(gtk.STATE_NORMAL, self.fg_title)
  130.         self.icon_label.set_padding(5, 0)
  131.         self.icon_label.set_markup("v")
  132.         self.icon_label.show()
  133.         ##
  134.         eventbox = gtk.EventBox()
  135.         eventbox.modify_bg(gtk.STATE_NORMAL, self.bg_title)
  136.         eventbox.connect("button_release_event", self.on_icon)
  137.         eventbox.add(self.icon_label)
  138.         self.titlebar.pack_start(eventbox, False, False, 0)
  139.         self.title_label = gtk.Label(title)
  140.         self.title_label.set_padding(10, 0)
  141.         self.title_label.modify_fg(gtk.STATE_NORMAL, self.fg_title)
  142.         self.title_label.show()
  143.         self.titlebar.pack_start(self.title_label)
  144.         ## min, max, close button
  145.         self.min_label = gtk.Label("")
  146.         self.min_label.modify_fg(gtk.STATE_NORMAL, self.fg_title)
  147.         self.min_label.set_padding(5, 0)
  148.         self.min_label.set_tooltip_markup(_("Iconify Window"))
  149.         self.min_label.set_markup("_")
  150.         self.min_label.show()
  151.         ##
  152.         eventbox = gtk.EventBox()
  153.         eventbox.modify_bg(gtk.STATE_NORMAL, self.bg_title)
  154.         eventbox.connect("button_press_event", self.on_min)
  155.         eventbox.add(self.min_label)
  156.         self.titlebar.pack_start(eventbox, False, False, 0)
  157.         self.max_label = gtk.Label("")
  158.         self.max_label.modify_fg(gtk.STATE_NORMAL, self.fg_title)
  159.         self.max_label.set_padding(5, 0)
  160.         self.max_label.set_tooltip_markup(_("Maximize Window"))
  161.         self.max_label.set_markup("+")
  162.         self.max_label.show()
  163.         ##
  164.         eventbox = gtk.EventBox()
  165.         eventbox.modify_bg(gtk.STATE_NORMAL, self.bg_title)
  166.         eventbox.connect("button_release_event", self.on_max)
  167.         eventbox.add(self.max_label)
  168.         self.titlebar.pack_start(eventbox, False, False, 0)
  169.         self.close_label = gtk.Label("")
  170.         self.close_label.modify_fg(gtk.STATE_NORMAL, self.fg_title)
  171.         self.close_label.modify_bg(gtk.STATE_NORMAL, self.bg_title)
  172.         self.close_label.set_padding(5, 0)
  173.         self.close_label.set_tooltip_markup(_("Close Window"))
  174.         self.close_label.set_markup("x")
  175.         self.close_label.show()
  176.         ##
  177.         eventbox = gtk.EventBox()
  178.         eventbox.modify_bg(gtk.STATE_NORMAL, self.bg_title)
  179.         eventbox.connect("button_release_event", self.on_close)
  180.         eventbox.add(self.close_label)
  181.         self.titlebar.pack_start(eventbox, False, False, 0)
  182.         self.vbox1.pack_start(self.titlebar, False, False, 0)
  183.         ## MDI Window Area
  184.         #self.mdi_alignment = gtk.Alignment(0.5, 0.5, 0, 0)
  185.         #self.mdi_alignment.show()
  186.         #self.vbox1.pack_start(self.mdi_alignment)
  187.         self._child_box = gtk.EventBox()
  188.         self._child_box.add(self._child)
  189.         self.vbox1.pack_start(self._child_box, True, True, 0)
  190.         ##
  191.         self.add(self.vbox1)
  192.         self.show_all()
  193.         pass
  194.     def _raise(self, *args):
  195.         try:
  196.             window = self.get_window() or self.get_window(1)
  197.             if window:
  198.                 gtk.gdk.Window.raise_(window)
  199.                 self.emit("switch", )
  200.                 pass
  201.             pass
  202.         except:
  203.             pass
  204.         pass
  205.     def lower(self, *args):
  206.         try:
  207.             window = self.get_window() or self.get_window(1)
  208.             if window:
  209.                 gtk.gdk.Window.lower(window)
  210.                 pass
  211.             pass
  212.         except:
  213.             pass
  214.         pass
  215.     def action(self):
  216.         _print('action:', self)
  217.         if self._is_min:
  218.             self.unmax()
  219.             pass
  220.         self._raise()
  221.         self._child.grab_focus()
  222.         pass
  223.     def on_focus(self, widget, *args):
  224.         _print('on_focus:', widget, args)
  225.         self._raise()
  226.         if widget and 'mditabbar' in self.parent.parent.__dict__:
  227.             mditabbar = self.parent.parent.mditabbar
  228.             mditabbar.action_tab(self)
  229.             pass
  230.         pass
  231.     def on_title_event(self, widget, event):
  232.         #_print('on_title_event', widget, event)
  233.         # for move
  234.         if event.type == gtk.gdk.BUTTON_PRESS:
  235.             if event.button == 3:
  236.                 self.on_menu(widget, event)
  237.                 return
  238.             else:
  239.                 self.on_focus(self)
  240.                 self._child.grab_focus()
  241.                 self._px, self._py = self.parent.get_pointer()
  242.                 ## MdiWindow x, y
  243.                 self._wx, self._wy = self.get_window().get_position()
  244.                 ## MdiArea width, height
  245.                 i, t, self._aw, self._ah = self.parent.get_allocation()
  246.                 ## MdiWindow width, height
  247.                 i, t, self._w, self._h = self.get_allocation()
  248.                 ##
  249.                 self._ox = self._wx - self._px
  250.                 self._oy = self._wy - self._py
  251.                 if self._w - event.x < 20 and self._h - event.y < 20:
  252.                     self._is_in_resize_rb = True
  253.                     pass
  254.                 else:
  255.                     self._is_in_move = True
  256.                     pass
  257.                 return
  258.             return
  259.         elif event.type == gtk.gdk.BUTTON_RELEASE:
  260.             self._is_in_move = False
  261.             self._is_in_resize_rb = False
  262.             return
  263.         ## move MdiWindow
  264.         elif self._is_in_move and event.type == gtk.gdk.MOTION_NOTIFY:
  265.             px, py = self.parent.get_pointer()
  266.             if px < 5: px = 5
  267.             if py < 0: py = 0
  268.             if px > self._aw: px = self._aw
  269.             if py > self._ah: py = self._ah
  270.             mx = px + self._ox
  271.             my = py + self._oy
  272.             #self.move(mx, my)
  273.             self.parent.move(self, mx, my)
  274.             return
  275.         ## resize MdiWindow
  276.         elif self._is_in_resize_rb and event.type == gtk.gdk.MOTION_NOTIFY:
  277.             x, y = event.x, event.y
  278.             px, py = self.parent.get_pointer()
  279.             if x < 30: x = 30
  280.             if y < 30: y = 30
  281.             if px > self._aw: x = self.get_allocation()[2]
  282.             if py > self._ah: y = self.get_allocation()[3]
  283.             self.set_size_request(int(x), int(y))
  284.             return
  285.         pass
  286.     def on_menu(self, widget, event):
  287.         _print('on_menu:', widget, event)
  288.         pass
  289.     def on_icon(self, widget, event):
  290.         if event.button == 1:
  291.             _print('on_icon:', widget, event)
  292.         pass
  293.     def on_min(self, widget, event):
  294.         if event.button == 1:
  295.             _print('on_min:', widget, event)
  296.             self.min()
  297.         pass
  298.     def on_unmax(self, widget, event):
  299.         if event.button != 1: return
  300.         _print('on_unmax:', widget, event)
  301.         self.unmax()
  302.     def on_max(self, widget, event):
  303.         if event.button != 1: return
  304.         self.max()
  305.         pass
  306.     def on_close(self, widget, event):
  307.         if event.button == 1:
  308.             _print('on_close:', widget, event)
  309.             self.close()
  310.             pass
  311.         pass
  312.     def move(self, x, y):
  313.         _print('move:', x, y)
  314.         self.parent.move(self, x, y)
  315.         pass
  316.     def min(self, *args):
  317.         self._is_min = True
  318.         # save MdiWindow position x, y
  319.         self._old_wx, self._old_wy = self.get_window().get_position()
  320.         # save MdiWindow width, height
  321.         i, t, self._old_w, self._old_h = self.get_allocation()
  322.         self.parent.grab_focus()
  323.         #self.lower()
  324.         self.hide()
  325.         if 'mditabbar' in self.parent.parent.__dict__:
  326.             mditabbar = self.parent.parent.mditabbar
  327.             mditabbar.next_page()
  328.             pass
  329.         pass
  330.     def max(self, *args):
  331.         i, t, self._w, self._h = self.get_allocation()
  332.         i, t, self._aw, self._ah = self.parent.get_allocation()
  333.         if self._w < self._aw or self._h < self._ah:
  334.             self._is_max = False
  335.             pass
  336.         if self._is_max: return self.unmax()
  337.         ##
  338.         self._is_max = True
  339.         self._is_min = False
  340.         # save MdiWindow position x, y
  341.         self._old_wx, self._old_wy = self.get_window().get_position()
  342.         # save MdiWindow width, height
  343.         i, t, self._old_w, self._old_h = self.get_allocation()
  344.         self.move(0, 0)
  345.         self.set_size_request(self._aw, self._ah)
  346.         pass
  347.     def unmax(self, *args):
  348.         self._is_max = False
  349.         self._is_min = False
  350.         self.set_size_request(self._old_w, self._old_h)
  351.         self.move(self._old_wx, self._old_wy)
  352.         self.show_all()
  353.         pass
  354.     def close(self, *args):
  355.         if 'mditabbar' in self.parent.parent.__dict__:
  356.             mditabbar = self.parent.parent.mditabbar
  357.             mditabbar.remove(self)
  358.             pass
  359.         self.destroy()
  360.         pass
  361. class GtkMdiArea(gtk.Layout):
  362.     __gtype_name__ = 'GtkMdiArea'
  363.     __gsignals__ = {
  364.         'switch-window': (gobject.SIGNAL_RUN_LAST, None, (gtk.Widget,)),
  365.     }
  366.     need_resize = 1L
  367.     def __init__(self):
  368.         self.__gobject_init__()
  369.         #self.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color("#003300"))
  370.         self._old_w = 0
  371.         self._old_h = 0
  372.         self.unset_flags(gtk.CAN_FOCUS)
  373.         self.connect("size-allocate", self.on_resize)
  374.         pass
  375.     def add(self, mdiwindow, x=0, y=0):
  376.         gtk.Layout.put(self, mdiwindow, x, y)
  377.         mdiwindow.connect("switch", self.on_switch)
  378.         pass
  379.     def on_resize(self, widget, rectangle):
  380.         i, t, w, h = rectangle
  381.         if self._old_w == w and self._old_h == h:
  382.             return
  383.         _print('on_resize:', widget, rectangle)
  384.         self._old_w, self._old_h = w, h
  385.         for p in self.children():
  386.             if p._is_max:
  387.                 p.set_size_request(w, h)
  388.                 pass
  389.             pass
  390.         pass
  391.     def on_switch(self, widget, *args):
  392.         _print('on_switch', self, widget, args)
  393.         self.emit("switch-window", widget)
  394.         if 'mditabbar' in self.parent.__dict__:
  395.             mditabbar = self.parent.mditabbar
  396.             mditabbar.action_tab(widget)
  397.             pass
  398.         pass
  399. class GtkMdi(gtk.Table):
  400.     def __init__(self):
  401.         self.__gobject_init__()
  402.         self.mdiarea = GtkMdiArea()
  403.         self.mditabbar = GtkMdiTabbar()
  404.         ## table.attach(widget, left_attach=0, right_attach=1, top_attach=0,
  405. #bottom_attach=1)
  406.         self.attach(self.mditabbar, 0, 1, 0, 1, gtk.FILL, gtk.FILL, 0, 0)
  407.         self.attach(self.mdiarea,    0, 1, 1, 2)
  408.         pass
  409.     def set_tab_pos(self, pos):
  410.         # pos: 0: left, 1: right, 2: top, 3: bottom
  411.         pass
  412.     def add(self, mdiwindow, x=0, y=0):
  413.         self.mdiarea.add(mdiwindow, x, y)
  414.         self.mditabbar.add(mdiwindow)
  415.         pass
  416.     def tab_top(self, *args):
  417.         pass
  418. def _demo():
  419.     _print('main')
  420.     w = gtk.Window()
  421.     w.set_title("Test MDI")
  422.     w.set_default_size(500, 500)
  423.     mdi = GtkMdi()
  424.     ##
  425.     ts = gtk.ScrolledWindow()
  426.     ts.add(gtk.TextView())
  427.     ts.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
  428.     ts.set_size_request(150, 150)
  429.     mw = GtkMdiWindow(ts, 'MDI Document 1')
  430.     mdi.add(mw, 0, 0)
  431.     ##
  432.     ts = gtk.ScrolledWindow()
  433.     ts.add(gtk.TextView())
  434.     ts.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
  435.     ts.set_size_request(150, 150)
  436.     mw = GtkMdiWindow(ts, 'MDI Document 2')
  437.     mdi.add(mw, 30, 30)
  438.     ##
  439.     ts = gtk.ScrolledWindow()
  440.     ts.add(gtk.TextView())
  441.     ts.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
  442.     ts.set_size_request(150, 150)
  443.     mw = GtkMdiWindow(ts, 'MDI Document 3')
  444.     mdi.add(mw, 60, 60)
  445.     w.add(mdi)
  446.     w.show_all()
  447.     w.connect('delete-event', gtk.main_quit)
  448.     gtk.main()
  449. if __name__=="__main__":
  450.     _demo()
Copy the Code
Reply View the author
vala2012
deepin
2013-03-14 07:21
#2
  上面程序没有实现层叠的效果 , 可拉伸, 每个小窗口里可以放任意gtk容器或控件,

看看这个
深度截图20130313222002.png
  1. import gtk, gobject
  2. import sys
  3. _print = lambda *args: None
  4. _print = lambda *args: sys.stdout.write(' '.join([str(i) for i in args]) + '\n')
  5. try: import i18n
  6. except: from gettext import gettext as _
  7. class GtkMdiTabbar(gtk.Notebook):
  8.     homogeneous_tabs = False
  9.     def __init__(self):
  10.         self.__gobject_init__()
  11.         self.set_scrollable(True)
  12.         self.popup_enable()
  13.         self.set_homogeneous_tabs(self.homogeneous_tabs)
  14.         self.unset_flags(gtk.CAN_FOCUS)
  15.         ##
  16.         self._is_action_jn = False
  17.         ##
  18.         #self.connect("grab-focus", self.on_focus)
  19.         #self.connect("focus-tab", self.on_focus_tab)
  20.         self.connect("create-window", self.on_create_window)
  21.         self.connect("page-reordered", self.on_page_reordered)
  22.         self.connect("change-current-page", self.on_change_current_page)
  23.         self.connect("select-page", self.on_select_page)
  24.         self.connect("switch-page", self.on_switch_page)
  25.         pass
  26.     def add(self, child):
  27.         p = gtk.EventBox()
  28.         child.tab = p
  29.         p.p = child
  30.         label = gtk.Label(child.title)
  31.         self.append_page(p, label)
  32.         self.set_tab_detachable(p, True)
  33.         self.show_all()
  34.         pass
  35.     def action_tab(self, child):
  36.         n = self.page_num(child.tab)
  37.         self._is_action_jn = True
  38.         self.set_current_page(n)
  39.         pass
  40.     def get_child_by_n(self, n):
  41.         p = self.get_nth_page(n)
  42.         if p:
  43.             return p.p
  44.         return
  45.     def get_n_by_child(self, child):
  46.         return  self.page_num(child.tab)
  47.     def on_focus_tab(self, widget, *args):
  48.         _print('on_focus_tab:', widget, args)
  49.         pass
  50.     def remove(self, child):
  51.         p = self.page_num(child.tab)
  52.         if p:
  53.             self.remove_page(p)
  54.             pass
  55.         pass
  56.     def on_focus(self, *args):
  57.         _print('on_focus:', args)
  58.         pass
  59.     def on_create_window(self, page, x, y, *args):
  60.         # when a detachable tab is dropped on the root window.
  61.         _print('on_create_window:', page, x, y, args)
  62.         pass
  63.     def on_page_reordered(self, widget, child, page_num, *args):
  64.         _print('on_page_reordered:', widget, child, page_num, args)
  65.         pass
  66.     def on_change_current_page(self, widget, offset, *args):
  67.         _print('on_change_current_page:', widget, offset, args)
  68.         pass
  69.     def on_switch_page(self, widget, page, page_num, *args):
  70.         if self._is_action_jn:
  71.             self._is_action_jn = False
  72.             return
  73.         _print('on_switch_page:', widget, page, page_num, args)
  74.         self.get_nth_page(page_num).p.action()
  75.         pass
  76.     def on_select_page(self, widget, move_focus, *args):
  77.         _print('on_select_page:', widget, move_focus, args)
  78.         pass
  79. class GtkMdiWindow(gtk.EventBox):
  80.     __gtype_name__ = 'GtkMdiWindow'
  81.     __gsignals__ = {
  82.         'switch': (gobject.SIGNAL_RUN_LAST, None, ()),
  83.     }   
  84.     bg_title = gtk.gdk.Color('#377F0C')
  85.     fg_title = gtk.gdk.Color('#ffffff')
  86.     defalut_max = False
  87.     def __init__(self, child=gtk.Alignment(), title="", icon=None,
  88. skiptaskbar=False):
  89.         self.__gobject_init__()
  90.         self.title = title
  91.         self.icon = icon
  92.         self._is_in_move = False
  93.         self._is_in_resize_rb = False
  94.         self._is_max = False
  95.         self._is_min = False
  96.         ##
  97.         self._old_x = 0
  98.         self._old_y = 0
  99.         self.modify_bg(gtk.STATE_NORMAL, self.bg_title)
  100.         ##
  101.         self._child = child
  102.         self.child_focus = child.child_focus
  103.         self.child_get = child.child_get
  104.         self.child_get_property = child.child_get_property
  105.         self.child_notify = child.child_notify
  106.         self.children = child.children
  107.         self.child_set = child.child_set
  108.         self.child_set_property = child.child_set_property
  109.         self.child_type = child.child_type
  110.         ##
  111.         self.unset_flags(gtk.CAN_FOCUS)
  112.         self.connect("set_focus_child", self.on_focus)
  113.         self.connect("grab_focus", self.on_focus)
  114.         ## move, resize
  115.         self.connect("event", self.on_title_event)
  116.         ##
  117.         self.vbox1 = gtk.VBox(False, 0)
  118.         ## MDI Window Border
  119.         self.vbox1.set_border_width(3)
  120.         #self.vbox1.connect("set_focus_child", self.on_focus)
  121.         #self.vbox1.connect("grab_focus", self.on_focus)
  122.         #self.vbox1.connect("expose_event", self.on_focus)
  123.         #self.vbox1.connect("focus", self.on_focus)
  124.         ## simulate MDI Window Title
  125.         self.titlebar = gtk.HBox(False, 0)
  126.         self.titlebar.unset_flags(gtk.CAN_FOCUS)
  127.         self.titlebar.show()
  128.         self.icon_label = gtk.Label("")
  129.         self.icon_label.modify_fg(gtk.STATE_NORMAL, self.fg_title)
  130.         self.icon_label.set_padding(5, 0)
  131.         self.icon_label.set_markup("v")
  132.         self.icon_label.show()
  133.         ##
  134.         eventbox = gtk.EventBox()
  135.         eventbox.modify_bg(gtk.STATE_NORMAL, self.bg_title)
  136.         eventbox.connect("button_release_event", self.on_icon)
  137.         eventbox.add(self.icon_label)
  138.         self.titlebar.pack_start(eventbox, False, False, 0)
  139.         self.title_label = gtk.Label(title)
  140.         self.title_label.set_padding(10, 0)
  141.         self.title_label.modify_fg(gtk.STATE_NORMAL, self.fg_title)
  142.         self.title_label.show()
  143.         self.titlebar.pack_start(self.title_label)
  144.         ## min, max, close button
  145.         self.min_label = gtk.Label("")
  146.         self.min_label.modify_fg(gtk.STATE_NORMAL, self.fg_title)
  147.         self.min_label.set_padding(5, 0)
  148.         self.min_label.set_tooltip_markup(_("Iconify Window"))
  149.         self.min_label.set_markup("_")
  150.         self.min_label.show()
  151.         ##
  152.         eventbox = gtk.EventBox()
  153.         eventbox.modify_bg(gtk.STATE_NORMAL, self.bg_title)
  154.         eventbox.connect("button_press_event", self.on_min)
  155.         eventbox.add(self.min_label)
  156.         self.titlebar.pack_start(eventbox, False, False, 0)
  157.         self.max_label = gtk.Label("")
  158.         self.max_label.modify_fg(gtk.STATE_NORMAL, self.fg_title)
  159.         self.max_label.set_padding(5, 0)
  160.         self.max_label.set_tooltip_markup(_("Maximize Window"))
  161.         self.max_label.set_markup("+")
  162.         self.max_label.show()
  163.         ##
  164.         eventbox = gtk.EventBox()
  165.         eventbox.modify_bg(gtk.STATE_NORMAL, self.bg_title)
  166.         eventbox.connect("button_release_event", self.on_max)
  167.         eventbox.add(self.max_label)
  168.         self.titlebar.pack_start(eventbox, False, False, 0)
  169.         self.close_label = gtk.Label("")
  170.         self.close_label.modify_fg(gtk.STATE_NORMAL, self.fg_title)
  171.         self.close_label.modify_bg(gtk.STATE_NORMAL, self.bg_title)
  172.         self.close_label.set_padding(5, 0)
  173.         self.close_label.set_tooltip_markup(_("Close Window"))
  174.         self.close_label.set_markup("x")
  175.         self.close_label.show()
  176.         ##
  177.         eventbox = gtk.EventBox()
  178.         eventbox.modify_bg(gtk.STATE_NORMAL, self.bg_title)
  179.         eventbox.connect("button_release_event", self.on_close)
  180.         eventbox.add(self.close_label)
  181.         self.titlebar.pack_start(eventbox, False, False, 0)
  182.         self.vbox1.pack_start(self.titlebar, False, False, 0)
  183.         ## MDI Window Area
  184.         #self.mdi_alignment = gtk.Alignment(0.5, 0.5, 0, 0)
  185.         #self.mdi_alignment.show()
  186.         #self.vbox1.pack_start(self.mdi_alignment)
  187.         self._child_box = gtk.EventBox()
  188.         self._child_box.add(self._child)
  189.         self.vbox1.pack_start(self._child_box, True, True, 0)
  190.         ##
  191.         self.add(self.vbox1)
  192.         self.show_all()
  193.         pass
  194.     def _raise(self, *args):
  195.         try:
  196.             window = self.get_window() or self.get_window(1)
  197.             if window:
  198.                 gtk.gdk.Window.raise_(window)
  199.                 self.emit("switch", )
  200.                 pass
  201.             pass
  202.         except:
  203.             pass
  204.         pass
  205.     def lower(self, *args):
  206.         try:
  207.             window = self.get_window() or self.get_window(1)
  208.             if window:
  209.                 gtk.gdk.Window.lower(window)
  210.                 pass
  211.             pass
  212.         except:
  213.             pass
  214.         pass
  215.     def action(self):
  216.         _print('action:', self)
  217.         if self._is_min:
  218.             self.unmax()
  219.             pass
  220.         self._raise()
  221.         self._child.grab_focus()
  222.         pass
  223.     def on_focus(self, widget, *args):
  224.         _print('on_focus:', widget, args)
  225.         self._raise()
  226.         if widget and 'mditabbar' in self.parent.parent.__dict__:
  227.             mditabbar = self.parent.parent.mditabbar
  228.             mditabbar.action_tab(self)
  229.             pass
  230.         pass
  231.     def on_title_event(self, widget, event):
  232.         #_print('on_title_event', widget, event)
  233.         # for move
  234.         if event.type == gtk.gdk.BUTTON_PRESS:
  235.             if event.button == 3:
  236.                 self.on_menu(widget, event)
  237.                 return
  238.             else:
  239.                 self.on_focus(self)
  240.                 self._child.grab_focus()
  241.                 self._px, self._py = self.parent.get_pointer()
  242.                 ## MdiWindow x, y
  243.                 self._wx, self._wy = self.get_window().get_position()
  244.                 ## MdiArea width, height
  245.                 i, t, self._aw, self._ah = self.parent.get_allocation()
  246.                 ## MdiWindow width, height
  247.                 i, t, self._w, self._h = self.get_allocation()
  248.                 ##
  249.                 self._ox = self._wx - self._px
  250.                 self._oy = self._wy - self._py
  251.                 if self._w - event.x < 20 and self._h - event.y < 20:
  252.                     self._is_in_resize_rb = True
  253.                     pass
  254.                 else:
  255.                     self._is_in_move = True
  256.                     pass
  257.                 return
  258.             return
  259.         elif event.type == gtk.gdk.BUTTON_RELEASE:
  260.             self._is_in_move = False
  261.             self._is_in_resize_rb = False
  262.             return
  263.         ## move MdiWindow
  264.         elif self._is_in_move and event.type == gtk.gdk.MOTION_NOTIFY:
  265.             px, py = self.parent.get_pointer()
  266.             if px < 5: px = 5
  267.             if py < 0: py = 0
  268.             if px > self._aw: px = self._aw
  269.             if py > self._ah: py = self._ah
  270.             mx = px + self._ox
  271.             my = py + self._oy
  272.             #self.move(mx, my)
  273.             self.parent.move(self, mx, my)
  274.             return
  275.         ## resize MdiWindow
  276.         elif self._is_in_resize_rb and event.type == gtk.gdk.MOTION_NOTIFY:
  277.             x, y = event.x, event.y
  278.             px, py = self.parent.get_pointer()
  279.             if x < 30: x = 30
  280.             if y < 30: y = 30
  281.             if px > self._aw: x = self.get_allocation()[2]
  282.             if py > self._ah: y = self.get_allocation()[3]
  283.             self.set_size_request(int(x), int(y))
  284.             return
  285.         pass
  286.     def on_menu(self, widget, event):
  287.         _print('on_menu:', widget, event)
  288.         pass
  289.     def on_icon(self, widget, event):
  290.         if event.button == 1:
  291.             _print('on_icon:', widget, event)
  292.         pass
  293.     def on_min(self, widget, event):
  294.         if event.button == 1:
  295.             _print('on_min:', widget, event)
  296.             self.min()
  297.         pass
  298.     def on_unmax(self, widget, event):
  299.         if event.button != 1: return
  300.         _print('on_unmax:', widget, event)
  301.         self.unmax()
  302.     def on_max(self, widget, event):
  303.         if event.button != 1: return
  304.         self.max()
  305.         pass
  306.     def on_close(self, widget, event):
  307.         if event.button == 1:
  308.             _print('on_close:', widget, event)
  309.             self.close()
  310.             pass
  311.         pass
  312.     def move(self, x, y):
  313.         _print('move:', x, y)
  314.         self.parent.move(self, x, y)
  315.         pass
  316.     def min(self, *args):
  317.         self._is_min = True
  318.         # save MdiWindow position x, y
  319.         self._old_wx, self._old_wy = self.get_window().get_position()
  320.         # save MdiWindow width, height
  321.         i, t, self._old_w, self._old_h = self.get_allocation()
  322.         self.parent.grab_focus()
  323.         #self.lower()
  324.         self.hide()
  325.         if 'mditabbar' in self.parent.parent.__dict__:
  326.             mditabbar = self.parent.parent.mditabbar
  327.             mditabbar.next_page()
  328.             pass
  329.         pass
  330.     def max(self, *args):
  331.         i, t, self._w, self._h = self.get_allocation()
  332.         i, t, self._aw, self._ah = self.parent.get_allocation()
  333.         if self._w < self._aw or self._h < self._ah:
  334.             self._is_max = False
  335.             pass
  336.         if self._is_max: return self.unmax()
  337.         ##
  338.         self._is_max = True
  339.         self._is_min = False
  340.         # save MdiWindow position x, y
  341.         self._old_wx, self._old_wy = self.get_window().get_position()
  342.         # save MdiWindow width, height
  343.         i, t, self._old_w, self._old_h = self.get_allocation()
  344.         self.move(0, 0)
  345.         self.set_size_request(self._aw, self._ah)
  346.         pass
  347.     def unmax(self, *args):
  348.         self._is_max = False
  349.         self._is_min = False
  350.         self.set_size_request(self._old_w, self._old_h)
  351.         self.move(self._old_wx, self._old_wy)
  352.         self.show_all()
  353.         pass
  354.     def close(self, *args):
  355.         if 'mditabbar' in self.parent.parent.__dict__:
  356.             mditabbar = self.parent.parent.mditabbar
  357.             mditabbar.remove(self)
  358.             pass
  359.         self.destroy()
  360.         pass
  361. class GtkMdiArea(gtk.Layout):
  362.     __gtype_name__ = 'GtkMdiArea'
  363.     __gsignals__ = {
  364.         'switch-window': (gobject.SIGNAL_RUN_LAST, None, (gtk.Widget,)),
  365.     }
  366.     need_resize = 1L
  367.     def __init__(self):
  368.         self.__gobject_init__()
  369.         #self.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color("#003300"))
  370.         self._old_w = 0
  371.         self._old_h = 0
  372.         self.unset_flags(gtk.CAN_FOCUS)
  373.         self.connect("size-allocate", self.on_resize)
  374.         pass
  375.     def add(self, mdiwindow, x=0, y=0):
  376.         gtk.Layout.put(self, mdiwindow, x, y)
  377.         mdiwindow.connect("switch", self.on_switch)
  378.         pass
  379.     def on_resize(self, widget, rectangle):
  380.         i, t, w, h = rectangle
  381.         if self._old_w == w and self._old_h == h:
  382.             return
  383.         _print('on_resize:', widget, rectangle)
  384.         self._old_w, self._old_h = w, h
  385.         for p in self.children():
  386.             if p._is_max:
  387.                 p.set_size_request(w, h)
  388.                 pass
  389.             pass
  390.         pass
  391.     def on_switch(self, widget, *args):
  392.         _print('on_switch', self, widget, args)
  393.         self.emit("switch-window", widget)
  394.         if 'mditabbar' in self.parent.__dict__:
  395.             mditabbar = self.parent.mditabbar
  396.             mditabbar.action_tab(widget)
  397.             pass
  398.         pass
  399. class GtkMdi(gtk.Table):
  400.     def __init__(self):
  401.         self.__gobject_init__()
  402.         self.mdiarea = GtkMdiArea()
  403.         self.mditabbar = GtkMdiTabbar()
  404.         ## table.attach(widget, left_attach=0, right_attach=1, top_attach=0,
  405. #bottom_attach=1)
  406.         self.attach(self.mditabbar, 0, 1, 0, 1, gtk.FILL, gtk.FILL, 0, 0)
  407.         self.attach(self.mdiarea,    0, 1, 1, 2)
  408.         pass
  409.     def set_tab_pos(self, pos):
  410.         # pos: 0: left, 1: right, 2: top, 3: bottom
  411.         pass
  412.     def add(self, mdiwindow, x=0, y=0):
  413.         self.mdiarea.add(mdiwindow, x, y)
  414.         self.mditabbar.add(mdiwindow)
  415.         pass
  416.     def tab_top(self, *args):
  417.         pass
  418. def _demo():
  419.     _print('main')
  420.     w = gtk.Window()
  421.     w.set_title("Test MDI")
  422.     w.set_default_size(500, 500)
  423.     mdi = GtkMdi()
  424.     ##
  425.     ts = gtk.ScrolledWindow()
  426.     ts.add(gtk.TextView())
  427.     ts.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
  428.     ts.set_size_request(150, 150)
  429.     mw = GtkMdiWindow(ts, 'MDI Document 1')
  430.     mdi.add(mw, 0, 0)
  431.     ##
  432.     ts = gtk.ScrolledWindow()
  433.     ts.add(gtk.TextView())
  434.     ts.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
  435.     ts.set_size_request(150, 150)
  436.     mw = GtkMdiWindow(ts, 'MDI Document 2')
  437.     mdi.add(mw, 30, 30)
  438.     ##
  439.     ts = gtk.ScrolledWindow()
  440.     ts.add(gtk.TextView())
  441.     ts.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
  442.     ts.set_size_request(150, 150)
  443.     mw = GtkMdiWindow(ts, 'MDI Document 3')
  444.     mdi.add(mw, 60, 60)
  445.     w.add(mdi)
  446.     w.show_all()
  447.     w.connect('delete-event', gtk.main_quit)
  448.     gtk.main()
  449. if __name__=="__main__":
  450.     _demo()
Copy the Code

你这个是MDI程序,和模拟不是一回事, 模拟是画出来的,就像窗口管理器一样,而不是这样, 我只是随便写了一点, 没有完全的体现出来.
要是做MDI程序 fixed在里面在放一些也可以. 我以前写visual python的时候实现过的, 有你上面的效果, 还可以放其它控件, 或者用gtk3, 嵌入窗口就完了.
重点在于模拟窗口管理器.我的程序没写完,我只是想去实验一下 窗口管理器模拟而已. 也不是一天两天的事情.
模拟, 是要去模拟窗口管理器的效果,不是MDI.

我知道你肯定不相信 fixed里面可以搞你那样的MDI, 很早的时候 visual python就玩过了. 地址: https://github.com/hailongqiu/visible-python
Reply View the author
New Thread

Popular Events

More
国际排名
WHLUG