Category: 编程、软件、技术

  • Hello, My Android(三)

    界面设计完成后,我要开始为那个Button的单击事件设计响应函数。

    在Android中,事件的设计也很诡异。我们先来看代码:

    (more…)

  • Hello, My Android(二)

    接下来,我们继续看属于LinearLayout的子控件的两个控件:TextView和Button。有关Android界面中可以用到的Widget有哪些我会在以后再描述。

    ===================

    (more…)

  • Hello, My Android!(一)

    我想,部分是受到了山寨机也即将支持Android的鼓舞,最近我下载了一套Eclipse Ganymede+Android SDK,开始看看在这套著名的API下开发Android应用会是怎样的体验。 不是说以前没有尝试过开发手机下的应用。比如,在我04年用Palm的时候,06年用WM的时候,08年用Symbian的时候……不过都可耻滴放弃了:

    • 放弃Palm是因为它的开发理念和我习惯的事件驱动相差实在太远;
    • 放弃WM是因为那时(包括现在)很BSMS;
    • 放弃Symbian是因为我有一个朋友开的公司将Symbian开发做到了极致,我肯定超不过他的水平……

    好吧,让我来看看Android……

    ===================

    当然,如何设置ADT(Android Eclipse Plugin)我就不说了(什么,你不知道怎么玩Eclipse?这个这个……);怎么用Wizard来创建基本的框架我也不多说了。我只说说接下来我做的事情。 首先,我先创建了一个Run的配置,然后就开始运行。Android模拟器顺利的启动了,新创建的项目也顺利执行。然后我开始看整个项目的结构:

    HelloMyAndroid
    ├─assets
    ├─bin
    │  └─com
    │      └─android
    │          └─tr
    │              └─testcase
    ├─res
    │  ├─drawable
    │  ├─layout
    │  └─values
    └─src
        └─com
            └─android
                └─tr
                    └─testcase

    在这个结构中:

    • assets目录目前是空的,我也暂时先不管这个目录派什么用场。不过从英文名可以推测是放置一些“有用的东西”;
    • bin目录下有三个文件:classes.dex, HelloMyAndroid.apk, resources.ap_。根据说明,这个apk文件就是以后安装应用程序到手机上时需要使用的打包文件;
    • bin目录下还有一个很深的目录结构,它其实代表了我创建这个程序时所选择的包:com.android.tr.testcase。在testcase目录下是编译好的class文件。
    • res目录下给出了Android程序中最常用的三种资源:drawable,layout,values。在drawable目录中只有一个icon.png,这个图标会成为我们程序的图标;layout目录中目前只有一个main.xml,在这个xml文件中,描述了程序界面——应该说,用xml描述界面没有什么不对的,但是如果没有一个GUI来辅助用户设计界面是8HD的;values目录中有一个strings.xml文件,这里保存着程序中使用到的字符串(你当然可以选择不用这种方式来保存、使用字符串,但是会失去i18n的灵活性)。
    • src目录下,又是一个对应于我开发这个程序时所选择的包的路径。在testcase目录下,有两个文件:一个是HelloMyAndroid.java,一个是R.java。前者当然是我编写的源文件,而后者是根据res目录中资源的情况自动生成的一个资源-ID对照表。

    =================

    由于我准备在一个很常规的Hello World程序中增加一些新东西,所以我第一步就开始修改界面。为此,我修改了res/layout/main.xml:

    <?xml version=1.0 encoding=utf-8?>
    <LinearLayout xmlns:android=http://schemas.android.com/apk/res/android
                        android:orientation=vertical
                        android:layout_width=fill_parent
                        android:layout_height=fill_parent
    >
        <TextView
            android:id=@+id/lblHello
            android:layout_width=fill_parent
            android:layout_height=wrap_content
            android:text=@string/hello
        />
        <Button
            android:id=@+id/btnClickMe
            android:layout_width=fill_parent
            android:layout_height=wrap_content
            android:text=@string/btn_click_me
        />
    </LinearLayout>

    我选择使用LinearLayout来线性安排我的控件(在Android中称为“Widget”),而android:orientation=vertical表示这个布局将是竖直方向的;android:layout_width=fill_parentandroid:layout_height=fill_parent表示这个布局的宽度、高度都将填充整个父控件的空间(这里就是整个屏幕)。 (未完待续)

  • Old Stable vs New Buggy

    最近的电脑很不稳定!很不稳定!!

    每次在我认真的打P聊天BT的时候,蓝屏!蓝屏!!

    =========

    (more…)

  • License your work

    猛禽在他的BLOG里针对煎蛋的放弃CC的协议进行了一段评论(原文连接)。文中提到了这么一段:

    跟煎蛋那些连协议是怎么回事都不理解的人真是没什么好讨论的,改叫扯蛋算了。

    我突然想到,我这里(两块内容:BLOG部分和非BLOG部分)一直也没有很好的定义一个我的授权类型。虽然耳濡目染的知道CC, (L)GPL, Apache……这样的名词,但是却从来没有认真的去看一下这些协议的内容——部分是被其臃肿的法律文件给吓坏了……

    今天既然CC被搬上了台面,我就下决心仔细看看关于CC协议的内容。

    (more…)

  • PHP创建Excel文件

    【本文收录于Go4Pro.org】 在我的任氏有无轩页面中,有一个专门记载湖人比赛情况的页面。随着NBA 08-09赛季的开幕,这个页面就开始频繁的更新了。

    在之前的改版中,我已经将这个页面用Smarty页面重新改写了,这次是要为其加入导出比赛情况到Excel文件的功能。

    211103注:本页面已经全面改写。

    ============

    我使用的后台库是PEAR类库中的Spreadsheet_Excel_Writer。安装了PEAR的用户都可以用以下命令安装这个库:

    pear install --onlyreqdeps Spreadsheet_Excel_Writer-beta

    PEAR还是很方便的。在我的PHP环境中,这个库将安装在<PHP install dir>/PEAR/Spreadsheet下。我习惯将<PHP install dir>/PEAR加入到我的PHP包含路径中去,这样在引用包含文件时可以省力一些。

    ==========

    获取来自数据库的内容等操作就不再赘述,只讲针对Excel导出的部分:

    require_once(Spreadsheet/Excel/Writer.php);
    $sdate=date(Y-m-d, strtotime($_POST['sYear'].-.$_POST['sMonth'].-.$_POST['sDay']));
    $edate=date(Y-m-d, strtotime($_POST['eYear'].-.$_POST['eMonth'].-.$_POST['eDay']));
    $rows=getGames($sdate, $edate);
    $wb=new Spreadsheet_Excel_Writer();
    $wb->send(Laker Games.xls);
    $ws=&$wb->addWorksheet(Games_Summary);
    $f_title=&$wb->addFormat(array('bold'=>true,
                                   'Align'=>'center',
                                   'Color'=>'blue',
                                   'FgColor'=>'yellow'));
    $ws->write(0,0, Game Sequence, $f_title);
    $ws->write(0,1, Date Played, $f_title);
    $ws->write(0,2, Teams, $f_title);
    $ws->write(0,3, Score, $f_title);
    $ws->write(0,4, Win/Lose, $f_title);
    $ws->write(0,5, Remarks, $f_title);
    $rowid=1;
    foreach ($rows as $game)
    {
        $ws->write($rowid,0, $game['seq']);
        $ws->write($rowid,1, $game['date']);
        $ws->write($rowid,2, $game['team']);
        $ws->write($rowid,3, $game['score']);
        $ws->write($rowid,4, $game['win']);
        $ws->write($rowid,5, iconv('utf-8', 'gb18030', $game['note']));
        $rowid++;
    }
    $wb->close();

    ==================

    大部分代码是自明的。不做太多的说明,结合PEAR关于Spreadsheet_Excel_Writer的文档,应该很容易知道各行代码的作用。

    值得注意的是,以上的代码无法在XAJAX的环境下执行。我猜想,原因在于send函数:

    function send($filename)
    {
            header(Content-type: application/vnd.ms-excel);
            header(Content-Disposition: attachment; filename=$filename);
            header(Expires: 0);
            header(Cache-Control: must-revalidate, post-check=0,pre-check=0);
            header(Pragma: public);
    }

    在这个函数中,Writer用header的方式来“欺骗”浏览器,表明将要输出的内容是一个Excel的表格文件。我认为,正是这个HEAD信息破坏了XAJAX(即AJAX)所维系的头信息,造成该函数无法在XAJAX的环境下运行(但是也不出错……)。

    Writer并没有提供一个独立的将生成的Excel内容保存起来的函数,有时间、有精力的话在这个方面加以改进应该是不错的。

  • 更友好的WordPress帖子的链接

    WP的后台管理页面中,可以设置帖子的Permalinks样式。 缺省时,它是用非SEO友好的形式的,例如:http://www.rsywx.net/wordpress/?p=960 这样的形式。但是,用户可以定制Permalinks的格式,并通过后台URI重写规则从而得到更SEO友好的URI。 我的设置是这样的:/%year%/%monthnum%/%post_id%,因此所有的帖子的连接都会是类似:http://www.rsywx.net/wordpress/2008/10/960 这样的,对应的URI重写规则为:

    RewriteRule ^wordpress/([0-9]+)/([0-9]+)/([0-9]+) wordpress/?p=$3

    如何,很简单吧?

    10月13日补记:

    突然想到,这个重写和Pylons的map还是有点不一样的。我在书写Pylons的map规则的时候,感到很不愉快。因为它的这个类似重写的规则,是和路径相关的。 例如,当我想将/xxx/yyy映射为/xxx?id=yyy的时候,所有html的路径映射都是基于/xxx/yyy而进行,而此时物理文件还是存放在/xxx目录下,所有的CSS/image/JavaScript的相对路径都是按照/xxx计算的,因此立马出现了路径的映射错误——除非你使用绝对路径进行引用……

    另外,又发现一个小问题。WordPress处理页面和帖子的方法是不一样的。在激活上述的RewriteRule之后,页面链接将出现问题,因此必须再一个新的RewriteRule:

    RewriteRule ^wordpress/([0-9]+) wordpress/?pageid=$1

    并在后台管理程序中将各个页面的链接的PermaLink修改即可。

    10月14日补记 今天又突然发现上述的重写规则对于一些WP的连接,如tag,按月的存档等还是不起作用。搜索一番并借助WP的帮助后,最终的重写规则如下,同时,该重写规则应存放在wordpress工作目录中:

    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-D
    RewriteRule . /wordpress/index.php [L]

    这个规则就基本正常了。唯一的问题是wordpress/wp-admin不能正常工作,而必须用wordpress/wp-admin/index.php才行。

  • 编程的乐趣

    这两天,和狗屎皮群在讨论一个小应用的编写。作为这个主意的提出者,原型的编写当然应该是我来做。

    在选择原型开发语言时,我还是踌躇了一番。从将来(必然的WEB)扩展来看,用python或者PHP似乎更好,但是我对这些脚本语言的OO特性一直掌握的不好。所以,在挣扎了20分钟后,我还是觉得用C++更“顺手”一些。

    我编程是从来不会先写什么流程图的。在脑海中将应用的框架做了一番YY后,自然就知道了要有哪些底层的类。然后简单的测试例程应该如何写也就清楚了。

    终于今天完成了一个最最最基本的原型。前令狐已经写好了针对Linux,minGW,VC,BCC的makefile,这样不同的开发平台都可以对这个原型进行编译了。我个人测试了BCC和Linux的编译,代码的兼容性应该是不错的。只有在Linux下出现了两个无关痛痒的warning。

    感觉很有成就感。当我看到程序的测试输出和我的想象一致的时候,我还是很兴奋的。

  • 【一日一得】Paamayim Nekudotayim

    在OO的编程语言(如C++)中,有一个很重要的符号:::,即双冒号,一般称其为Scope Resolution Operator,范围解析运算符。

    在C++中,我们可以这样写:

    class Base
    {
        protected int i;
        public showI()
        {
            cout showI();
            //感谢指正,用脚本语言多了,忘记在C++中是没有GC的
            delete d;
            d=NULL;
        }
    }

    (more…)

  • Smarty中用section完成主从表循环

    在我的“任氏有无轩”WEB界面中,有一个是读书页面。这个页面列出了我非但读过、而且写过相关评论的书籍,各个评论将链接到对应的BLOG文章去。 显然,这是一个很典型的“一对多”的主从表循环。原来我是简单的用嵌套循环,现在既然用了Smarty引擎,我就改用了Smarty中的section语法。

    =======================

    Smarty中的section语法说来不复杂——特别是在不嵌套的时候:

    <?php
    //从PHP脚本中assign()一个数组给Smarty:
    $data = array(1000,1001,1002);
    $smarty->assign('custid',$data);
    ?>
    输出数组的模板:
    {* 本例将打印出$custid数组的所有值 *}
    {section name=customer loop=$custid}
    id: {$custid[customer]}
    {/section}
    {*  逆序打印所有$custid数组中的值 *}
    {section name=foo loop=$custid step=-1}
    {$custid[foo]}
    {/section}

    语法是自明的,这里不多做解释。如果牵涉到主从表的嵌套循环,那么语法会稍微复杂一些:

    {section name=reading loop=$readings}
        //循环显示外层循环的内容
        {section name=reading_detail loop=$reading_details[reading]}
        {$reading_details[reading][reading_detail].reviewid} <a
          href={$reading_details[reading][reading_detail].uri}>
        {$reading_details[reading][reading_detail].title}
        </a>
        {$reading_details[reading][reading_detail].datein}
        {/section}
    {/section}

    可见,外层循环(主循环)还是保持基本语法不变,内层的语法中需要特别注意loop=$reading_details[reading]这个loop变量的控制,以及循环显示内层循环的内容时对索引的引用控制。 当然,我使用的是一种最直截了当的方法。在对应的PHP文件中,对各个循环变量可以使用一个类似的嵌套循环来赋值:

    $i=0;
    $arr1=array();
    $arr2=array();
    foreach ($result1 as $master)
    {
        $arr[$i]['aField']=$master['aField'];
        // 更多的外层赋值
        $j=0;
        foreach ($result2 as $detail)
        {
            $arr[$i][$j]['anotherField']=$detail['anotherField'];
            // 更多的内层赋值
            $j++;
        }
        $i++;
    }

    这样就可以完成两个循环变量的初始化,然后再用Smarty赋值给模板变量即可。 Smarty中的section是非常强大的循环控制语句。任何需要使用Smarty进行模板操作的人,必须掌握其语法。也许,它的唯一不足也在于此:对于一个MVC完全隔离,前端界面可能由根本不懂计算机编程的设计人员完成的前端来说,section的语法还是稍微复杂了一些。