2014年12月15日 星期一

Android Studio 下載、安裝與設定


以前要寫 Android App 必須同時安裝 Eclipse 和 Android SDK,不僅手續繁瑣而且又須耗費不少時間去安裝與設定,現在有了 Android Studio 之後一切都變簡單了。

Android Studio 套件包括有 Android Studio IDE、Android SDK tools、Android 5.0 (Lollipop) platfrom 和 Android 5.0 emulator system image with Google APIs。

官網 http://developer.android.com/


下載 Android Studio

1. 切換網頁到 http://developer.android.com/sdk/index.html,點按螢幕中間的「Download Android Studio」綠色按鈕。
2. 勾選同意條款後,再點按下方的「Download Android Studio」藍色按鈕。


安裝 Android Studio 

雙擊 android-studio-bundle-xxxx.exe,然後依照視窗提示安即可。

一些提示:
1. 在安裝過程中它會順便幫你安裝 Microsoft C++ 和 Java,此部分一樣請依照視窗指示安裝。
2. 它也會幫你建立一個安卓虛擬裝置(Android Virtul Device),這個安卓虛擬裝置就是一個手機模擬器,如果你沒有安卓手機,仍然可以利用這個虛擬裝置來設計 App。
3. 另外它還會幫你預設一個虛擬裝置驅動規劃。不同的手機需要不同的裝置驅動規劃,它目前預設的可能並未符合我們的需求,在下一階段中我將會告訴你如何規劃我們的裝置驅動。

安裝完成後的畫面如下:


安裝完後還不能保證您可以開始寫 App,還需要做一些設定才行。這些設定是在 Android Studio IDE 裏面進行的,所以我們要先進入 IDE,步驟如下:

1. 選取 Start a new Android Studio project 這個項目。
2. 然後一直點按 [Next] 鈕,最後按下 [Finish] 鈕,就會出現 Android Studio 的操作畫面。




設定 Android Studio

這兒有幾項工作要做:指定 JAVA 安裝路徑,安裝 Android SDK,規劃虛擬裝置驅動。

指定 Java 的安裝路徑,步驟如下:

1. 選擇  開始功能表 > 設定 > 控制台 > 系統  > 進階 > 環境變數。
2. 在下方的系統變數區塊內點擊 [新增] 鈕。
3. 在「變數名稱」內鍵入 JAVA_HOME,在「變數值」內鍵入 C:\Program Files\Java\jdk1.7.0_21(此處應該鍵入你電腦上的 JAVA 路徑),如圖



安裝 Android SDK

雖然最新版的 Android 系統功能最多,但由於它並未支援大多數的行動裝置,因此我們需要安裝較低版的 Android 作業系統,此處我們建議您安裝 Android 2.3.3 版。

1. 點擊操作介面下拉功能表 Tools > Android > SDK Manager,出現「Android SDK Manager」視窗。
2. 除了它自動幫您建議必須安裝的項目之外,我們還必須勾選「Android 2.3.3(API 10)」這個項目。
3. 點擊右下角落的「Install xx packages...」鈕。
4. 點擊右下角落的「Accept License」鈕,再點擊「Install」鈕。
這個步驟需要花費一點時間,請您耐心等候。如果安裝完之後發現「Install xx packages...」這個按鈕還是亮的(可被點擊),請持續這部分的安裝值到按鈕都變灰色不可按下。
5. 點擊右上角落的紅色叉叉,關閉「Android SDK Manager」。


虛擬裝置(AVD)的驅動規劃

為了模擬不同尺寸的手機或平板,我們需要為它們設置不同的驅動規劃。
如果您有實體手機或平板,可以略過此步驟。
事實上,我們不太建議您略過此步驟,畢竟有時候會在沒有實體裝置的情況下來執行 App。

1. 點擊操作介面下拉功能表 Tools > Android > AVD Manager,出現「Android AVD Manager」視窗。
2. 點擊視窗下方的「Create Virtual Device」鈕。
3. 在「Category」列表裏面選擇「手機(Phone)」或「平板(Tablet)」。此處我選的是「Phone」。
4. 在右側列表裏面選擇「3.2" QVGA(ADP2)」。這是一個320x480畫素的手機,選擇這個項目可以適用於大部分的手機。
5. 點擊視窗右下方的「Next」鈕。
6. 選擇「Gingerbread 10 armeabi Android 2.3.3」後按下「Next」鈕。
7. 在 AVD Name 欄位右側鍵入您的手機名稱,然後按下「Finish」鈕。此處我是鍵入「320x480」。
8. 點擊視窗右下方的「OK」鈕。


簡單測試是否可正確執行

到這個階段我們大致上都已完成安裝與設定,不過我們還是要來測試一下是否可以正確執行 AVD。

1. 點擊工具列圖示

2. 在 Android virtual device: 右側欄位選擇「320x480」這個項目(註A),如下圖:
3. 點擊「OK」鈕。
經過一段時間之後螢幕會出現一支手機,如下圖:


註A:

如果您有實體手機或平板,可以選擇實體裝置,這個實體裝置將會出現在列表之中。
安裝實體裝置的步驟如下:

1. 用USB線將它與電腦連接,首先安裝正確的USB驅動程式。
2. 然後執行手機桌面上的「設定(Settings)」程式,進入開發人員選項(Developer options)」 。
3. 將「USB debugging」設為「可用(Enable)」。


下一階段我會為您說明如何開始寫一個簡單的 App,請詳 http://pizgchen.blogspot.tw/2014/12/blog-post.html


2014年12月14日 星期日

開啟另一個活動(Activity)

開啟另一個活動(Activity)
原文詳 https://developer.android.com/training/basics/firstapp/starting-activity.html#BuildIntent


回應"Send"按鈕

1. 在 res/layout 路徑下編輯 activity_main.xml 檔案。
2. 在 <Button> 元素內加入 "android:onClick" 屬性。
activity_main.xml 內容看起來應如下:

<Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/button_send"
        android:onClick="sendMessage"/>

此 "android:onClick" 屬性的值 "sendMessage"它是一個方法(method),當使用者按下按鈕時會去執行這個方法。

3. 到 "java/com.example_xxx/myapplication1" 路徑下開啟 MainActivity.java。
4. 在 MainActivity 類別(class)下加入一個 "sendMessage()" 方法(method),如下所示:

 public void sendMessage(View view) {
        // Do something in response to button
 }

為了讓系統能配合這個方法,您必須符合如下規定:

