PyGobject(一百一十)代码整合及GtkSource安装使用

官方demo中所有的例子程序最后都是在一个gtk-demo.py中展现出来的。本文稍微有做一点修改。就是左侧目录可以展示多级子目录。

例子

先上一张效果图
这里写图片描述
代码:

#!/usr/bin/env python3
# -*- Mode: Python; py-indent-offset: 4 -*-
# vim: tabstop=4 shiftwidth=4 expandtab
#
# Copyright (C) 2010 Red Hat, Inc., John (J5) Palmieri <johnp@redhat.com>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
# USA


import codecs
import os
import sys
import textwrap
import glob
import gi

gi.require_version('Pango', '1.0')
gi.require_version('GdkPixbuf', '2.0')
gi.require_version('Gtk', '3.0')
from gi.repository import GLib, GObject, Pango, GdkPixbuf, Gtk, Gio

try:
    gi.require_version('GtkSource', '3.0')
    from gi.repository import GtkSource  # PyFlakes
except Exception:
    GtkSource = None

DEMOROOTDIR = os.path.abspath(os.path.dirname(__file__))
DEMOCODEDIR = os.path.join(DEMOROOTDIR, 'demos')
sys.path.insert(0, DEMOROOTDIR)


class Demo(GObject.GObject):
    __gtype_name__ = 'GtkDemo'

    def __init__(self, title, module, filename):
        super(Demo, self).__init__()

        self.title = title
        self.module = module
        self.filename = filename

    @classmethod
    def new_from_file(cls, path):
        relpath = os.path.relpath(path, DEMOROOTDIR)
        packagename = os.path.dirname(relpath).replace(os.sep, '.')
        modulename = os.path.splitext(os.path.basename(relpath))[0]
        try:
            package = __import__(packagename, globals(), locals(), [modulename], 0)
            module = getattr(package, modulename)
            return cls(module.TITLE, module, path)
        except AttributeError as e:
            raise AttributeError('(%s): %s' % (path, e))


class DemoTreeStore(Gtk.TreeStore):
    __gtype_name__ = 'GtkDemoTreeStore'

    def __init__(self, *args):
        super(DemoTreeStore, self).__init__(str, Demo, Pango.Style)

        self._parent_nodes = {}

        self._list_dir(DEMOCODEDIR)

    def _list_dir(self, path):
        for filename in glob.glob(path + "/[!__]*"):

            if os.path.isdir(filename):
                self._list_dir(filename)
            elif os.path.isfile(filename) and filename.endswith(".py"):
                parentname = os.path.dirname(os.path.relpath(filename, DEMOCODEDIR))
                if parentname:
                    parent = self._get_parent_node(parentname)
                else:
                    parent = None
                demo = Demo.new_from_file(filename)
                self.append(parent, (demo.title, demo, Pango.Style.NORMAL))

    def _get_parent_node(self, name):
        if name not in self._parent_nodes.keys():
            parent_path, current_path = self._get_parent_path(name)
            if parent_path:
                node = self.append(self._get_parent_node(parent_path), (current_path, None, Pango.Style.NORMAL))
            else:
                node = self.append(None, (name, None, Pango.Style.NORMAL))
            self._parent_nodes[name] = node

        return self._parent_nodes[name]

    @staticmethod
    def _get_parent_path(path):
        index = path.rfind(os.sep)
        if index != -1:
            return path[0:index], path[index + 1:]
        else:
            return None, None


