K.I.S.S. – 简单哲学 Linux, Freedom, Arch, Python, Gtk+, C … Keep It Simple, Stupid!

2一/112

使用 gtkaml 编写 GTK+ 界面

想必大家对 GTK+ 跑在 HTML5 上已经不感到惊讶了,那么用 编写 + 界面呢?好吧,Glade 是这样做的,不过今天介绍的不是它,而是

按照官网的介绍,gtkaml 是基于 的一种标记语言,旨在使用简洁的 XML 语法来描述 GTK+ 界面,乍看起来和 Glade 没有什么区别。

不过 gtkaml 采用的是类似于 Glade 2 的转换代码方式,将 XML 转换成 Vala 代码再进行编译。不过,不用担心图形界面和实际代码分离的问题,因为 gtkaml 在 XML 中预留了 Vala 代码的空间,也就是说,你不需要面对自动转换得到的很可能难懂的代码进行修改,而只需要在 XML 中直接书写 Vala 代码即可!

另外,觉得标准的 XML 太过繁复? gtkaml 还提供了一种叫做 的语法,允许你使用类似 的语法编写界面,语法一下子就简洁了好多,看个 Hello World 吧(来自 Vala Code):

Window using=Gtk name=GtkHello type={WindowType.TOPLEVEL} title="First GTK+ Program"
        position={WindowPosition.CENTER} default-width=300 default-height=50 destroy=Gtk.main_quit
{
        Button label="Click me!" clicked={target.label="Thank you"};
        -{
                static int main (string[] args) {
                        Gtk.init (ref args);
                        var window = new GtkHello ();
                        window.show_all ();
                        Gtk.main ();
                        return 0;
                }
        }-
}

怎么样?在 Vala 代码中,根本就没有怎么写与界面相关的东西,是不是很 Cool?更多代码可以看官方 Wiki 的样例

另外,虽然 gtkaml 现在仅支持 Vala 和 GTK+,不过根据官方介绍, 的支持也在计划中,而只要有 vapi 的库,都可以使用 gtkaml 而不限于 GTK+,相信 gtkaml 的前景应该不赖。

9十一/104

Marlin —— GNOME 下新文件管理器启动!

首先得说明,这个不是 官方的计划,而是 Elementary 项目的一部分。

相信 -elementary 大家都很熟悉了,这个 的修改版,为 GNOME 用户提供了一个更加美观易用的文件管理器。不过, Elementary 小组为 做的一些修改被上游认为是 Hacks 而迟迟不被接受,现在,他们终于开始研究自己的文件管理器了!

采用 编写界面,而 用来编写底层函数。在界面的编写上,使用了 + 3 和其他的 GNOME3 的时髦技术;而在底层上, 则从 Nautilus 和 Thunar 里面“偷”了些代码。加上 Elementary 自己本身特长的发挥,相信 相较于 Nautilus 会在多个方面有所突破!

当然,Marlin 的代码刚刚推送上 launchpad 还不到一天,不要期待能够马上用到稳定版本,不过 bzr 版本已经可以看出它的一些特色了:

marlin_preview.png

电脑上没有装 GTK+ 3 的主题引擎,所以看起来丑了点。可以看出,Marlin 现在默认是这种小栏模式,嵌套进入目录,有点像 Ranger 的样子,操作起来很方便。当然那三个五角星预示着 Marlin 肯定会有各种传统的视图模式,另外,隐藏菜单栏之类的原有功能也是少不了的。

虽然,Marlin 还处于早期开发阶段,不过 Elementary 小组的品质一向很有保证,让我们见证这一文件管理器闪耀出奇迹的光吧!

Marlin 的源代码目前托管在 launchpad 上,可以通过下面的命令获得源代码:

bzr branch lp:marlin
2八/1015

人生苦短,我用 Genie

这篇文章已经酝酿很久了,不过一直没时间没心情写。今天到学校开始学日语了,又看到 WowUbuntu 介绍的日语 50 音图测试软件 Kanatest 的 AUR 里面找不到,所以干脆自己写一个,顺便补上这篇文章。

进入正题,开发一个 Linux 下的软件,你选择的编程语言是什么呢?我想大多数人会选择 或者 吧。像上面说的 50 音图测试软件,用 C 开发有些大材小用了,用 呢,要是涉及运算的时候速度又不尽人意。

那么用什么呢?Google 的 Go 语言?库还不完善呢。?有些人会想到这个 的项目了,确实,Vala 对于熟悉 C# 的朋友可能十分顺手,可是对于更加喜欢 Python 的朋友,或许就不是那么友好了。

好的,我们的主角登场了,