1. 方法必須為全域(public)。
2. 需要有一個 void 的返回值。
3. 需要有一個 View 的參數。


建立一個意圖(Intent)

所謂"意圖(Intent)",就是在按下按鈕之後所要做的事。

1. 在 MainActivity.java 的 sendMessage() 方法內部建立一個意圖,在這兒我們要啟用另一個叫做 "DisplayMessageActivity" 的活動(Activity)。程式碼如下所示:

public void sendMessage(View view) {
        Intent intent = new Intent(this, DisplayMessageActivity.class);
}

注意:你會發現程式中出現紅色的文字,表示目前這兒有一些錯誤,這是因為我們目前尚未建立 "DisplayMessageActivity" 這個類別。目前您可以先忽視這個錯誤,稍後我們將會建立這個類別。

這個架構使用到兩個參數:

  • Context 作為 new Intent 的第一個參數(之所以使用 this 是因為 Context 的次類別是 Activity)。
  • App 的 Class 部件會用來驅動 Intent ,在這兒將會啟用一個 Activity。


2. 在檔案的頂端加入這一行

import android.content.Intent;

提示:同時按下<Alt>+<Enter>鍵可以自動匯入(import)遺失的類別(class)。

3. 在 sendMessage() 方法裏使用 findViewById 以取得 EditText 元件。
4. 在檔案的頂端加入這一行

import android.content.Intent;

你也可以同時按下<Alt>+<Enter>鍵自動匯入(import) EditText 類別。

5. 取得使用者輸入的內容,將值指定給區域變數 message。並且使用 putExtra() 方法將 message 這個值加到 Intent 裏。
MainActivity.java 內容看起來應如下:

public void sendMessage(View view) {
        Intent intent = new Intent(this, DisplayMessageActivity.class);
        EditText editText = (EditText) findViewById(R.id.edit_message);
        String message = editText.getText().toString();
        intent.putExtra(EXTRA_MESSAGE, message);
}

6. 在 MainActivity 類別的頂端加入 "EXTRA_MESSAGE"的定義,如下:

public class MainActivity extends ActionBarActivity {
    public final static String EXTRA_MESSAGE = "com.mycompany.myfirstapp.MESSAGE";
    ....

7. 在 sendMessage() 方法內呼叫 startActivity() 方法,把這個 Intent 傳送出去,如下:

public void sendMessage(View view) {
        Intent intent = new Intent(this, DisplayMessageActivity.class);
        EditText editText = (EditText) findViewById(R.id.edit_message);
        String message = editText.getText().toString();
        intent.putExtra(EXTRA_MESSAGE, message);
        startActivity(intent);
}

系統接收到這個呼叫之後,會開始一個 Intent 指定的 Activity 實例,現在你需要去建立一個 DisplayMessageActivity 類別,為了這事來工作。


建立第二個活動(Activity)

所有的 Activity 次類別都必須實作 onCreate()方法,可以使用這個方法來接收 Intent 傳遞過來的資訊,同時必須在 onCreate() 方法內使用 setContentView() 方法來激活佈局,

使用 Android Studio 建立一個新的活動(Activity)

1. 在 Android Studio 的 java 路徑下選擇 com.example.myapplication1,按下滑鼠右鍵並選取 New > Activity > Blank Activity
2. 在 選擇視窗內填入下列資料:

Activity Name = DisplayMessageActivity
Layout Name = activity_display_message
Title = DisplayMessageActivity
Hierarchical Parent = com.example.myapplication1.MainActivity
Package name = com.example.john.myapplication1

按一下 [Finish] 鍵。

3. 雙擊 DisplayMessageActivity 開啟程式碼視窗。

4. 移除 onCreateOptionsMenu() 方法。


建立活動

1. 在 src/ 路徑下建立一個新檔案 DisplayMessageActivity.java,


3. 到 strings.xml 內加入這一行

<string name="title_activity_display_message">My Message</string>

4. 雙擊 manifests 在 <Application> 裏面為 DisplayMessageActivity 這個類別加入 <activity> 宣告,如下:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.john.myapplication1" >

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".DisplayMessageActivity"
            android:label="@string/title_activity_display_message"
            android:parentActivityName=".MainActivity" >
            <meta-data
                android:name="android.support.PARENT_ACTIVITY"
                android:value="com.example.john.myapplication1.MainActivity" />
        </activity>
    </application>

</manifest>


接收意圖

1. 編輯 DisplayMessageActivity.java 檔案。
2. 移除 onCreate() 方法裏面的這一行

setContentView(R.layout.activity_display_message);

3. 取得意圖,並將他指定給 intent 區域變數。

Intent intent = getIntent();

4. 在檔案的頂端加入這一行

import android.content.Intent;

你也可以同時按下<Alt>+<Enter>鍵自動匯入(import) EditText 類別。

5. 使用 getStringExtra() 方法萃取從 MyActivity 傳遞過來的訊息。

String message = intent.getStringExtra(MainActivity.EXTRA_MESSAGE);


顯示訊息

1. 在 onCreate() 方法內建立 TextView 物件。

 TextView textView = new TextView(this);

2. 使用 setText() 方法設定文字大小和內容。

textView.setTextSize(40);
textView.setText(message);

3. 利用 setContentView() 方法將 textView 傳送到最底層的活動佈局裏。
4. 在檔案的最頂端加入

import android.widget.TextView;

完整的 onCreatet() 方法程式碼如下:

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Get the message from the intent
        Intent intent = getIntent();
        String message = intent.getStringExtra(MainActivity.EXTRA_MESSAGE);

        // Create the text view
        TextView textView = new TextView(this);
        textView.setTextSize(40);
        textView.setText(message);

        // Set the text view as the activity layout
        setContentView(textView);
}


現在你可以執行這個 App 了,畫面如下:



















建立簡單的使用者介面

Android Studio - 建立簡單的使用者介面
原文詳 https://developer.android.com/training/basics/firstapp/building-ui.html

建立 Linear Layout (線性布局)

線性布局(Linear Layout)有水平(horizontal) 和垂直(vertical)兩種型式。


1. 在 Android Studio 裏切換到 res/layout 路徑,開啟 activity_main.xml 檔案。
2. 在 預覽面板(Preview)裏,點按  關閉預覽。
3. 刪除 <TextView> 元素。
4. 將 <RelativeLayout> 變更為 <LinearLayout>。
5. 加入 android:orientation 屬性將畫面設置為水平。
6. 移除 android:padding 屬性並加入 tools:context 屬性。
res/layout/activity_mail.xml 內容看起來應如下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal">