class GtkDemoApp(Gtk.Application):
    __gtype_name__ = 'GtkDemoWindow'

    def __init__(self):
        super(GtkDemoApp, self).__init__(application_id='org.gnome.pygobject.gtkdemo')

        # Use a GResource to hold the CSS files. Resource bundles are created by
        # the glib-compile-resources program shipped with Glib which takes an xml
        # file that describes the bundle, and a set of files that the xml
        # references. These are combined into a binary resource bundle.
        base_path = os.path.abspath(os.path.dirname(__file__))
        resource_path = os.path.join(base_path, 'demos/Data/demo.gresource')
        resource = Gio.Resource.load(resource_path)

        # FIXME: method register() should be without the underscore
        # FIXME: see https://bugzilla.gnome.org/show_bug.cgi?id=684319
        # Once the resource has been globally registered it can be used
        # throughout the application.
        Gio.resources_register(resource)

    def on_activate(self, app):
        self.window = Gtk.ApplicationWindow.new(self)
        self.window.set_title('PyGObject GTK+ Code Demos')
        self.window.set_default_size(600, 400)
        self.setup_default_icon()

        hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL,
                       homogeneous=False,
                       spacing=0)
        self.window.add(hbox)

        tree = self.create_tree()
        hbox.pack_start(child=tree, expand=False, fill=False, padding=0)

        # Right vbox contains info/source panels
        right_vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL,
                             homogeneous=False,
                             spacing=0)
        hbox.pack_start(child=right_vbox, expand=True, fill=True, padding=0)

        stack = Gtk.Stack(transition_type=Gtk.StackTransitionType.SLIDE_LEFT_RIGHT,
                          homogeneous=True)
        switcher = Gtk.StackSwitcher(stack=stack)
        right_vbox.pack_start(child=switcher, expand=False, fill=False, padding=0)
        right_vbox.pack_start(child=stack, expand=True, fill=True, padding=0)

        text_widget, info_buffer = self.create_text_view()
        stack.add_titled(text_widget, name='info', title='Info')

        self.info_buffer = info_buffer
        self.info_buffer.create_tag('title', font='Sans 18')

        text_widget, self.source_buffer = self.create_source_view()
        stack.add_titled(text_widget, name='source', title='Source')

        self.window.show_all()

        self.selection_cb(self.tree_view.get_selection(),
                          self.tree_view.get_model())

    @staticmethod
    def find_file(base=''):
        dir = os.path.join(DEMOCODEDIR, 'data')
        logo_file = os.path.join(dir, 'gtk-logo-rgb.gif')
        base_file = os.path.join(dir, base)

        if (GLib.file_test(logo_file, GLib.FileTest.EXISTS) and
                GLib.file_test(base_file, GLib.FileTest.EXISTS)):
            return base_file
        else:
            filename = os.path.join(DEMOCODEDIR, base)

            if GLib.file_test(filename, GLib.FileTest.EXISTS):
                return filename

            # can't find the file
            raise IOError('Cannot find demo data file "%s"' % base)

    def setup_default_icon(self):
        filename = self.find_file('gtk-logo-rgb.gif')
        pixbuf = GdkPixbuf.Pixbuf.new_from_file(filename)
        transparent = pixbuf.add_alpha(True, 0xff, 0xff, 0xff)
        list = []
        list.append(transparent)
        Gtk.Window.set_default_icon_list(list)

    def selection_cb(self, selection, model):
        sel = selection.get_selected()
        if sel == ():
            return
        treeiter = sel[1]
        title = model.get_value(treeiter, 0)
        demo = model.get_value(treeiter, 1)

        if demo is None:
            return

        # Split into paragraphs based on double newlines and use
        # textwrap to strip out all other formatting whitespace
        description = ''
        for paragraph in demo.module.DESCRIPTION.split('\n\n'):
            description += '\n'.join(textwrap.wrap(paragraph, 99999))
            description += '\n\n'  # Add paragraphs back in

        f = codecs.open(demo.filename, 'rU', 'utf-8')
        code = f.read()
        f.close()

        # output and style the title
        (start, end) = self.info_buffer.get_bounds()
        self.info_buffer.delete(start, end)
        (start, end) = self.source_buffer.get_bounds()
        self.source_buffer.delete(start, end)

        start = self.info_buffer.get_iter_at_offset(0)
        end = start.copy()
        self.info_buffer.insert(end, title)
        start = end.copy()
        start.backward_chars(len(title))
        self.info_buffer.apply_tag_by_name('title', start, end)
        self.info_buffer.insert(end, '\n')

        # output the description
        self.info_buffer.insert(end, description)

        # output the code
        start = self.source_buffer.get_iter_at_offset(0)
        end = start.copy()
        self.source_buffer.insert(end, code)

    @staticmethod
    def row_activated_cb(view, path, col, store):
        iter = store.get_iter(path)
        demo = store.get_value(iter, 1)
        if demo is not None:
            store.set_value(iter, 2, Pango.Style.ITALIC)
            try:
                demo.module.main()
            except Exception as e:
                print(demo.module)
                raise e
            finally:
                store.set_value(iter, 2, Pango.Style.NORMAL)

    def create_tree(self):
        tree_store = DemoTreeStore()
        tree_view = Gtk.TreeView()
        self.tree_view = tree_view
        tree_view.set_model(tree_store)
        selection = tree_view.get_selection()
        selection.set_mode(Gtk.SelectionMode.BROWSE)
        tree_view.set_size_request(200, -1)

        cell = Gtk.CellRendererText()
        column = Gtk.TreeViewColumn(title='Widget (double click for demo)',
                                    cell_renderer=cell,
                                    text=0,
                                    style=2)

        first_iter = tree_store.get_iter_first()
        if first_iter is not None:
            selection.select_iter(first_iter)

        selection.connect('changed', self.selection_cb, tree_store)
        tree_view.connect('row_activated', self.row_activated_cb, tree_store)

        tree_view.append_column(column)

        # tree_view.expand_all()
        tree_view.set_headers_visible(False)
        scrolled_window = Gtk.ScrolledWindow(hadjustment=None,
                                             vadjustment=None)
        scrolled_window.set_policy(Gtk.PolicyType.NEVER,
                                   Gtk.PolicyType.AUTOMATIC)

        scrolled_window.add(tree_view)

        label = Gtk.Label(label='Widget (double click for demo)')

        box = Gtk.Notebook()
        box.append_page(scrolled_window, label)

        tree_view.grab_focus()

        return box

    @staticmethod
    def create_scrolled_window():
        scrolled_window = Gtk.ScrolledWindow(hadjustment=None,
                                             vadjustment=None)
        scrolled_window.set_policy(Gtk.PolicyType.AUTOMATIC,
                                   Gtk.PolicyType.AUTOMATIC)
        scrolled_window.set_shadow_type(Gtk.ShadowType.IN)
        return scrolled_window

    def create_text_view(self):
        text_view = Gtk.TextView()
        buffer = Gtk.TextBuffer()

        text_view.set_buffer(buffer)
        text_view.set_editable(False)
        text_view.set_cursor_visible(False)

        scrolled_window = self.create_scrolled_window()
        scrolled_window.add(text_view)

        text_view.set_wrap_mode(Gtk.WrapMode.WORD)
        text_view.set_pixels_above_lines(2)
        text_view.set_pixels_below_lines(2)

        return scrolled_window, buffer

    def create_source_view(self):
        font_desc = Pango.FontDescription('monospace 13')

        if GtkSource:
            lang_mgr = GtkSource.LanguageManager.get_default()
            # print(lang_mgr.get_language_ids())
            lang = lang_mgr.get_language('python3')
            buffer = GtkSource.Buffer()
            buffer.set_language(lang)
            buffer.set_highlight_syntax(True)
            view = GtkSource.View()
            view.set_buffer(buffer)
            view.set_show_line_numbers(True)

            scrolled_window = self.create_scrolled_window()
            scrolled_window.add(view)

        else:
            scrolled_window, buffer = self.create_text_view()
            view = scrolled_window.get_child()

        view.modify_font(font_desc)
        view.set_wrap_mode(Gtk.WrapMode.NONE)
        return scrolled_window, buffer

    def run(self, argv):
        self.connect('activate', self.on_activate)
        return super(GtkDemoApp, self).run(argv)