既然你知道 Vala,或许你也知道,它只是对 C 语言的一个包装,运行效率与 C 相差无几。Genie 语言就是 Vala 的同胞弟弟,它也是对 C 语言的包装和翻译,能够实现 Vala 的所有特性,甚至“编译器”都是相同的——valac!唯一不同的是,Genie 是以 Boo、Python 等脚本语言为蓝本,语法上更加灵活、简洁,如果你学过 Python,Genie 的入门将十分之快!

来看看我写的这个简单的 50 音图背诵软件吧,功能很简单,就是将日语的平假名随机闪现,相信有 + 基础的朋友很容易就可以看懂。

/* Build with valac --pkg gtk+-2.0 mykana.gs */
[indent=4]
uses
    Gtk

init
    Gtk.init(ref args)
    var window = new MainWindow()
    window.show_all()
    Gtk.main()

class MainWindow: Window
    label: Label
    const chars : array of string = {"あ", "い", "う", "え", "お", "か", "き", "く", "け", "こ", "さ", "し", "す", "せ", "そ", "た", "ち", "ち", "て", "と", "な", "に", "ぬ", "ね", "の", "は", "ひ", "ふ", "へ", "ほ", "ま", "み", "む", "め", "も", "や", "う", "よ", "ら", "り", "る", "れ", "ろ", "わ", "を", "ん"}

    init
        title = "My Kana"
        window_position = WindowPosition.CENTER
        default_width = 250
        default_height = 250
        destroy.connect(Gtk.main_quit)
        label = new Label(null)
        add(label)
        Timeout.add_seconds(1, this.change_char)

    def change_char(): bool
        var i = Random.int_range(0, 46)
        var output = Markup.printf_escaped("%s", chars[i])
        label.set_markup(output)
        return true

可以看出,除了类型声明之外,从某种程度上讲,Genie 的语法甚至比 Python 更加简单。而且,通过使用 libgee,Genie 甚至可以使用等同于 Python 中的 list、dict 等类型,功能十分强大。Genie 与 Vala 共用 API,所以库的问题也不用担心。

不过,Genie 创造于 2008 年,年纪还很轻,文档还不够全。就如同 Vala 一样,Genie 的语法也在发展之中。如果你觉得这些都不是问题,那么赶快看看文档学习一下吧!

我觉得很不错的一些文档:官方指南来自 Puppy Linux 的指南官方代码示例

标签: , , , 15 评论
16七/109

GtkApplication – GTK+ 3 中的 Application 支持

+ 3 在紧锣密鼓的开发之中,虽然说 3.0 版本相对于 + 2 在编程方面的改变并不大,不过仍然有些改变是和 + 使用者密切相关的,比如新加入的 GtkApplication 类。

大家知道开始学习 GTK+ 的一个难点就是莫名其妙的 gtk_init()、gtk_main(),以及 quit、destroy 等信号的区别之类的,简单来说,一个 Hello World 程序的构建过程很让人困惑,感觉就像记住了一个模板,每次都要写一次。

GTK+ 3 为了解决这个问题,抽象出了 GtkApplication 这个类,那么一切都变得容易理解起来:gtk_init() 就是 GtkApplication 的构造函数,现在只需要调用 gtk_application_new() 就可以,gtk_main() 现在变成了 gtk_application_run(),意义很明显,而程序的退出也只需要连接 GtkApplication 类的 quit 信号即可。

GtkApplication 默认自带一个 GtkWindow,可以通过 gtk_application_get_window() 获得,因此一个新的 Hello World 看起来可能是这样:

#include <gtk/gtk.h>
int
main (int argc, char **argv)
{
  GtkApplication *app;
  GtkWindow *window;

  app = gtk_application_new ("org.gtk.Example", &argc, &argv);

  window = gtk_application_get_window (app);
  gtk_container_add (GTK_CONTAINER (window), gtk_label_new ("Hello world"));
  gtk_widget_show_all (GTK_WIDGET (window));

  gtk_application_run (app);

  return 0;
}

怎么样,是不是简单明了得多?

更多关于 GtkApplication 类的信息可以参照 GTK+ Reference Manual

标签: 9 评论
8五/1019

神秘软件 Yaner 截图

我就发图,我不说话。

yaner-main.png
yaner-normal.png
yaner-bt.png
yaner-metalink.png

27五/090

在自己的 GTK+ 程序中加入 RGBA 透明支持

上次介绍了怎么在 Arch Linux 下启用 RGBA 透明窗口 ,然而,目前支持 的程序还很少,看起来有的透明,有的不透明,很不爽吧?
另外,+ 默认是不启用 RGBA 支持的,我们自己编写程序的时候,怎么加入 RGBA,达到这种酷炫的效果呢?
细心的同学可能已经发现,上次我发的图中最顶端那个程序就是我自己写的,而且已经实现了半透明效果。
加入 RGBA 效果的方法并不难,仅仅是几条语句而已,看看下面的 patch:

From fb88cb790a08e9285e6656f83342645ae9f93a Mon Sep 17 00:00:00 2001
From: Kevin Lange
Date: Wed, 5 Mar 2008 09:26:53 -0500
Subject: [PATCH] Added RGBA colormap support to the GUI

---
 ccm/Window.py |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/ccm/Window.py b/ccm/Window.py
index 09306da..84f1d76 100644
--- a/ccm/Window.py
+++ b/ccm/Window.py
@@ -42,6 +42,10 @@ class MainWin(gtk.Window):

     def __init__(self, Context, pluginPage=None, categoryName=None):
         gtk.Window.__init__(self)
+        self.gtk_screen = self.get_screen()
+        colormap = self.gtk_screen.get_rgba_colormap()
+        if colormap:
+            gtk.widget_set_default_colormap(colormap)
         self.ShowingPlugin = None
         self.Context = Context
         self.connect("destroy", self.Quit)
@@ -99,6 +103,7 @@ class MainWin(gtk.Window):
             self.ToggleCategory(None, categoryName)

     def Quit(self, *args):
+        gtk.widget_pop_colormap()
         gtk.main_quit()

     def ResetMainWidgets(self):
--
1.5.2.5

呵呵,这是 CCSM 的 RGBA 补丁,看到了吧,其实关键的也就那么几行而已,在初始化的时候试着载入 RGBA 颜色表,在退出的时候对颜色表进行出栈,其他语言也是这个道理。
有了这几行代码,是不是想把桌面上的所有 GTK+ 程序 hack 掉?
呵呵,赶快在自己的程序里加入 RGBA 支持吧!

26五/092

在 Arch Linux 下启用 RGBA 透明窗口

看了 Ubuntu 9.04 那么炫,突然感觉自己的 好像缺了什么,哎?窗口怎么不是透明的啊……
这个东西是由 控制的,大家知道 RGB 是通常所说的三原色:红绿蓝,那么 A 是什么呢?不错,就是 Alpha,透明。
Arch 里面默认没有启用透明的引擎,所以窗口都是 RGB 的,看起来当然不如 Ubuntu 那么炫啦~
那么怎么在 Arch 里面启用透明呢?

先来看一下效果图:

screenshot_001.png

其实启用方法很简单,只要从 AUR 里安装 librgba--module 这个包就可以了:

yaourt -S librgba-gtk-module

然后按照提示,运行:

-color-chooser

在弹出的窗口里选择“引擎”-“全局”-“Murrine”-“首选项”,勾上 Enable/Disable RGBA support 的两个勾就行了。

rgba_setting.png

应用的时候,可能会等待一会儿,之后就可以看到透明窗口和控件啦!
值得一提的是,并非所有窗口都支持透明效果,这要看软件的源代码启没启用支持哦~
以上方法在 Arch Linux、Gnome 2.26.2 下验证通过。

标签: , , 2 评论
24五/091

今天给大家讲了讲 Linux

呵呵,这是第二次讲课哦,上次讲 + 感觉太深了,于是这次讲些体系的东西。
不过这次还是有很多人没有基础啊,好象又讲深了……唉……
希望能起到引路的作用吧……附上简报:

2五/090

使用 PyGTK 和 Cairo 编写一个简单的时钟

呵呵,其实说这个是个自定义控件也不为过。
先介绍一下 Cairo:Cairo 是一套提供设备独立的矢量图形 API 的二维图形库,支持很多不同的后端,如果可能的话,还可以使用硬件加速绘图。Cairo 是用 语言编写的,但是提供了很多其他语言的绑定,Factor, Haskell, Lua, Perl, , Ruby, Scheme, Smalltalk 等等。Cairo 基于 LGPL 和 MPL 双许可,这意味着你可以用它开发闭源软件。Cairo 是自由软件。
关于 Cairo 的更多详情,可以参照维基百科
Cairo 的使用方法很简单,跟中学时学习的 LOGO 语言差不多,这里用 + 编写一个时钟出来。
首先,建立一个窗口。GTK+ 提供了一个专门用来画图的控件 DrawingArea,我们继承它,建立一个类 CairoDrwa,并且把一个对象加到窗口上去。虽然 GTK+ 本身提供了不少绘图功能,不过这里只说 Cairo。

import gtk, glib, math, time
class CairoDraw(gtk.DrawingArea):
   """Drawing with Cairo"""
   def __init__(self):
       super(self.__class__,self).__init__()

class MainWindow(gtk.Window):
   """Main window of the test program"""
   def __init__(self):
       super(self.__class__, self).__init__(gtk.WINDOW_TOPLEVEL)
       self.set_title("Cairo test")
       self.connect("delete-event", gtk.main_quit)

       cairo_test= CairoDraw()
       self.add(cairo_test)

   def main(self):
       self.show_all()
       gtk.main()