</LinearLayout>


加入文字欄位

1. 在 activity_main.xml 檔案的 <LinearLayout> 裏面定義一個 <Edittext> 元素,並將
它的 ID 屬性設為 @ + ID / edit_message 
2. 將 layout:width 和 layout_height 屬性的值設為 warp_content。
3. 將 hint 的屬性值設為 edit_message 的 string 物件。
<EditText>元素內容看起來應如下:

<EditText android:id="@+id/edit_message"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:hint="@string/edit_message" />

你應該可以注意到有紅色的文字出現,這表示該行有錯誤。
底下我們要來修訂這個錯誤。


加入 String 資源

預設情況下,專案包含有一個 res/values/string.xml 資源,我們將會在這兒增加一個 "edit_message" 的項目,並將它的值設為 "Edit a message"。

1. 在 res/values 路徑下開啟 strings.xml。
2. 加入 "edit_message" 這一行,並將它的值設為 "Edit a message"。
3. 加入 "button_send" 這一行,並將它的值設為 "Send"。這個東西是作為我們下一階段給按鈕元件使用的。
4. 移除 "hello world" 文字。
strings.xml 內容看起來應如下:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">My Application1</string>
    <string name="action_settings">Settings</string>
    <string name="edit_message">Edit a message</string>
    <string name="button_send">Send</string>
</resources>


加入一個按鈕

1. 在 res/layout 路徑下編輯 activity_main.xml。
2. 在 <LinearLayout> 內部的 <EditText> 下方加入一個按鈕元素 <Button>。
3. 設定按鈕的 "width" 和 "height" 屬性值為 "warp_content"。
4. 將按鈕的文字標籤屬性 :androis:text 設為 string 資源裏的 "button_send"。
activity_main.xml 內容看起來應如下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal">

    <EditText android:id="@+id/edit_message"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:hint="@string/edit_message" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/button_send" />
</LinearLayout>

注意: 這個按鈕並不需要一個 android:id 屬性,因為它不會被其他介面所參考。

目前這個佈局包刮了一個 EditText 元件和 Button 元件,如下所示:


目前雖然這個按鈕可以正常運作,但由於使用者可能在會在輸入盒(EditText)裏鍵入過長的文字,所以我們可以透過指定這個元件的 weight (權重),來重新分配 "EditText" 和 "Button" 所佔用的比例。

所有工具元件權重的預設值都是 0,如果你指定大於 0 的值,你就可以看到元件佔據該空間的比例。


讓輸入盒(EditText)充滿螢幕寬度

1. 將 <EditText> 的 "layout_weight" 屬性設為 1。
2. 同時將 <EditText> 的 "layout_width" 屬性設為 0dp。
activity_main.xml 內容看起來應如下:

....
<EditText android:id="@+id/edit_message"
        android:layout_weight="1"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:hint="@string/edit_message"/>
....

切換到 Display 頁籤,你可以看到目前這個佈局外觀變更了,如下所示:


所以, activity_main.xml 最終內容看起來應如下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal">

    <EditText android:id="@+id/edit_message"
        android:layout_weight="1"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:hint="@string/edit_message"/>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/button_send" />
</LinearLayout>


執行這個 APP

點按  這個工具列按鈕,執行我們上面所建立的 APP。


在下一個階段,我會告訴您如何回應按鈕的動作,去取得使用者輸入的內容,並開啟另一個活動(Activity),詳 http://pizgchen.blogspot.tw/2014/12/activity.html。

2014年11月20日 星期四

瞭解 Arduino 的記憶體

記憶體的管控對 Arduino UNO來說是一件非常重要的事。

Arduino 板子上面有三種記憶體:Flash、SRAM 和 EEPROM。

Flash 記憶體是用來儲存你的程式的。Arduino UNO 有 32k 的 Flash 記憶體,但因為 5k 被 bootloader 用掉了,所以你大約只能寫 27k 左右的程式。

SRAM 記憶體是被程式用來隨機存取資料,它只有 2k 的空間。這個會關係到程式中變數的可使用量。

EEPROM 記憶體是用來儲存斷電後也不會遺失的資料,它只有 1k 的空間。

這裏要提醒您,SRAM 的空間其實不大,在您使用字串變數時將會耗用大量的 SRAM 記憶體空間。

官網 http://arduino.cc/en/Tutorial/Memory





瞭解變數占用的記憶體大小

Arduino 的記憶體空間非常寶貴,Arduino 也不擅長處理大量的資料,因此為變數宣告合適的資料型態,盡量節省記憶體空間,將可以提高程式的執行效率。

在 Arduino UNO 裏宣告 int 會占用 16bit(2byte),若是在 Arduino Due 裏宣告 int 則會占用 32bit(4byte)。

如果使用 uint8_t 來宣告變數,只會占用 8bit(1byte),雖然 Arduino 沒有提到 uint8_t 也可以用來宣告變數,但因為 Arduino 是走 C 家族的編譯環境,而 uint8_t 就是 C 家族合法的資料型態,因此您可以放心地使用 unint8_t 來宣告變數,如此可以節省不少記憶體空間。

底下有一個程式可以列出資料型態所占用的記憶體空間是多少:


範例程式:

// Arduino DatatypeSize v2 - Display information about data types used in Arduino
// Created by Michael 'TeX' Hex - http://www.texhex.info/
//
// Full list of all data types:
// http://arduino.cc/en/Reference/HomePage -> Section "Data Types"
//
// Additonal references:
// http://www.arduino.cc/playground/Code/DatatypePractices
// http://arduino.cc/en/Reference/VariableDeclaration
//
// Any text in this sketch is taken from the Arduino homepage,
// licensed under a Creative Commons Attribution-ShareAlike 3.0 License.
//


void setup() {  
  Serial.begin(9600);
}