def main(argv):
    """Entry point for demo manager"""
    app = GtkDemoApp()
    return app.run(argv)


if __name__ == '__main__':
    SystemExit(main(sys.argv))

GtkSource安装

要显示Python风格的源代码,需要安装GtkSource
具体方法为:

jhbuild build gtksourceview

安装完成后还需要把gtksourceview一些样式装到系统本地路径

cd /Users/xiaosanyu/gtk/source/gtksourceview 
./configure
make 
make install

可惜我的安装好后,只能显示行号,没有彩色关键字,报如下错误

(gtk-demo.py:22336): Gdk-WARNING **: GdkQuartzDisplay does not implement the monitor vfuncs
/Applications/Project/Python/project/PYGUI/pygtk3/gtk-demo.py:333: Warning: unknown option bit(s) set
buffer.set_language(lang)
/Applications/Project/Python/project/PYGUI/pygtk3/gtk-demo.py:333: Warning: g_regex_match_full: assertion ‘regex != NULL’ failed
buffer.set_language(lang)
/Applications/Project/Python/project/PYGUI/pygtk3/gtk-demo.py:333: Warning: g_regex_replace_eval: assertion ‘regex != NULL’ failed
buffer.set_language(lang)
/Applications/Project/Python/project/PYGUI/pygtk3/gtk-demo.py:333: Warning: g_regex_unref: assertion ‘regex != NULL’ failed
buffer.set_language(lang)
(gtk-demo.py:22336): GtkSourceView-WARNING **: in file /usr/local/share/gtksourceview-3.0/language-specs/python3.lang: style ‘python:module-handler’ not defined
(gtk-demo.py:22336): GtkSourceView-WARNING **: Failed to load ‘/usr/local/share/gtksourceview-3.0/language-specs/python3.lang’: style override used with wildcard context reference in language ‘python3’ in ref ‘def:line-continue’