if __name__ == "__main__":
   window = MainWindow()
   window.main()

然后,连接事件。把这个类的 expose-event 连接到一个回调函数 on_expose 上去,expose-event 是一个“曝光”事件,在控件被显示的时候会触发此事件。

class CairoDraw(gtk.DrawingArea):
   """Drawing with Cairo"""
   def __init__(self):
       super(self.__class__,self).__init__()
       self.connect("expose-event", self.on_expose)

下面来写 on_expose 函数。首先我们要取得我们的 Cairo Context(可以理解为“画板”),这个画板是从 DrawingArea 中的 GdkWindow 中取得的。

    def on_expose(self, widget, event):
       context = widget.window.cairo_create()
       return False

我们需要设定 DrawingArea 的刷新区域。这样以后每次触发 expose-event 的时候,都会重绘这个区域。

    def on_expose(self, widget, event):
       context = widget.window.cairo_create()

       context.rectangle (event.area.x, event.area.y,
               event.area.width, event.area.height)
       context.clip()

       return False

我们把绘图的部分写在 draw 这个函数中,然后让控件每秒钟重绘一次。这样每秒时间改变的时候,图形就会刷新,指针就会动了。

    def on_expose(self, widget, event):
       context = widget.window.cairo_create()

       context.rectangle (event.area.x, event.area.y,
               event.area.width, event.area.height)
       context.clip()

       self.draw(context)

       glib.timeout_add(1000, self.queue_draw)
       return False

下面来写 draw 这个函数。
首先来画表盘,也就是一个圆。我们用 arc 函数来画一个弧线,这个弧线的角度从 0 到 2 * pi,也就是一个圆了。注意,这时候我们还没有上色,所以画板依然是空的。使用 set_source_rgb 来设定画笔颜色,fill_preserve 和 stroke 分别用于填充和描边。

clock1.png

    def draw(self, context):
       rect = self.get_allocation()
       x = rect.x + rect.width / 2
       y = rect.x + rect.height / 2
       radius = min(rect.width / 2, rect.height / 2) - 5

       context.arc(x, y, radius, 0, 2 * math.pi)
       context.set_source_rgb(1, 1, 1)
       context.fill_preserve()
       context.set_source_rgb(0, 0, 0)
       context.stroke()

接下来画刻度。很简单的算法,值得注意的是 save 和 restore 两个函数,这是一种类似堆栈的保存 Context 状态的方法,这样对线的长度修改之后,很容易就可以恢复过来。

clock2.png

        for i in xrange(12):
           context.save()

           if i % 3 == 0:
               inset = .2 * radius
           else:
               inset = .1 * radius
               line_width = context.get_line_width()
               context.set_line_width(.5 * line_width)

           context.move_to(
                   x + (radius - inset) * math.cos(i * math.pi / 6),
                   y + (radius - inset) * math.sin(i * math.pi / 6))
           context.line_to(
                   x + radius * math.cos(i * math.pi / 6),
                   y + radius * math.sin(i * math.pi / 6))
           context.stroke()
           context.restore()

最后,对指针进行绘制。和表盘差不多的算法。

clock3.png

        tm_hour, tm_min, tm_sec = time.localtime()[3:6]
       handlist = (
               (tm_hour, .3, 12, 1.5),
               (tm_min, .2, 60, 1),
               (tm_sec, .1, 60, .5),
               )
       for (hand, inset, num, width) in handlist:
           context.save()

           inset *= radius
           line_width = context.get_line_width()
           context.set_line_width(width * line_width)
           context.move_to(
                   x + (radius - inset) * math.sin(2 * hand * math.pi / num),
                   y - (radius - inset) * math.cos(2 * hand * math.pi / num))
           context.line_to(x, y)
           context.stroke()

           context.restore()

这样,一个简单的时钟程序就做好了。源代码在这里
参考:Writing a Widget Using Cairo and PyGTK 2.8
PS:晕,写完了才发现这篇文章还有下半部分……

23三/093

昨天给大家讲了讲 Gtk+

呵呵,听众都是些大一大二的,我本来也是个菜鸟,不过为了社区的发展,咳咳,当然还有 Linux 的发展,我也就硬着头皮上了……
呵呵,也就是讲些基础的知识,gcc、make、helloworld什么的,不过看下面,基本已经晕了……而且不知为何,所有人齐齐往后面坐……哭,本来就没几个人的说……
连讲了一个半小时,本来就咽炎,出来的时候嗓子疼死了……
简报放在 Google Docs 上面了。

标签: , , , 3 评论
   下一页