void loop() {
 Serial.println("--- Variable type: Size in SRAM (bytes) ---");


 // C standard data type "unsigned int length 8 bits".
 // Occupies one byte of memory.
 // http://arduino.cc/forum/index.php/topic,41590.0.html
 // http://en.wikipedia.org/wiki/Stdint.h#Fixed_width_integer_types
 Serial.print("uint8_t: ");
 Serial.println(sizeof(uint8_t));

 // A boolean holds one of two values, true or false.
 // Each boolean variable occupies one byte of memory.
 // http://arduino.cc/en/Reference/BooleanVariables
 Serial.print("boolean: ");
 Serial.println(sizeof(boolean));

 // A data type that takes up 1 byte of memory that stores a character value.
 // Character literals are written in single quotes, like this: 'A' (for multiple
 // characters - strings - use double quotes: "ABC").
 // http://arduino.cc/en/Reference/Char
 Serial.print("char: ");
 Serial.println(sizeof(char));

 // An unsigned data type that occupies 1 byte of memory. Same as the byte datatype.
 // The unsigned char datatype encodes numbers from 0 to 255.
 // For consistency of Arduino programming style, the byte data type is to be preferred.
 // http://arduino.cc/en/Reference/UnsignedChar
 Serial.print("unsigned char: ");
 Serial.println(sizeof(unsigned char));

 // A byte stores an 8-bit unsigned number, from 0 to 255.
 // http://arduino.cc/en/Reference/Byte
 Serial.print("byte: ");
 Serial.println(sizeof(byte));

 // Integers are your primary datatype for number storage, and store a 2 byte value.
 // This yields a range of -32,768 to 32,767 (minimum value of -2^15 and a maximum value of (2^15) - 1).
 // http://arduino.cc/en/Reference/Int
 Serial.print("int: ");
 Serial.println(sizeof(int));

 // Unsigned ints (unsigned integers) are the same as ints in that they store a 2 byte value.
 // Instead of storing negative numbers however they only store positive values, yielding a
 // useful range of 0 to 65,535 (2^16) - 1).
 // http://arduino.cc/en/Reference/UnsignedInt
 Serial.print("unsigned int: ");
 Serial.println(sizeof(unsigned int));

 // A word stores a 16-bit unsigned number, from 0 to 65535.
 // Same as an unsigned int.
 // http://arduino.cc/en/Reference/Word
 Serial.print("word: ");
 Serial.println(sizeof(word));

 // Long variables are extended size variables for number storage, and store 32 bits (4 bytes),
 // from -2,147,483,648 to 2,147,483,647.
 // http://arduino.cc/en/Reference/Long
 Serial.print("long: ");
 Serial.println(sizeof(long));

 // Unsigned long variables are extended size variables for number storage, and store 32 bits (4 bytes).
 // Unlike standard longs unsigned longs won't store negative numbers, making their range from 0
 // to 4,294,967,295 (2^32 - 1).
 // http://arduino.cc/en/Reference/UnsignedLong
 Serial.print("unsigned long: ");
 Serial.println(sizeof(unsigned long));

 // Datatype for floating-point numbers, a number that has a decimal point.
 // Floating-point numbers can be as large as 3.4028235E+38 and as low as -3.4028235E+38.
 // They are stored as 32 bits (4 bytes) of information.
 // http://arduino.cc/en/Reference/Float
 Serial.print("float: ");
 Serial.println(sizeof(float));

 // Double precision floating point number. Occupies 4 bytes.
 // The double implementation on the Arduino is currently exactly the same as the float,
 // with no gain in precision.
 // http://arduino.cc/en/Reference/Double
 Serial.print("double: ");
 Serial.println(sizeof(double));

 delay(8500);
}

顯示結果:

--- Variable type: Size in SRAM (bytes) ---
uint8_t: 1
boolean: 1
char: 1
unsigned char: 1
byte: 1
int: 2
unsigned int: 2
word: 2
long: 4
unsigned long: 4
float: 4
double: 4


參考資料:

1. Arduino 官網  http://arduino.cc/en/Reference/int
2. Sparkfun https://learn.sparkfun.com/tutorials/data-types-in-arduino





2014年11月10日 星期一

CodeBlocks - Arduino IDE

CodeBlocks 可以作為 Arduino 的程式編寫器。事實上,您也可以它來編寫其他微處理器的程式。

cbarduino

官網 http://arduinodev.com/codeblocks/


下載 https://sourceforge.net/projects/arduinodev/files/






2014年10月9日 星期四

啟動 Boa Constructor 時出現「AttributeError: 'module' object has no attribute 'NO_3D'」錯誤的解決方案

無法順利啟動 Boa Constructor 除了是 Python 、wxPython 和 Boa Constructor 這三者的版本匹配有問題之外,另外一個問題就是會出現「AttributeError: 'module' object has no attribute 'NO_3D'」這樣的錯誤訊息,這個應該是 Boa Constructor 本身的 Bug,原因是它無法對 wx.NO_3D 這個變數做解析。

解決的方法是到 Boa Constructor 資料夾內逐一對每一個 .py 程式檔找出有 wx.NO_3D 的文字將它用 wx.DEFAULT_FRAME_STYLE 來置換掉。

可能有wx.NO_3D 文字的程式如下:

boa.py
Preferences.py
prefs.rc.py


要注意的是千萬別使用編輯器(不管您使用的是何種編輯器)的置換功能,因為 Boa Constructor 的眾多程式當中有些程式碼使用到字典,例如:

style = {'wx.NO_3D': wx.NO_3D, ....}

此時你應該把值置換掉即可,如下:

style = {'wx.NO_3D': wx.DEFAULT_FRAME_STYLE, ....}


我的方法

我是使用 pyScripter 編輯器打開 Boa.py 然後執行它,在執行的過程當中若有出現錯誤,pyScripter 會將有問題的程式檔案開啟並標註錯誤的位置,此時就可以很容易找到 wx.NO_3D 的位置,於是您就可以用 wx.DEFAULT_FRAME_STYLE 置換它。






2014年9月22日 星期一

安裝 ConfigObj

ConfigObj Library 可以幫您很容易存取 .ini 檔。

官網 https://pypi.python.org/pypi/configobj



下載

切換網頁到 https://pypi.python.org/pypi/configobj/5.0.6,點擊「Download」綠色按鈕。


安裝

解壓縮 configobj-5.0.6.tar.gz,開啟「命令提示字元」視窗,鍵入

cd \configobj-5.0.6

再鍵入

python setup.py install


參考網站

http://www.voidspace.org.uk/python/configobj.html#configobj-in-the-real-world









2014年9月19日 星期五

安裝 kivy - python for android

從現在起,您可以在 KIVY 架構下使用 Python 語言建立 Android App 了。
官網 http://kivy.org/#home


下載

https://github.com/kivy/python-for-android


教學影片

https://www.youtube.com/watch?v=F7UKmK9eQLY







2014年9月14日 星期日

將 Youtube 影片轉成音樂檔

步驟如下:

1. 先找到 youtube 影片。

2. 複製該影片的網址。

3. 切換網頁到 http://www.youtube-mp3.org/

4. 將影片網址貼到這兒。


5. 點擊「Convert Video」按鈕。
經過一會兒會出現類似下列畫面



6. 點擊藍色的「Download」按鈕。

2014年9月13日 星期六

安裝 wxGlade

wxGlade 是一個利用 wxPython 工具箱製作而成的使用者圖形介面建構器。目前,它也可以產生 Python、C + +、Perl、Lisp 和 XRC(wxWidgets的“XML資源)的使用者圖形介面代碼。

官網 http://wxglade.sourceforge.net/


下載

切換網頁到 http://sourceforge.net/projects/wxglade/,點擊螢幕中央的「Download」綠色按鈕。


安裝

雙擊 wxGlade-SAE-0.6.8-setup.exe,然後依照視窗指示進行即可。


教學

官網 http://wxglade.sourceforge.net/tutorial.php

程式語言教學誌 http://pydoing.blogspot.tw/2009/01/docsdemowxglade.html










2014年9月12日 星期五

Wyliodrin

Wyliodrin - 視覺化的樹莓派整合發展環境

官網 https://www.wyliodrin.com/


教學影片

Program Raspberry Pi Lesson 1: Switch a LED on and off by using a web browser

https://www.youtube.com/watch?v=YWLwUdkdWVE


Program Raspberry Pi Lesson 2: Show the likes from a Facebook page on two 7-segment displays

https://www.youtube.com/watch?v=qLnDilQtAzM


Program Raspberry Pi Lesson 3: Display sensor values on graphs.

https://www.youtube.com/watch?v=1K97q-Md7sA


Program Intel Galileo Gen 2 Lesson 4: Show sensors' value

https://www.youtube.com/watch?v=PapUdght_po&list=UUDe4G1RXRYsOEJzXHixutRA


Program Intel Galileo Gen 2 Lesson 5: Turn on/off the light with a relay and a light sensor

https://www.youtube.com/watch?v=PziZTtdeH5k&list=UUDe4G1RXRYsOEJzXHixutRA

安裝 Win32 Extensions

Win32 Extensions 提供一些讓您存取 Windows 作業系統的功能,例如讀取磁碟機資訊...等。
官網 http://starship.python.net/crew/mhammond/


下載

切換網頁到 http://sourceforge.net/projects/pywin32/files/pywin32/Build%20219/,點擊 pywin32-219.win32-py3.5.exe 。


安裝

雙擊  pywin32-219.win32-py3.5.exe ,然後依照視窗內的指示安裝即可。






2014年9月9日 星期二

安裝 PyKE

PyKE(Python Knowledge Engine) 是一個知識引擎套件,無論是正向鏈接或反向鏈規則(包括Python代碼)都可以被編譯成 Python,還可以自動組合成 Python 函數以外的程式,並且附加到反向鏈規則之中。

官網 http://pyke.sourceforge.net/


下載

切換網頁到 http://sourceforge.net/projects/pyke/?source=typ_redirect,點擊螢幕中央的「Download」綠色按鈕。


安裝

將 pyke-1.1.1.zip 解壓縮,開啟「命令列提示視窗」,鍵入 python setup.py install。










2014年9月4日 星期四

安裝 Visual Tkinter Python IDE

這是一個視覺化的整合操作環境,您可以用它來建立圖形化的使用者介面。


下載

切換至網頁 http://sourceforge.net/projects/visualtkinter/,點擊畫面中央的「Download」綠色按鈕。


安裝

解壓縮 Visual Python 2v0.12.2554.zip,雙擊 setup.exe,然後依照視窗指示進行即可。
安裝完成後會在桌面產生一個捷徑圖示,如下圖:


雙擊捷徑您就可以看到 Visual Tkinter 的整合介面,如下圖:









安裝 PythonCard

PythonCard 是一個以 wxPython 為基礎的使用者介面建構器。

官網 http://pythoncard.sourceforge.net/index.html


下載

切換網頁至 http://sourceforge.net/projects/pythoncard/files/,然後點擊淡藍色的 Download PythonCard-0.8.2.win32.exe (3.5 MB) 字樣。


安裝

快擊兩下 PythonCard-0.8.2.win32.exe,然後依照視窗指示安裝即可。


檢查是否已正確安裝

開啟範例檔案 <Python>\Lib\site-packages\PythonCard\samples\minimal\minimal.py 並執行它,如果有看到如下視窗表示已正確安裝。




查看所有的視窗工具

開啟範例檔案 <Python>\Lib\site-packages\PythonCard\samples\widgets\widgets.py 並執行它,您將可以看到如下視窗。


或是您也可以到這兒逐一檢視視窗工具有哪些:

http://pythoncard.sourceforge.net/samples/addresses.html

2014年9月2日 星期二

註解

註解是不會被執行的,為代碼加註說明是一件好的習慣,這些註解能夠讓您的程式更容易閱讀和維護。


單行註解

假設您有如下之代碼:

a = 5
b = 2
c = a + b
print c

您想把 c = a + b 這一行改成 c = a - b,但又不想把  c = a + b 這一行刪除掉,則您可以在該行前面加一個「 #」字元,如下:

a = 5
b = 2
#c = a + b
c = a - b
print c


註解區塊

假設您有如下之代碼:

a = 5
b = 2
print a + b
print a - b
print a * b
print a / b