貌似是正则库没有装好,还请有装好的朋友给个参考方法

20160804
更新:pcre正则匹配原因找到了

修改/Users/xiaosanyu/gtk/source/glib/glib/gregex.c
大约1420行

 re = pcre_compile2 (pattern, compile_options, &errcode,
                      &errmsg, &erroffset, NULL);

改成

 re = pcre_compile2 (pattern, 0, &errcode,
                      &errmsg, &erroffset, NULL);

然后重新编译glib

jhbuild build glib

OK,大功告成,开心~~~~~





代码下载地址:http://download.csdn.net/detail/a87b01c14/9594728

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
安装vscode时,您遇到了一个问题,即安装python-gi时2.7版本的python覆盖了您的3.8版本的python命令,导致vscode中的jupyter无法启动。为了解决这个问题,您可以尝试以下几种方法: 1. 确保您的电脑上已经安装了3.8版本的python,并且将其添加到系统的环境变量中。这样可以确保在安装python-gi时不会覆盖您的3.8版本的python命令。 2. 如果您已经安装了3.8版本的python,但仍然遇到了问题,可以尝试使用虚拟环境来隔离不同版本的python。您可以使用工具如virtualenv或conda来创建一个独立的虚拟环境,并在该环境中安装所需的python-gi版本。 3. 如果以上方法都无法解决问题,您可以考虑手动编译和安装pygobject。您可以从官方网站下载源代码,并按照它们提供的说明进行编译和安装。这样可以确保您使用的是与您的python版本兼容的pygobject版本。同时,您还可以尝试使用其他构建工具,如buildout、BitBake、fabricate等,来构建和部署应用程序。 总结来说,解决vscode安装pygobject的问题可以通过确保正确的python版本和环境设置,使用虚拟环境隔离不同版本的python,或者手动编译和安装pygobject来实现。希望这些方法能够帮助您解决问题。\[1\]\[2\]\[3\] #### 引用[.reference_title] - *1* [ubuntu安装微信](https://blog.csdn.net/qq_36591505/article/details/115675488)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [awesome-python(python集合框架)](https://blog.csdn.net/chehec2010/article/details/119754494)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sanxiaochengyu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值