而您想把一整個區塊的代碼做註解,則您可以在該區塊首尾各加一個「'''」字元,如下:

a = 5
b = 2
'''
print a + b
print a - b
print a * b
'''
print a / b




2014年9月1日 星期一

Python-Arduino-Command-API

Python-Arduino-Command-API 提供您另外一種方式讓 Python 與 Arduino 通訊。


下載

切換網頁到 https://github.com/thearn/Python-Arduino-Command-API,點擊右下角落的 Download ZIP 按鈕。


安裝

下載後解壓縮,然後開啟「命令提示字元」視窗,切換到你解壓縮後的路徑,鍵入

        python setup.py build install


範例

讓 Arduino 的 pin13 LED 閃爍。

Python Code

#!/usr/bin/env python
"""
 Blinks an LED on digital pin 13
 in 1 second intervals
"""

from Arduino import Arduino
import time

board = Arduino('9600') #plugged in via USB, serial com at rate 9600

while True:
    board.digitalWrite(13, "LOW")
    time.sleep(1)
    board.digitalWrite(13, "HIGH")
    time.sleep(1)

Arduino Code

#include <SoftwareSerial.h>
#include <Wire.h>
#include <Servo.h>
#include <EEPROM.h>

SoftwareSerial *sserial = NULL;
Servo servos[8];
int servo_pins[] = {0, 0, 0, 0, 0, 0, 0, 0};
boolean connected = false;

int Str2int (String Str_value)
{
  char buffer[10]; //max length is three units
  Str_value.toCharArray(buffer, 10);
  int int_value = atoi(buffer);
  return int_value;
}

void split(String results[], int len, String input, char spChar) {
  String temp = input;
  for (int i=0; i<len; i++) {
    int idx = temp.indexOf(spChar);
    results[i] = temp.substring(0,idx);
    temp = temp.substring(idx+1);
  }
}

void Version(){
  Serial.println("version");
}

uint8_t readCapacitivePin(String data) {
  int pinToMeasure = Str2int(data);
  // readCapacitivePin
  //  Input: Arduino pin number
  //  Output: A number, from 0 to 17 expressing
  //  how much capacitance is on the pin
  //  When you touch the pin, or whatever you have
  //  attached to it, the number will get higher
  //  http://playground.arduino.cc/Code/CapacitiveSensor
  //
  // Variables used to translate from Arduino to AVR pin naming
  volatile uint8_t* port;
  volatile uint8_t* ddr;
  volatile uint8_t* pin;
  // Here we translate the input pin number from
  //  Arduino pin number to the AVR PORT, PIN, DDR,
  //  and which bit of those registers we care about.
  byte bitmask;
  port = portOutputRegister(digitalPinToPort(pinToMeasure));
  ddr = portModeRegister(digitalPinToPort(pinToMeasure));
  bitmask = digitalPinToBitMask(pinToMeasure);
  pin = portInputRegister(digitalPinToPort(pinToMeasure));
  // Discharge the pin first by setting it low and output
  *port &= ~(bitmask);
  *ddr  |= bitmask;
  delay(1);
  // Make the pin an input with the internal pull-up on
  *ddr &= ~(bitmask);
  *port |= bitmask;

  // Now see how long the pin to get pulled up. This manual unrolling of the loop
  // decreases the number of hardware cycles between each read of the pin,
  // thus increasing sensitivity.
  uint8_t cycles = 17;
       if (*pin & bitmask) { cycles =  0;}
  else if (*pin & bitmask) { cycles =  1;}
  else if (*pin & bitmask) { cycles =  2;}
  else if (*pin & bitmask) { cycles =  3;}
  else if (*pin & bitmask) { cycles =  4;}
  else if (*pin & bitmask) { cycles =  5;}
  else if (*pin & bitmask) { cycles =  6;}
  else if (*pin & bitmask) { cycles =  7;}
  else if (*pin & bitmask) { cycles =  8;}
  else if (*pin & bitmask) { cycles =  9;}
  else if (*pin & bitmask) { cycles = 10;}
  else if (*pin & bitmask) { cycles = 11;}
  else if (*pin & bitmask) { cycles = 12;}
  else if (*pin & bitmask) { cycles = 13;}
  else if (*pin & bitmask) { cycles = 14;}
  else if (*pin & bitmask) { cycles = 15;}
  else if (*pin & bitmask) { cycles = 16;}

  // Discharge the pin again by setting it low and output
  //  It's important to leave the pins low if you want to 
  //  be able to touch more than 1 sensor at a time - if
  //  the sensor is left pulled high, when you touch
  //  two sensors, your body will transfer the charge between
  //  sensors.
  *port &= ~(bitmask);
  *ddr  |= bitmask;

  //return cycles;
  Serial.println(cycles);
}

void Tone(String data){
  int idx = data.indexOf('%');
  int len = Str2int(data.substring(0,idx));
  String data2 = data.substring(idx+1);
  int idx2 = data2.indexOf('%');
  int pin = Str2int(data2.substring(0,idx2));
  String data3 = data2.substring(idx2+1);
  String melody[len*2];
  split(melody,len*2,data3,'%');

  for (int thisNote = 0; thisNote < len; thisNote++) {
    int noteDuration = 1000/Str2int(melody[thisNote+len]);
    int note = Str2int(melody[thisNote]);
    tone(pin, note, noteDuration);
    int pause = noteDuration * 1.30;
    delay(pause);
    noTone(pin);
  }
} 

void ToneNo(String data){
  int pin = Str2int(data);
  noTone(pin);
} 

void DigitalHandler(int mode, String data){
      int pin = Str2int(data);
    if(mode<=0){ //read
        Serial.println(digitalRead(pin));
    }else{
        if(pin <0){
            digitalWrite(-pin,LOW);
        }else{
            digitalWrite(pin,HIGH);
        }
        //Serial.println('0');
    }
}

void AnalogHandler(int mode, String data){
     if(mode<=0){ //read
        int pin = Str2int(data);
        Serial.println(analogRead(pin));
    }else{
        String sdata[2];
        split(sdata,2,data,'%');
        int pin = Str2int(sdata[0]);
        int pv = Str2int(sdata[1]);
        analogWrite(pin,pv);
    }
}

void ConfigurePinHandler(String data){
    int pin = Str2int(data);
    if(pin <=0){
        pinMode(-pin,INPUT);
    }else{
        pinMode(pin,OUTPUT);
    }
}

void shiftOutHandler(String data) {    
    String sdata[4];
    split(sdata, 4, data, '%');
    int dataPin = sdata[0].toInt();
    int clockPin = sdata[1].toInt();
    String bitOrderName = sdata[2];
    byte value = (byte)(sdata[3].toInt());
    if (bitOrderName == "MSBFIRST") {
       shiftOut(dataPin, clockPin, MSBFIRST, value);
    } else {
       shiftOut(dataPin, clockPin, LSBFIRST, value);
    }
}

void shiftInHandler(String data) {
    String sdata[3];
    split(sdata, 3, data, '%');
    int dataPin = sdata[0].toInt();
    int clockPin = sdata[1].toInt();
    String bitOrderName = sdata[2];
    int incoming;
    if (bitOrderName == "MSBFIRST") {
       incoming = (int)shiftIn(dataPin, clockPin, MSBFIRST);
    } else {
       incoming = (int)shiftIn(dataPin, clockPin, LSBFIRST);
    }
    Serial.println(incoming);
}

void SS_set(String data){
  delete sserial;
  String sdata[3];
  split(sdata,3,data,'%');
  int rx_ = Str2int(sdata[0]);
  int tx_ = Str2int(sdata[1]);
  int baud_ = Str2int(sdata[2]);
  sserial = new SoftwareSerial(rx_, tx_);
  sserial->begin(baud_);
  Serial.println("ss OK");
}

void SS_write(String data) {
 int len = data.length()+1;
 char buffer[len];
 data.toCharArray(buffer,len);
 Serial.println("ss OK");
 sserial->write(buffer); 
}
void SS_read(String data) {
 char c = sserial->read(); 
 Serial.println(c);
}

void pulseInHandler(String data){
    int pin = Str2int(data);
    long duration;
    if(pin <=0){
          pinMode(-pin, INPUT);
          duration = pulseIn(-pin, LOW);      
    }else{
          pinMode(pin, INPUT);
          duration = pulseIn(pin, HIGH);      
    }
    Serial.println(duration);
}

void pulseInSHandler(String data){
    int pin = Str2int(data);
    long duration;
    if(pin <=0){
          pinMode(-pin, OUTPUT);
          digitalWrite(-pin, HIGH);
          delayMicroseconds(2);
          digitalWrite(-pin, LOW);
          delayMicroseconds(5);
          digitalWrite(-pin, HIGH);
          pinMode(-pin, INPUT);
          duration = pulseIn(-pin, LOW);      
    }else{
          pinMode(pin, OUTPUT);
          digitalWrite(pin, LOW);
          delayMicroseconds(2);
          digitalWrite(pin, HIGH);
          delayMicroseconds(5);
          digitalWrite(pin, LOW);
          pinMode(pin, INPUT);
          duration = pulseIn(pin, HIGH);      
    }
    Serial.println(duration);
}

void SV_add(String data) {
    String sdata[3];
    split(sdata,3,data,'%');
    int pin = Str2int(sdata[0]);
    int min = Str2int(sdata[1]);
    int max = Str2int(sdata[2]);
    int pos = -1;
    for (int i = 0; i<8;i++) {
        if (servo_pins[i] == pin) { //reset in place
            servos[pos].detach();
            servos[pos].attach(pin, min, max);
            servo_pins[pos] = pin;
            Serial.println(pos);
            return;
            }
        }
    for (int i = 0; i<8;i++) {
        if (servo_pins[i] == 0) {pos = i;break;} // find spot in servo array
        }
    if (pos == -1) {;} //no array position available!
    else {
        servos[pos].attach(pin, min, max);
        servo_pins[pos] = pin;
        Serial.println(pos);
        }
}

void SV_remove(String data) {
    int pos = Str2int(data);
    servos[pos].detach();
    servo_pins[pos] = 0;
}

void SV_read(String data) {
    int pos = Str2int(data);
    int angle;
    angle = servos[pos].read();
    Serial.println(angle);
}

void SV_write(String data) {
    String sdata[2];
    split(sdata,2,data,'%');
    int pos = Str2int(sdata[0]);
    int angle = Str2int(sdata[1]);
    servos[pos].write(angle);
}

void SV_write_ms(String data) {
    String sdata[2];
    split(sdata,2,data,'%');
    int pos = Str2int(sdata[0]);
    int uS = Str2int(sdata[1]);
    servos[pos].writeMicroseconds(uS);
}

void sizeEEPROM() {
    Serial.println(E2END + 1);
}

void EEPROMHandler(int mode, String data) {
    String sdata[2];
    split(sdata, 2, data, '%');
    if (mode == 0) {  
        EEPROM.write(Str2int(sdata[0]), Str2int(sdata[1]));  
    } else {
        Serial.println(EEPROM.read(Str2int(sdata[0])));
    }
}

void SerialParser(void) {
  char readChar[64];
  Serial.readBytesUntil(33,readChar,64);
  String read_ = String(readChar);
  //Serial.println(readChar);
  int idx1 = read_.indexOf('%');
  int idx2 = read_.indexOf('$');
  // separate command from associated data
  String cmd = read_.substring(1,idx1);
  String data = read_.substring(idx1+1,idx2);
  
  // determine command sent
  if (cmd == "dw") {
      DigitalHandler(1, data);   
  }
  else if (cmd == "dr") {
      DigitalHandler(0, data);   
  }  
  else if (cmd == "aw") {
      AnalogHandler(1, data);   
  }    
  else if (cmd == "ar") {
      AnalogHandler(0, data);   
  }      
  else if (cmd == "pm") {
      ConfigurePinHandler(data);   
  }    
  else if (cmd == "ps") {
      pulseInSHandler(data);   
  }    
  else if (cmd == "pi") {
      pulseInHandler(data);   
  }        
  else if (cmd == "ss") {
      SS_set(data);   
  }
  else if (cmd == "sw") {
      SS_write(data);   
  }
  else if (cmd == "sr") {
      SS_read(data);   
  }    
  else if (cmd == "sva") {
      SV_add(data);   
  }      
  else if (cmd == "svr") {
      SV_read(data);   
  }   
 else if (cmd == "svw") {
      SV_write(data);   
  }    
 else if (cmd == "svwm") {
      SV_write_ms(data);   
  }      
  else if (cmd == "svd") {
      SV_remove(data);   
  } 
  else if (cmd == "version") {
      Version();   
  }
  else if (cmd == "to") {
      Tone(data);   
  } 
  else if (cmd == "nto") {
      ToneNo(data);   
  }  
  else if (cmd == "cap") {
      readCapacitivePin(data);   
  }
  else if (cmd == "so") {
      shiftOutHandler(data);
  }
  else if (cmd == "si") {
      shiftInHandler(data);
  }
  else if (cmd == "eewr") {
      EEPROMHandler(0, data);   
  } 
  else if (cmd == "eer") {
      EEPROMHandler(1, data);   
  }  
  else if (cmd == "sz") {  
      sizeEEPROM();
  }  
}

void setup()  {
  Serial.begin(9600); 
    while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }
}

void loop() {
   SerialParser();
}










the Micro Python board


Micro Python 控制板是由劍橋大學理論物理學家喬治·達米安(Damien George)所研發出來的, 它比 Arduino 更強大,比 Raspberry PI 更簡易,你只要將 Python 的程式貼到控制板內即可。

它提供一個 USB 接口,可以讓您連接電腦,因為它是屬於跨平台的,所以 Windows、Mac 或 Linux 作業系統都可以使用。

原文詳 http://www.wired.co.uk/news/archive/2013-12/06/micro-python







安裝 MySQL for Python

如果您想有計畫地處理大量資料,我想您需要一個資料庫軟體來處理這件事情,而 MySQL 就是最佳的選擇之一。

目前 MySQL 為 3.23 版,支援 Python 2.4~2.7 版,未來才會支援 Python 3.x 版。


下載

切換到下載頁 http://sourceforge.net/projects/mysql-python/?source=dlp,點擊綠色的 Download 按鈕。


安裝

雙擊 MySQL-python-1.2.4b4.win32-py2.7.exe,然後依照視窗內的指示進行安裝。


首先用 MySQL 建立一個含有溫濕度數據的氣象資料表,如下:

create table weatherData (
    weatherDataID int(11) AUTO_INCREMENT NOT NULL,
    humidity decimal(4,2) NOT NULL,
    tempC decimal(4,2) NOT NULL,
    constraint weatherData_PK primary key (weatherDataID)
);



Python Code

#!/usr/bin/python

import serial
import MySQLdb

#establish connection to MySQL. You'll have to change this for your database.
dbConn = MySQLdb.connect("localhost","database_username","password","database_name") or die ("could not connect to database")
#open a cursor to the database
cursor = dbConn.cursor()

device = 'COM5' #this will have to be changed to the serial port you are using
try:
  print "Trying...",device
  arduino = serial.Serial(device, 9600)
except:
  print "Failed to connect on",device

try:
  data = arduino.readline()  #read the data from the arduino
  pieces = data.split("\t")  #split the data by the tab
  #Here we are going to insert the data into the Database
  try:
    cursor.execute("INSERT INTO weatherData (humidity,tempC) VALUES (%s,%s)", (pieces[0],pieces[1]))
    dbConn.commit() #commit the insert
    cursor.close()  #close the cursor
  except MySQLdb.IntegrityError:
    print "failed to insert data"
  finally:
    cursor.close()  #close just incase it failed
except:
  print "Failed to get data from Arduino!"


uint8_t 是甚麼?

uint8_t 在 Arduino 裏相當於 byte。維基百科頁面 Stdint.h (http://en.wikipedia.org/wiki/Stdint.h) 有更多的信息。

基本上 Stdint.h 是 C\C++ 的檔頭,它是用來定義一些跨平台的資料型態。當您需要一些無正負符號的位元數值時,就可以使用它。例如:

void loop() {
uint8_t volume = Serial.read() - 'a';
....
}






2014年8月29日 星期五

Boa Constructor - 建立你的第一支程式



1. 點選下拉功能表「New」右下角落的 [wx.App]工具列按鈕,會產生 App1,Frame1 兩個頁籤,如下圖


2. 分別點擊 App1和 Frame1頁籤,並儲存成 App1.py 和 Frame1.py,如下圖


接著會出現檔案儲存視窗,如下圖


3. 利用視窗上方的「top | up」切換路徑到 C 磁碟機根目錄底下,點選「new floder」新建一個資料夾「App1」,再點擊「Save」鈕,如下圖


您可以使用檔案管理員檢視 C:\App1 資料夾,您可以發現我們剛剛儲存的 App1.py 和 Frame1.py 就在這裏。


3.點擊 [Run application] 工具列按鈕,看看目前的成果。 

它會出現一個空白視窗, 如下:








安裝 Boa Constructor

Boa Constructor 是一個以 wxPython 為基礎的使用者介面建構器。

官網 http://boa-constructor.sourceforge.net/



下載

切換至下載頁面 http://sourceforge.net/projects/boa-constructor/files/,點擊淡藍色的「Download boa-constructor-0.6.1.src.win32.exe (13.9 MB)字樣。


安裝

雙擊 boa-constructor-0.6.1.src.win32.exe,然後依照指示安裝。
接著在 C:\Python27 內新增一個文字文件,在裏面鍵入

python C:\Python27\Lib\site-packages\boa-constructor\Boa.py

如下圖



儲存檔案並將「新增文字文件.txt」更名為「Boa.bat」。
最後再為 Boa.bat 建立一個桌面捷徑,以後只要雙擊 Boa 捷徑圖示,即可啟動 Boa Constructor。

溫馨提示:

1. 如果您的作業系統是 Windows7 (含)以上版本,則您應該以系統管理者身分執行 Boa 捷徑。

2. 如果在啟動過程中顯示無法找到 wx.NO_3D 模組,則您可以分別找出模組內文中有 「wx.NO_3D」文字的地方以「wx.DEFAULT_FRAME_STYLE」取代。

3. 如果無法存取「C:\Documents and Settings」資料夾,您可以依照網頁 http://www.minwt.com/pc/5502.html 的指示解除這個限制。

教學影片

1. https://www.youtube.com/watch?v=Im2odZllHXM
2. https://www.youtube.com/watch?v=_vqZeyZfap8
3. http://showmedo.com/videotutorials/video?name=4010000&fromSeriesID=401


2014年8月28日 星期四

安裝 wxEasyGUI

wxEasyGUI 可以讓您更簡單地使用 wxPython 的視窗工具。
以 MessageBox 為例,如果要顯示如下畫面


使用 wxPython 需要寫這麼多行:

import wx

class Example(wx.Frame):

    def __init__(self, *args, **kwargs):
        super(Example, self).__init__(*args, **kwargs)

        self.InitUI()

    def InitUI(self):

        wx.FutureCall(5000, self.ShowMessage)

        self.SetSize((300, 200))
        self.SetTitle('Message box')
        self.Centre()
        self.Show(True)

    def ShowMessage(self):
        wx.MessageBox('aaaa\nbbb', 'Info',
            wx.OK | wx.ICON_INFORMATION)


def main():

    ex = wx.App()
    Example(None)
    ex.MainLoop()


if __name__ == '__main__':
    main()

而使用 WxEasyGUI 只需要 2 行:

import wxEasyGUI as eg
s = eg.MessageDialog('aaaa\nbbb')     # s = 'ok'

由此可見 wxEasyGUI 的確是非常地好用。


安裝需求

1. Python
2. WxPython


下載

切換網頁到 http://sourceforge.net/projects/wxeasygui/?source=typ_redirect,點擊綠色的 Download 按鈕。


安裝

將 wxEasyGUI.py 複製到 python2.7\Lib 底下即可。


範例程式

這裡有許多範例程式 http://sourceforge.net/projects/wxeasygui/files/,您可以下載並執行它。