總網頁瀏覽量

2013年4月30日 星期二

assert

assert用來捕抓程式在商業邏輯、現實活動運作流程上的錯誤。

assert(boolean) :"assertionErrorMessage"


要讓java 執行assert測試程式
在執行class時候要跟jvm說
java -ea XXXX
ea:enable assert


當條件式為false才會觸發AssertionError

2013年4月29日 星期一

開啟IIS服務

去控制台的"程式與功能",之後點選"開啟或關閉windows功能"
接著等一陣子後出現選單 緊接著將Internet Information Service打勾
(懶惰的話就將裡面細項全勾吧!這樣iis主控台的項目東西比較齊全)
開啟IIS服務
這樣一來在瀏覽器打上localhost就會出現大張圖片用多國語言問候大家
(IIS預設是80port,安裝apache要注意)

想運作的網頁放在
C:\Inetpub\wwwroot底下


點下開始  執行iis 就可以開啟IIS主控台


如果網頁不想放在wwwroot底下那麼可以去
iis主控台的ASP項目點兩下
將啟用上層路徑設定為true
接著左邊選單站台底下網頁點右鍵選新增虛擬目錄
設定別名以及實體路徑即可

PHP開發環境設定

基本上用安裝包
就可以了
要注意的是port設定

如果系統已經安裝IIS那麼安裝apache時候務必將port換掉
可以去conf/httpd.comf更改以下兩行將80換掉
Listen 80
ServerName localhost:80


登入phpMyAdmin管理介面
http://localhost:4869/phpMyAdmin/




MySQL
匯入資料庫的最直接方法
將整個資料庫資料夾複製貼上到data底下就好

show variable like '%charac%'
顯示MySQL系統名稱有charac字眼的環境變數設定

2013年4月28日 星期日

所學大綱

在某單位所學的概要,紀錄這幾個月上的內容
心得:
1.感覺.NET上的比Java還多
2.平均兩周就上完一種課程而且每堂課份量都比大學課程還多
3.腦袋實在無法短時間裝下這麼多東西

Linux


命令列語法
安裝Java環境
打包壓縮、解壓縮
檔案與資料夾的權限設置與變更
ps、pstree

crontab
bsd-mailx城市
mplayer城市
bindq城市
Dns架設
Apache架設
組態檔設定
網站登入設定

資料庫

MSSQL:

Join、Union語法
子查詢
Insert Delete
select into
#臨時資料表
Delete、Truncate
建立資料庫
資料型別
建立資料圖表
檢視表
規則
預設值
使用者自訂資料物件
索引觀念
Batch批次執行
SQL變數宣告以及應用
條件判斷
if----else----
case.......then
迴圈
while
begin......end
建立執行程序
create procedure
Trigger
Cursor
Transation
鎖定(write lock read lock)
SQLserver使用者權限(連線登入、新增使用者、資料庫腳色、使用DB權限)
安全設定
網路設定
備份
切換使用者
權限腳色
資料復原
全文檢索
利用index做鎖定



MySQL:

管理MySql四種方式
字元編碼設定
storage engines特色
字元編碼原理
export to file
log 的設置與查看
type注意事項
MySQL資料型態
位元旗標
資料複寫
資料架構設計

Oracle

全域資料庫與網域名稱的觀念
sqlplus
注意事項:記憶體設定、考慮字元集、連線模式
net manager
建立DB 刪除DB by DB組態輔助程式
sequece物件
建立腳色
使用權限
建立表格與管理
索引組織表格
同義詞
資料庫連接
資料庫匯入匯出
Trigger
Sqlplus匯出
匯出(exp)匯入(imp)
資料倒朔




Asp.net(.Net programming)

Web伺服器控制項的功能(TextBox、DropDownLink.............)
C#函數宣告 應用
C#迴圈 條件判斷
SqlDataSource
GridView
FormView
DataList
在網頁上列出DB 查詢DB
使用者控制項
Application
Session
cookie
Lab-BackAndForth
Lab-MasterPage

ADO.net
connection
DataAdapter
DateSet
BindingSource(Write XML,Read XML)
AddCustomerRow
利用sqlconnection sqlcommand sqldatareader物件、指令與資料庫繫結
並在dropdownlist與Gridview顯示資料
建Dataset繫結DB
GridView實作paging功能 更新Row

command物件介紹
參數輸入的使用與安全
sqldatasource介紹
資料圖表整理
多個資料集回傳與處理
多個command組合transaction

常用工具:
calender
multiview
view
wizard

資料驗證:
Required validator
compare
custotm
range
rangeexception
validationSummary
customvalidator
system.io
directory,directory info
file ,fileinfo
foreach
getfiles
StreamWriter
StreamReader
Image SQL
QueryString
從SQL傳資料倒Excel
ajax
updatepanel
scriptManager
Graphic:2D字型繪圖
pringing:pringDocumemt,print previewDialog
WCF:WcfTestClient,非同步呼叫
下載圖片from Web   from Storage
刪除圖片
從網路讀取XML文件格式輸出到listbox
()==執行緒 新增 取消 lock 系統lock(windows phone?)
分散式WCF(one way ,duplicate,duplex SVC,WCF data service)
LINQ
Discovery探索服務位址埠號
DynamicHost
Event



.net程式安全
防止script攻擊,by HTML injection,server,Html encode
SQLinjection(入侵,防止)
cross site script(XSS)
使用圖片驗證做人公斷點防止xss跨站攻擊
user identify身分驗證
表單驗證
雜湊函數用法,Hashed(MD5,sha256)
金鑰加解密RSA 直接用內建API


JSP


servlet
標籤說明
處裡請求與產生回應
編碼問題
Get Post
部屬環境與開發環境
URL對應
JSP網頁執行過程
JSP網頁元素組成
MVC架構與存取資料庫
屬性物件
JavaBean,性質(編碼問題與處理)
JNDI:連到DB
存取DB  新增Data
MVC架構實作
expression language ${key}
EL屬性物件與對應的識別字串
EL的其他運算子
standard action
標準動作標記(setProperty getProperty include foreward param
JSTL功能
<C:foreach>具迴圈功能的標籤
<c:if>可判斷條件的標籤
session管理
cookie功能
URLRewriting
Session物件的寫法
Session API
Session物件建立刪除
servlet生命週期
servletconfig介面
servletContext介面,應用
servletContextListener介面
servlet起始參數與生命週期的init()



PHP
運算 型別(一些撇步)
rand
isset()
$_Get[]取得Html中的name變數
陣列不同寫法
foreach寫法
function寫法
檔案總管
檔案上傳與下載
檔案輸入輸出
連接資料庫 新增修改刪除換頁



Javascript

弱型別的程式語言
變數宣告方式var x=0;  自動視為int
函式介紹  javascript物件導向
array的用法
事件觸發
jQuery初探


CSS

樣式、規則
CSS ID選擇器 類別選擇器
常用CSS屬性
jQuery應用
slide window
DOM操作
Ajax
開jQuery外掛
jQueryUI

2013年4月27日 星期六

SCJP觀念筆記以及考取心得

考完之後跟網路上傳說的一樣
猛虎出閘跟教戰手冊考題背一背就可以上場了
約莫四十五題來自這兩本後面習題
其中四十題一模一樣
剩下五題只是小地方修改
感覺很像在考大學通識課的期末考



不過,準備OCJP過程感覺自己有在變強這才是最重要的
重點是過程而不是那張紙
過程補足自己忽略掉的小細節觀念
至少這樣拿這張證照不會心虛

在做練習題時候感覺很像中學考試一樣
書上教大觀念,考試一直考小細節
剛開始做題目時候挫折感真的很重




1.物件強制轉型
父類別物件不可assign給子類別變數(compile erro)



父類別物件不可強制轉型成為子類別物件(可以compile,但是會ClassCastException)


Thingy t = new Thingy();
//Thingy是父類別型態存放父類別物件
DeluxeThingy k= (DeluxeThingy)t;
//強制轉型成子類別型態的t裝不下原本父類別的物件所以發生classcastexcetpion



Thingy t = new DeluxeThingy();
//父類別型態存放子類別物件

DeluxeThingy k= (DeluxeThingy)t;
//雖然t放的是子類別物件,因為t的型態是父類別所以要強制轉型



2.
javac -d course java/Hello.java
這句話意思是編譯java/Hello.java檔案
並且將.class放在目錄course底下


3.
有個檔案Vermouth.class
放在D:Java\course\accessmode底下
檔案內容為
package course.accessmode;
public class Vermouth{   }

Java是專案跟目錄


在D任何資料夾打上底下這行指令,皆可以順利執行
java -classpath  /Java  course.accessmode.Vermouth

在D:Java目錄打上底下這行,可以順利執行
java course.accessmode.Vermouth 


注意:不可以進入accessmode目錄(類別檔所在目錄)
執行java Vermouth
會出現NoClassFound,因為accessmode沒有course\accessmode資料夾
所以找不到

4.宣告介面後不可再宣告同名的類別



5.

short a=5;
int b =6;
a=b;//不給過
a=(short)b;//給過


6.在java裡所有基本型態資料的變數,傳遞到method均已傳值呼叫(pass by value)傳值呼叫不影響原來的變數值
(編譯器將變數值拷貝一份,再將這個拷貝的一份傳遞給method引數)

傳遞陣列或物件是以傳參照(pass by reference)方式傳參照是傳遞變數的參考位置,因此在method更改變數內容原先變數內容也會隨之更改
(編譯器將物件或陣列參考位址拷貝一份 傳給method引數)
此時有兩個變數操作到同一個實體


如果有上萬的元素的陣列,採用傳值呼叫傳遞引數
那麼編譯器勢必要複製上萬的元素的值,給引數
會降低效率
如果採用傳參照 只消複製一個參考位址給引數即可

7.多載:將功能相似的method 以相同名稱命名,編譯器會根據引數的個數與型態自動值星相對應的method。一個多載化的method 引數內容都是獨一無二的。因此如果有引數相同的method,就算傳回型態不同,編譯器也會搞不清楚該呼叫誰。compile error


8.
列舉型態本身也是類別一種
每個項目預設為public final static
當建立物件時MyColor color = MyColor.RED;
會呼叫建構子,而且是每個項目都呼叫一次
以下的例子會呼叫帶有參數的建構子
因此只寫下面這樣會error
必須加上帶有參數的建構子
public enum MyColor{ RED(0xff0000),GREEN(0x00ff00),BLUE(0x0000ff); }

2013年4月24日 星期三

JSP



JSP是JavaServerPage的縮寫


Jsp的容器物件Tomcat位於Apache Software Foundation資料夾底下
bin存放tomcat服務的執行檔、相關設定
conf資料夾存放tomcat server相關設定
webapps放tomcat網站以及jsp部屬地方


自己手動安裝tomcat
去官網下載32bit版的tomcat
資料夾可隨意放
解壓縮之後
在bin資料夾底下的setclasspath.bat

rem Make sure prerequisite environment variables are set
加上

set JAVA_HOME=C:\Program Files (x86)\Java\jdk1.7.0_07
set JRE_HOME=C:\Program Files (x86)\Java\jre7
告訴Tomcat,Java Jre安裝路徑



如果電腦有其他tomcat或IIS 那麼要注意port有沒有衝到
如果有就去conf資料夾下的server.xml更改port
將下面的8080改成其他port

 <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />



2013年4月22日 星期一

播放音樂、背景音樂

MediaPlayer 不支援多個音樂同時播放
SoundPool 音樂容量只允許10M





private MediaPlayer player;


1.從內部儲存空間播放


player.setDataSource("/mnt/sdcard/slashwater.aif");
無法播放aif
// player.setDataSource("/mnt/sdcard/morzart.mid");

player.prepare();
player.start();


2.從網路播放


3.從res/raw播放

Android一些理論筆記

Activity:


1.每個activity是一個螢幕
關於activity生命週期查閱lifecycle

2.activity有兩種宣告方式:

第一種透過XML設定檔宣告:
activity設定檔位於res/layout底下
一個xml相當於一個view容器

第二種自訂一個繼承View的類別
之後再MainActivity實體化並setContentView
MySelfeView mcv = new MySelfeView(this);
setContentView(mcv);//設定目前螢幕


Service元件

1.
Service 沒有提供與用戶進行互動的展示層,Service是執行在後台的元件
Service通常由Activity或其他的Context物件來啟動
Service通常在Activity生命週期結束仍會運行
每個Service應該在AndroidMainifest.xm.進行宣告

2.
Service啟動方式有兩種:
第一透過startService(Intent)啟動。

透過startService(Intent)呼叫的service生命週期:跟Activity差不多
onCreate() onStart() onDestroy()

第二透過bindService方法啟動,然後Service會跟呼叫Service的物件(Context,就是Activity)綁住
當被綁定的Context被銷毀時 Service也會連帶停止執行
生命週期大致如下順序
onCreate()  onBind()  onUnbind() /onDestory()



Broadcast Receiver元件:

負責接收廣播訊息並對訊息做出反應的元件
應用:當電池電量過低、或信號過低時 系統發廣播進行通知


Content Provider元件


Service

Service:
播歌、下載檔案、電池快耗盡通知、mail來電通知

Service通常會啟動另外一個thread處理較花時間的程序


一、Notification,通知服務的功能實作(有部分method是deprecation)

1.在MianActivity宣告intent並startService

Intent it = new Intent(this,MyService.class);
it.putExtra("Name", "Morzart");
startService(it);


2.新增class繼承extends Service
extends Service

3.
務必記得去Mainifest.xml
註冊Service不然是不會執行Service的

4.
override    onStartCommand(Intent intent)。
//接收啟動Service的Activity Inent物件
//如果沒有特別事情,可以省略

public int onStartCommand(Intent intent, int flags, int startId) {
String name = intent.getStringExtra("Name");
Log.i("YYP",name);
//Toast.makeText(this, name, Toast.LENGTH_SHORT).show();
return super.onStartCommand(intent, flags, startId);
}




宣告
private Timer timer;

在onCreate(){
timer= new Timer();
ttimer.scheduel(new MyNotice(),10000);

}
//我們會發現當啟動Service之後會先onCreate 接著再執行onStartCommand


//接著宣告thread處理service要做的事情
//本例子是在state bar顯示通知
//使用者按下通知時候會跳到另一個頁面

private class MyNotice extends TimerTask{

public void run(){
NotificationManager mgr= (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
//notificationManager負責整個系統通知控制
//NotificationManager屬於系統管理類別因此要從getSystemService取得notification服務
@SuppressWarnings("deprecation")
Notification notice = new Notification(R.drawable.ic_launcher,"重要通知",System.currentTimeMillis());
//notification 物件此物件名稱是"重要通知"
//(顯示在state Bar的icon,顯示再狀態bar的文字,顯示的時戳)
//System.currentTimeMillis()取得現在時間


notice.flags=Notification.FLAG_AUTO_CANCEL;
//按一下service後notification會Service列表消失
// notice.flags=Notification.FLAG_FOREGROUND_SERVICE;
//Service為常駐狀態,常駐在service列表
// notice.flags=Notification.FLAG_ONLY_ALERT_ONCE;
//Service為常駐狀態,常駐在service列表

//flag表用來標記notification是何種類型任務


Intent it = new Intent(this,Page2.class);
//按下Service通知 進入page2
PendingIntent pit = PendingIntent.getActivity(this, 1, it, 0);
// PendingItent pit = PendingIntent.getActivities(context, requestCode, intents, flags);
//pending:即將發生的。
//顧名思義是宣告暫時存放的intent
//PendingIntent pit = PendingIntent.getBroadcast(this,1, it, 0);
//PendingIntent pit = PendingIntent.getService(this,1, it, 0);


notice.setLatestEventInfo(this, "重要訊息", "好好學習天天向上", pit);
//deprecated
//notice.setLatestEventInfo(context, contentTitle, contentText, contentIntent)
//當使用者點下該notification之後會去執行pit的intent

mgr.notify(1, notice);
//指定要顯示的notification物件以及識別ID
}
}



最後要停止Service,要宣告intent物件
再呼叫stopService()

private void toStop(){
Intent it = new Intent(this,MyService.class);
stopService(it);
//執行到這,會呼叫Serivce的onDestroy()
//雖然stop了 但是service仍會在service列表裡
}



二、廣播訊息、接收廣播訊息

在Service的.java檔
實作發送廣播訊息,以TimerTask實作之


timer.schedule(new MyTask(), 0,500);



private class MyTask extends TimerTask{

@Override
public void run() {

//Toast.makeText(this, "service start", Toast.LENGTH_SHORT).show();
//要Handler

int temp=(int)(Math.random()*49+1);
Intent it = new Intent("MyAction");
//Intent(String Action)  給intent貼標籤"MyAction"
it.putExtra("value", temp);//想要傳遞的東西放進去
sendBroadcast(it);//廣播出去由BroadcastReceiver接收
}
}

在MainActivity裡面:
實作接收訊息

宣告
private class MyReceiver extends BroadcastReceiver{


@Override
public void onReceive(Context arg0, Intent intent) {
int value = intent.getIntExtra("value", -1);
//int value = intent.getIntExtra("", defaultValue)

tv.setText(""+value);
}



}


宣告:

private MyReceiver receiver;

receiver = new MyReceiver();

IntentFilter filter = new IntentFilter("MyAction");
//只接收"MyAction"的intent廣播

//IntentFilter filter = new IntentFilter("MyAction2");
//如果這裡改為"MyAction2"會收不到MyAction的intent廣播


registerReceiver(receiver,filter);


2013年4月20日 星期六

簽名、手記製作

程式的目的:
將手機螢幕當作便條紙可以在上面畫圖。


一、畫圖實作


圖構成的邏輯:
畫圖由多條線構成一張圖
而兩個以上的點構成一條線

實作:
1.宣告LinkedList 裡面存放多條線(多個HashMap物件)
2.宣告HashMap代表一個線條,HashMap存放線條的顏色、粗細,以及構成線條的座標
3.HashMap裡面其中一欄位存放LinkedList存放多個座標,每一個座標以HashMap姿態放進LinkedList中
(一條線由多個座標連起來所構成)
因此實作LinkedList為容器存放多個座標,

接著利用GestureDetector以及onTouchEvent onDraw onDown來實作將HashMap放進LinkedList
或者取出的動作啦


ScrollView:ScrollView也是layout一種,只限定vertical的方向。當scrollview裡面的元件超過螢幕顯示範圍,可以滾動方式取得元件。不可以放在LinearLayout之內。

自訂View:新增.java類別,類別必須繼承(extends View)。
且必須有建構式,本例子的建構式接收Context,AttributeSet

所謂Context就是指向parent對象的指標(或參考),受到parent控制
通常Context指向Activity
Context可以理解成程式(物件)所在的環境(狀態)
Context裡面存放Activity各式各樣的資訊


首先,準備好painel view
public class MainPanel extends View


在建構式宣告畫筆Paint
以及手勢偵測物件,告知gesturedetector所在context以及listener

在建構式外面宣告傾聽者類別繼承手勢傾聽者
new GestureDetector(context,MyListenter)
private void MyListener extends SimpleOnGestureListener{}


GestureListener要override OnDown 以及onScroll method
MainPanel(View) 要override onTouchEvent 以及onDraw method


範例程式:


public class MainPanel extends View {
private Paint p;// 畫筆
private GestureDetector gd;
private Context context;
private HashMap<String, Object> line;//
private LinkedList<HashMap<String, Object>> lines, redos;
private int size;// 筆畫粗細
private boolean isInit;
private boolean isDrawing;

public MainPanel(Context c, AttributeSet attrs) {
super(c, attrs);
context = c;// 從mainActivity來的?

//Log.i("context",context.toString());
//context指的是MainActivity@416a87d0

size = 10;
p = new Paint();
p.setColor(Color.MAGENTA);
p.setStrokeWidth(size);

gd = new GestureDetector(context, new MyListener());
// 手勢偵測物件,偵測碰觸螢幕的事件

setBackgroundColor(Color.TRANSPARENT);// View的顏色與parent一樣

}

private class MyListener extends SimpleOnGestureListener {

@Override
public boolean onDown(MotionEvent e) {
//onTouchEvent return gd.onTouchEvent(event)且action_down 會觸發這裡
//Log.i("Sing","onDown");

//onDown表示線條起點

float x = e.getX(), y = e.getY();
//手指碰到的座標

line.put("color", p.getColor());
line.put("size", (int)p.getStrokeWidth());

LinkedList<HashMap<String,Float>> lxy = new LinkedList();
HashMap<String,Float> xy = new HashMap();
xy.put("x", x);
xy.put("y", y);

lxy.add(xy);//HashMap放進Linklist
//將起始座標放入lxy[0]

line.put("line", lxy);//起始座標
// return super.onDown(e);
return true;
//retrun true會持續觸發touchevent 以及onScroll
}

// @Override
// public boolean onScroll(MotionEvent e1, MotionEvent e2,
// float distanceX, float distanceY) {
// Log.i("Sing","onScroll");
//
// return super.onScroll(e1, e2, distanceX, distanceY);
// }

}//GuestureDetector

//初始化
private void init(){
lines = new LinkedList<HashMap<String,Object>>();
redos= new LinkedList<HashMap<String,Object>>();

isDrawing = false;
isInit =true;

}


@Override
protected void onDraw(Canvas canvas) {
Log.i("Sing","onDraw");
super.onDraw(canvas);

if(!isInit) init();
//初始化,因為onDraw相當於View的main,
//但是有時會自動執行多次 所以就用init()初始化


//第一次進入這裡不會在View上畫出東西
//第一次進入畫面不會跑進foreachloop
for(HashMap<String,Object> line : lines){

// p.setColor(Color.BLACK);
// p.setStrokeWidth(3);
//所以這邊可以用條件判斷,當line裡面lxy的index符合某條件時
//更改線條顏色

p.setColor((Integer)line.get("color"));
//Log.i("Conan"," "+(Integer)line.get("color"));
p.setStrokeWidth((Integer)line.get("size"));
// Log.i("Conan"," "+(Integer)line.get("size"));

LinkedList<HashMap<String,Float>> lxy = (LinkedList)line.get("line");
//第一次treace程式碼:line存放兩個座標了

for(int i=1; i<lxy.size();i++){
HashMap<String,Float> xy0 = lxy.get(i-1);
//取得linkedlist 裡面物件 ,節點1
HashMap<String,Float> xy1 = lxy.get(i);
//節點2
canvas.drawLine(xy0.get("x"), xy0.get("y"), xy1.get("x"), xy1.get("y"), p);
// 畫線

}


}

}
@Override
public boolean onTouchEvent(MotionEvent event) {
// Log.i("Sing","onTouchEvent");

if(!isDrawing){

//之前尚未開始畫圖,進入這裡進行初始化
//第二次treace:新增第二條線
line = new HashMap();
lines.add(line);//line是一條線,lines放多條線的LinkedList
//第二次trace到這,在lines[1]加上line HashMap物件
//還沒設定線條顏色與粗細
// Log.i("YYP", "" + lines.size());

//lines放n條線
isDrawing = true;
return gd.onTouchEvent(event);//第一次onTouchEvent後跳去onDown
}
else if(isDrawing && event.getAction()==MotionEvent.ACTION_UP)
{//正在畫圖  手指離開螢幕
isDrawing = false ;
return false;
}
else
{//isDrawing = true  event.getAction()==MotionEvent.Action_Move
//正在畫圖
LinkedList<HashMap<String,Float>> lxy = (LinkedList)line.get("line");
//這裡的line跟onDwon的line是同一個
//第二次trace到這邊:line裡面已經有兩個座標,
HashMap<String,Float> xy = new HashMap();
xy.put("x", event.getX());//線的終點
xy.put("y", event.getY());
//第二次trace到這邊:增加第三座標
lxy.add(xy);
//第一次trace將座標放入lxy[1]
//第二次trace到這 ,座標放入lxy[2]
postInvalidate();//呼叫ondraw
return gd.onTouchEvent(event);

}

// String str=event.toString();
// Log.i("Sing",str);
// int action = event.getAction();
//    cordinateX = (int) event.getX();
//    cordinateY = (int) event.getY();
//    switch (action) {
//    // 按下那一刻的動作
//    case MotionEvent.ACTION_DOWN:
// Log.v("Sing", "ACTION_DOWN");
// break;
//    // 移動的動作
//    case MotionEvent.ACTION_MOVE:
// Log.v("Sing", "ACTION_MOVE");
// break;
//    // 抬起的動作
//    case MotionEvent.ACTION_UP:
// Log.v("Sing", "ACTION_UP");
//// postInvalidate();//好像開啟另一條thread呼叫onDraw吧?
// break;  
//    }
//    return super.onTouchEvent(event);
//    return true;
}
}




二、開新檔案的功能:


以上完成之後,手指在螢幕上畫圖表示
將線條座標一一塞入LinkedList裡面。
開新檔案就是將LinkedList裡面的物件(線條、座標)清空
最快的方法重新new一個LinkedList物件,讓line指向新的物件
這樣就達到開新檔案了。



在MainPanel裡面宣告
void doInit(){
isInit=false;
postInvalidate;
//執行上面的onDraw
}

在MainActivity
宣告view變數
private MainPanel mp;
mp= (MainPanel)findViewById(R.id.mp);
//若沒寫這行會出現nullPointException

將mp.doInit();寫在btnOnClick事件裡。


三、復原、重做

以一個線條為單位復原重作。



void undo() {
//復原表示將LinkedList的元素逐一刪掉
if (!lines.isEmpty()) {
//lines.removeLast();
//
// lines裡面將線條移除
redos.add(lines.removeLast());
              //刪掉的元素放進redo
postInvalidate();
}
}
void redo(){

if((redos!=null)&&(redos.size()>0)){

lines.add(redos.removeLast());
//將redo的東西重新放入lines
postInvalidate();
}
}


四、自訂線條顏色(color picker實作)

取用別人寫好的code當作自己的函式庫libray
引用別人寫好的函式庫

1.
首先下載
android color picker
整個project程式碼

2. import android-color-picker

3.import之後在android-color-picker專案點右鍵,選properties
之後選擇"android"     之後將"is Libray"打勾   之後點apply並關閉視窗


4.回到原本project
在原本project點右鍵跟上面一樣選properties 選android
之後點add
將android-color-picker加入
這樣一來可以將自己/別人寫的code當作函式庫引用了

private void colorPicker(){
// initialColor is the initially-selected color to be shown in the rectangle on the left of the arrow.
// for example, 0xff000000 is black, 0xff0000ff is blue. Please be aware of the initial 0xff which is the alpha.
AmbilWarnaDialog dialog = new AmbilWarnaDialog(this,mp.getColor, new OnAmbilWarnaListener() {
        @Override
        public void onOk(AmbilWarnaDialog dialog, int color) {
                // color is the color selected by the user.
mp.setColor(color);        
}
                
        @Override
        public void onCancel(AmbilWarnaDialog dialog) {
                // cancel was selected by the user
        }
});
}

相關步驟以及整個code下載來源如下:
https://code.google.com/p/android-color-picker/





五、儲存檔案


首先去mainifest.xml設定權限
android.permission.WRITE_EXTERNAL_STORAGE
允許程式可以將資料儲存到手機上面去

接著利用MainPanel extends View物件的setDrawingCacheEnabled(true)

mp.setDrawingCacheEnabled(true);
讓onDraw的資訊可以快取在記憶體
不寫這行,下面程式會出現NotFoundException之類的字眼
Bitmap物件在記憶體中抓取不到資料


private void save(){}
FileOutputStream fout;
try{
fout = new FileOutputStream("/mnt/sdcard/name.png");
//指定輸出到內部儲存空間

Bitmap bmp = mp.getDrawingCache();
//Bitmap物件 接收快取記憶體裡的資料
bmp.compress(Compress.PNG,100,fout);
//輸出格式  輸出品質 輸出目的
fout.flush();
fout.close();


Toast.makeText(this, "saveOK", Toast.LENGTH_SHORT).show();

}catch(Exception e){
Log.i("Exception",e.toString());


}


六、自訂線條大小


SeekBar實作

private SeekBar seekbar;
seekbar = (SeekBar)findViewById(R.id.seekbar);
seekbar.setProgress(mp.getSize());
//設定seekbar初始值
seekbar.setMax(10);

//設定seekbar最大值

 seekbar.setOnSeekBarChangeListener(new OnSeekBarChangeListener(){

@Override
public void onProgressChanged(SeekBar arg0, int progress, boolean fromUser) {
//progress:seekbar的值
mp.setSize(progress);
}

@Override
public void onStartTrackingTouch(SeekBar arg0) {

}

@Override
public void onStopTrackingTouch(SeekBar seekBar) {

}});





int getSize(){

return (int)p.getStrokeWidth();

}

void setSize(int size){
p.setStrokeWidth(size);


}



七、自訂歡迎畫面



Application Node新增Activity
在Activity底下新增
intent filter將其他activity的intent filter刪掉
這樣可以依照自己意思指定起始畫面了



PS:



private Resource res;
res = getResources();//從Context取得Resource物件
//Resource物件可以在.java檔案取得該專案的xml資源設定值



Toast.makeText(this, res.getString(R.string.btn_save), Toast.LENGTH_SHORT).show();
//re.getString(R.string.btn_save);  印出string.xml中所對應的字串
去看values/string.xml有這樣標籤
<string name="btn_save">Save</string>







2013年4月18日 星期四

手機、平板電腦座標系統

將裝置橫放我們會發現有些裝置橫向(左右方向)的座標軸是x軸,有些是y軸
通常手機橫放的左右方向是y軸

共通點是Y軸方向是照相機鏡頭的方向



Private Display display;

display= getWindowManager().getDefaultDisplay()


display.getRotation();


當getRotation()為1時候表示使用手機

若為零表示使用平板電腦

2013年4月15日 星期一

android自訂View觸控事件筆記

一、原始狀況:

自訂繼承View的類別。
override onTouchEvent與onDraw

執行程式會先跑onDraw
碰觸螢幕會觸發onTouchEvent事件
(onTouchEvent 回傳super.onTouchEvent(event)



二、
將onTouchEvent的retrun super.onTouchEvent(event);
改為return true

執行程式碰觸View會一直觸發onTouchEvent事件
onTouchEvent事件分成三種動作(action)
可以藉由event.getAction();
得知目前使用者的onTouchEvent事件的action
分別為Action_Down、Action_Move、Action_Up
第一個例子onTouchEvent只會偵測到Action_Down
如果onTouchEvent改為return true
則可以偵測到Action_Down、Action_Move、Action_UP


三、加上GuestureDetector手勢偵查物件

宣告GuestureDetector物件並宣告SimpleOnGestureListener子類別,
override onDown 與Scroll 與Fling


private GestureDetector gd;
gd = new GestureDetector(context,MyListener());
//context是指activity要看view放在哪個activity,MyListener是傾聽者



private class MyListener extends SimpleOnGestureListener{
//宣告傾聽者 繼承自SimpleOnGestureListener

@Override
public boolean onDown(MotionEvent e) {
Log.i("Sing","onDown");

return super.onDown(e);
}

@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY) {
Log.i("Sing","onScroll");
return super.onScroll(e1, e2, distanceX, distanceY);
}
}

1.
將onTouchEvent傳回值
改成gd.onTouchEvent(event)
//GestureDetector偵測有沒有發生onTouchEvent事件

執行程式會執行onDraw
按下螢幕會執行onTouchEvent
緊接著執行onDown。
因為GestureDetector偵測到onTouchEvent觸發onDown

2.承上
將onDown的return super.onDown(e);改為return true;
再執行程式
按下螢幕(不滑動)會發現
程式會先onTouchEvent之後onDwon接著就是連續執行onToucheEvent
而沒有執行onDown

由此可知道
當onTouchEvent 的 action 為down時候
會觸發Listener 的ondown


如果手指在螢幕上滑動一段距離
會交錯著先觸發onTouchEvent之後觸發onScroll

onDraw → onTouchEvent→ onDown → onTouchEvent→ onScroll →onTouchEvent→ onScroll


3.若沒加上postInvalidate()是不會再呼叫onDraw的

2013年4月14日 星期日

SensorManager

SensorManager是手機平板電腦特有的功能


本文先說明加速度感測器:
加速度感測器顯示手機受到加速度的方向
分成X Y Z三個方向

將手機平躺著那麼X 與Y加速度趨近於零
Z加速度為9.8m/s^2

如果將手機直立Y加速度為9.8m/s^2
將手機橫立X軸加速度為9..8m/s^2

只是單純旋轉手機,不出力那麼所受的合力為9.8m/s^2




public class MainActivity extends Activity {
private SensorManager mgr;
private TextView info;
private Sensor sensor;
private MyListener listener;
private int nowz = -500, nowx, initx;
private float maxx;
private boolean isPull;
private int iscast = 0;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

info = (TextView) findViewById(R.id.info);

mgr = (SensorManager) getSystemService(SENSOR_SERVICE);
List<Sensor> list = mgr.getSensorList(Sensor.TYPE_ALL);

// for (Sensor sensor: list){
// info.append(sensor.getName() + ":" +
// sensor.getMaximumRange() + ":" +
// sensor.getResolution() + "\n"
// );
// }

//
sensor = mgr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
//
// sensor = mgr.getDefaultSensor(Sensor.TYPE_ORIENTATION);

// sensor = mgr.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION);
// sensor = mgr.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
// sensor = mgr.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR);
listener = new MyListener();

}

@Override
protected void onResume() {
super.onResume();
mgr.registerListener(listener, sensor, SensorManager.SENSOR_DELAY_NORMAL);
}

@Override
protected void onPause() {
super.onPause();
mgr.unregisterListener(listener);
}

private class MyListener implements SensorEventListener {

@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// TODO Auto-generated method stub

}

@Override
public void onSensorChanged(SensorEvent event) {
float[] data = event.values;
float x = data[0] * 10, z = data[2] * 100;
// info.setText(data[0]+"\n"+data[2]);

if (z < nowz) {


if (iscast == 0) {
Log.i("log", "以拉釣竿");
nowz = 990;
iscast = 1;
}

}

if (z > nowz) {
if (iscast == 1) {
if (x < 0) {

maxx = (Math.abs(1-x/10))*5;
Log.i("log", "z"+z + " x"+x);
info.setText("" + maxx);
iscast = 3;
}
}
maxx = 0;
initx = -20;
nowz = -500;

}

// if (z < nowz) {
// nowz = (int) z * 10;
// initx = (int) x;
// isPull = true;
// } else {
// isPull = false;
// if (x < initx) {
// int dx = (int) (Math.abs(x - initx));
// if (dx > maxx) {
// maxx = dx;
// info.setText("Power:" + maxx);
// }
// } else {
// nowz = 999;
// maxx = 0;
// }
// }
}}}




SensorManager.getOrientation();

Dialog(AlertDialog,ProgressDialog,自訂dialog,自訂Toast,View)

本文是AlertDialgo的實作
基本上當作SOP處理
記得實作AlertDialog基本架構


AlertDialog是一個類別,裡面包住Builder類別
AlertDialog是Dialog子類別。

本例子
全都用Button來觸動showDialog method


首先在Activity宣告AlertDialog的物件。
private AlertDialog alert;


一、true與false對話框:

private void showDialog1(){

AlertDialog.Builder builder = new AlertDialog.Builder(this);
//宣告AlertDialog裡的Builder物件
////this 是指Activity也就是對話框顯示所在的Activity,this為context型態

builder.setTitle("這是對話框標題");
builder.setMessage("這是對話框內容。是否刪除資料?");
builder.setCancelable(false);
//設定鎖住返回鍵,false表示禁止按下返回鍵,只能按"確定"與"取消"

//alertDidalog的"確認"按鈕,傳遞參數,按鈕的內容以及註冊傾聽者。實作傾聽者匿名內部類別。
builder.setPositiveButton("是", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(MainActivity.this,"資料已刪除",Toast.LENGTH_SHORT).show();
//由於Toast包在內部類別裡面所以this前面要加上MainActivity
//記得要加上show()
}
});

//alertDidalog的"取消"按鈕,其餘同上
builder.setNegativeButton("否", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(MainActivity.this, "取消刪除", Toast.LENGTH_SHORT).show();
}
});

//最後務必記得要create() 跟show()
alert=builder.create();//create傳回Builder型態
alert.show();//.show() 傳回Dialog型態

}



二、列表式(list)對話框:按下button顯示多個項目,點其中一個項目,告知使用者所選的項目。
核心method :setItems(CharSequence[],DialogInterface.OnClickListener);

String items={"香蕉","芭樂","手榴彈","書"};


private void showDialog2(){
AlertDialog.Builder builder = new AlertDialog.Builder(this);

builder.setTitle("選擇一個喜歡的項目吧");
builder.setCancelable(true);

builder.setItems(items,new DialogInterface.OnClickListener() {
//傳入字串陣列items
@Override
public void onClick(DialogInterface dialog, int which) {
//which表示使用者所點選的項目
Toast.makeText(MainActivity.this, "你選擇了"+items[which], Toast.LENGTH_SHORT).show();
}
});
alert=builder.create();
alert.show();

}



三、自訂對話框:利用xml自訂對話框,與Dialog物件結合。Dialog是AlertDialog父類別。


private Dialog dialog;


private void showDialog3(){
dialog = new Dialog(this);
//對話框物件,this是context物件,表示對話框所在activity
dialog.setContentView(R.layout.newreg);//配接對話框
dialog.setTitle("註冊新帳號");

Button ok , cancel;
// ok=(Button)findViewById(R.id.ok);
//必須指定是哪個Activity、Dialog在findViewById,否則會出現NullPointerException,找不到對應物件。
ok = (Button)dialog.findViewById(R.id.ok);
//使用dialog下的findviewbyid
cancel = (Button)dialog.findViewById(R.id.cancel);
username = (EditText)dialog.findViewById(R.id.username);
passwd = (EditText)dialog.findViewById(R.id.passwd);

ok.setOnClickListener(new OnClickListener(){

@Override
public void onClick(View v) {
String uname = username.getText().toString();
String password=passwd.getText().toString();

Toast.makeText(MainActivity.this, uname+":"+password, Toast.LENGTH_SHORT).show();
dialog.dismiss();//解散(關閉)對話框
}});

cancel.setOnClickListener(new OnClickListener(){

@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "cancel", Toast.LENGTH_SHORT)
.show();
dialog.dismiss();
}});
dialog.show();//別忘了要show()
}




四、ProgressDialog:
實作下載檔案時常會出現的對話框
宣告ProgressDialog物件
利用執行緒計算count、Handler處理長條bar的運作

private ProgressDialog progress;
private MyHandler handler = new MyHandler();

//private Handler handler;
//打錯,造成NullPointerException
//記得要new MyHandler();否則也會造成NullPointerException





private void showDialog4(){

progress = new ProgressDialog(this);
progress.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
//progress.setProgressStyle(ProgressDialog.STYLE_SPINNER);
//Spinner表示畫圓圈,Horizontal表示長條bar
progress.setCancelable(false);
progress.setMessage("Loading.....");
progress.setMax(123);//長條bar最大長度


new MyThread().start();

progress.show();

}

private class MyThread extends Thread{
@Override
public void run() {
for(int i=0;i<=123;i++){
//改成i+=2  長條bar只會跑到122就停止

handler.sendEmptyMessage(i);
//忘了打這行造成,progressDialog只開啟視窗卻沒有跑

//progress.setProgress(i);
//其實可以直接在thread處理也有同樣效果,但忘了為何在Handler處理會比較好

try {
Thread.sleep(60);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}


}

progress.dismiss();
}
}


private class MyHandler extends Handler{

@Override
public void handleMessage(Message msg)
{
progress.setProgress(msg.what);//傳入參數設定長條bar的值
if(msg.what==progress.getMax()){
progress.dismiss();

}
}

}


五、自訂View並將View鑲嵌進Toast,變成自訂Toast

利用context提供的method getLayoutInflater建立自訂view
LayoutIflater inflater= getLayoutInflater()



private void showMyToast(int status , String info){

LayoutInflater inflater = getLayoutInflater();
//Activity的method
//將自己設計的layout轉成View

View layout = inflater.inflate(R.layout.mytoast, (ViewGroup)findViewById(R.id.root));
//R.id.root是xml中layout的id
//將xml檔mytoast裡面的ViewGroup(Layout及其元件)轉成View
//setContentView(layoutID)會直接將layout貼上畫面


ImageView img = (ImageView)layout.findViewById(R.id.img);
TextView msg= (TextView)layout.findViewById(R.id.msg);

//注意Img跟msg是屬於變數layout裡面的
//所以是layout之中findview,不是MainActivity findview


switch(status){

case 1:

img.setImageResource(R.drawable.warning);
break;

case 2:
img.setImageResource(R.drawable.warning);
break;

default:
img.setImageResource(R.drawable.warning);
break;


}

msg.setText(info);
//TextView mag秀出文字

Toast toast = new Toast(this);

toast.setView(layout);//將自訂view放入toast
toast.setGravity(Gravity.CENTER_VERTICAL, 0, 100);
//(,xoffset,yoffset)
//設置toast的位置

toast.setDuration(Toast.LENGTH_SHORT);
toast.show();

}


六、另一種自訂View

另一種自訂View是將java鑲嵌到layout檔案
在java檔案中寫class繼承view
在layout寫
<com.example.signature.MainPanel  

 />

2013年4月11日 星期四

android 資料儲存data storage

SharedPreference:


儲存基本型態的資料
如果應用程式使用的資料量不大
那麼可以考慮用SharedPreference

應用:
遊戲的紀錄
聲音開與關
等程式相關狀態


用SharedPreference創立的資料只限於該應用程式使用
當然可以在getSharedPreferences設定公開檔案給其他應用程式使用
SharedPreferences sp = getSharedPreferences("YYP.dat",MODE_PRIVATE);

以XML格式將資料存放到/data/data/com.example.fishingmapmaker/shared_prefs/之下

如果在實體手機操作那麼
/data必須是root權限才可以讀取





public class MainActivity extends Activity {

private Button click1, click2, click3;
private TextView tv, tv2, tv3;
private EditText iodata1, iodata3;

private SharedPreferences sp;
//宣告sharedpreference物件
private SharedPreferences.Editor editor;
//宣告sharedpreference編輯器

private String username;
private int stage;
private boolean sound;


protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

sp = getSharedPreferences("YYPdata", MODE_PRIVATE);
         //getSharedPreferences是context裡面的method
                //建立sharedpreference儲存資料的檔案   並宣告存取權限為只限於本程式閱讀

editor= sp.edit();
//調出sharedpreference編輯器

click1 = (Button)findViewById(R.id.click1);
tv = (TextView)findViewById(R.id.tv);

click2 = (Button)findViewById(R.id.click2);
tv2 = (TextView)findViewById(R.id.tv2);
iodata1 = (EditText)findViewById(R.id.iodata1);

click3 = (Button)findViewById(R.id.click3);
tv3 = (TextView)findViewById(R.id.tv3);
iodata3 = (EditText)findViewById(R.id.iodata3);



click1.setOnClickListener(new OnClickListener(){

@Override
public void onClick(View arg0) {
savePreference();
}
});
readPreference();
click2.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
saveInnerData();
}
});

readInnerData();

click3.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
saveSDData();
}
});

readSDData();


}


private void savePreference(){
editor.putBoolean("sound", false);//每個資料型態都有對應的method
editor.putString("username", "Brad");//存進檔案
editor.putInt("stage", 118);

editor.commit();//務必要寫這行,才會將資料存進檔案
readPreference();

}


private void readPreference(){
username = sp.getString("username", "nobody");//讀取sharedpreference的儲存內容
stage=sp.getInt("stage", 0);
sound=sp.getBoolean("sound", true);

tv.setText("UserName: " +  username + "\n" +
"Sound: " + (sound?"On":"Off") + "\n" +
"Stage: " + stage);

}

private void saveInnerData(){
String data = iodata1.getText().toString();//EditView的輸入文字記得要在末端加上toString(),因為getText()是View型態

try{
FileOutputStream fout

FileOutputStream fout = openFileOutput("YYP.dat",MODE_PRIVATE);
FileOutputStream fout= new FileOutputStream("YYP.dat");//錯誤寫法 filenotfound
//在純翠java 會預設純到專案跟目錄 

fout.write(data.getBytes());//因為檔案皆為字串所以要將字串型別轉成byte型式

fout.flush();
fout.close();
Toast.makeText(this, "save OK", Toast.LENGTH_SHORT).show();
readInnerData();

}catch(IOException e){

Toast.makeText(this,"IO Exception", Toast.LENGTH_SHORT).show();
}

}
private void readInnerData(){

try{
// FileInputStream fin = new FileInputStream("YYP.dat");//出現fileNotFoundException
FileInputStream fin = openFileInput("YYP.dat");
BufferedReader reader = new BufferedReader(new InputStreamReader(fin));
String line;
while((line=reader.readLine())!=null){
tv.append(line+"\n");


}

fin.close();
}catch(IOException e){

Toast.makeText(this,"save ok",Toast.LENGTH_SHORT ).show();
}



}


//讀取寫入SDcard

private void saveSDData(){
String data = iodata3.getText().toString();
try{
FileWriter writer = new FileWriter("/mnt/sdcard/brad.dat");

writer.write(data);
writer.flush();
writer.close();

}catch(IOException e){

e.printStackTrace();

}

}


private void readSDData(){
try{
BufferedReader reader = new BufferedReader(new FileReader("/mnt/sdcard/brad.dat"));
String line;
while((line=reader.readLine())!=null){
tv3.append(line+"\n");

}
reader.close();
}catch(Exception e){


}

}


}





InnerStorage:

inner storage儲存在/data/data/com.example/files/之下


SDcardStorage
將資料儲存在SDcard

2013年4月10日 星期三

android Tiemrtask

除了extends Thread 、implement Runnable之外
也可以用timertask物件啟動執行緒

並且可以採用Button按下去會執行多個執行緒


在一般java swing可以直接在thread 的run()中直接操控UI
但是在android不行
必須裡用handler傳遞message操控UI


private Timer timer;
pirvate MyHandler handler;
timer.schedule(timertask,什麼時候執行,執行時間長度);





private void Click3(){
timer = new Timer();
// timer.schedule(task, when, period)
timer.schedule(new MyTask(),0,1000);
//第零秒後執行my task物件,持續執行一千秒,每秒執行一次
}

private class MyTask extends TimerTask{
int i;
@Override
public void run() {
Log.i("YYP","i = "+i++);
// tv.setText("i = "+i++);
//在android裡面thread不可以直接操控UI否則會出現
//04-10 23:31:45.967: W/dalvikvm(399): threadid=7: thread exiting with uncaught exception (group=0x4001d800) 04-10 23:31:46.009: E/AndroidRuntime(399): FATAL EXCEPTION: Timer-0 //04-10 23:31:46.009: E/AndroidRuntime(399): android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. 

//要操控UI必須用handler物件傳遞Message
handler.sendEmptyMessage(i++);
//handler.sendEmtyMessage(what);
}
}

//handler必須宣告,UI所在的activity之中。
private class MyHandler extends Handler{

//reciev Message
@Override
public void handleMessage(Message msg) {
tv.setText("i="+msg.what);
}


}

//activity結束時,取消timer物件執行緒
//否則activity結束後timer物件仍會持續執行
public void finish(){
timer.cancel();
timer=null;
super.finish();


}

2013年4月8日 星期一

事件處理

Java事件處理採取"委派事件模式"(delegation event model)。
委派事件模式:當事件發生時,產生事件的物件(event source)會將此一"訊息"轉給"事件傾聽者"(event listener)處理的一種方式。

訊息:java.awt.event事件類別庫裡的事件物件。

ex:按下Button會觸發一個動作事件,java產生一個"事件物件",將事件物件傳遞給事件傾聽者,事件傾聽者再將事件物件的種類將工作指派給事件處理者。


一個程式裡面允許多個事件傾聽者,為了讓"產生事件的物件"知道要將事件訊息傳送到哪一個"事件傾聽者",我們必須先把"事件傾聽者"向產生事件的物件註冊(register)。

事件傾聽者由"包含事件來源者"的物件擔任。
該物件必須實作implements ActionListener事件處理介面



事件類別有很多種

每個事件類別都有相對應的事件傾聽者

事件處理者包在事件傾聽者介面中,事件處理者是一堆method。

2013年4月7日 星期日

Java UI

import java.awt.*;  //使用視窗物件Frame 必須Import

Frame frm = new Frame("Window Title");//建立視窗物件,附上標題
frm.setSize(100,200);
frm.setBackground(Color.blue);
frm.setLocation(200,300);//視窗的位置
frm.setVisible(true);//讓視窗印在螢幕上


或者是
class XXX extnds Frame{

XXX frm = new XXX();

frm.setTitle("");
frm.setSize(100,200);
frm.setLocation(200,300);
frm.setVisible(true);


}



import java.awt.*;

public class UITest {
    static Frame frm= new Frame("label class");
    static Label lab = new Label();
    //label亂碼問題
    //file→project property→endocing選x-windows-950或x-MS950-SCS
   //這是netBean解決方法
    static Button btn = new Button("click me");
    static Checkbox ckb1= new Checkbox("電腦",true);
    static Checkbox ckb2= new Checkbox("人腦");
    static Checkbox ckb3= new Checkbox("豬腦",true);
 
    static Checkbox ckb4= new Checkbox("劉邦");
    static Checkbox ckb5 = new Checkbox("蕭何");
 
 
    public static void main(String[] args) {
      frm.setLayout(null);//加上這行就可以看到原來視窗底色
        frm.setSize(400, 300);
        frm.setBackground(Color.pink);
        lab.setText("初出茅廬");
        lab.setBackground(Color.gray);
       //執行結果只會看到灰色占滿版面,因為awt預設版面配置
        //將物件放大到與視窗同樣大小
        lab.setAlignment(Label.CENTER);
 //       lab.setForeground(Color.red);
   lab.setForeground(new Color(0xE12A94)); //自己建立color物件 設定顏色        
        lab.setLocation(50, 60);//設定label大小 位置
        lab.setSize(100,50);//上面的frm.setLayout(null);再加上這兩行才會正確顯示label位置大小
        Font fnt = new Font("新細明體",Font.ITALIC+Font.BOLD,22);//自型、style、size
        lab.setFont(fnt);              
        frm.add(lab);
       // lab.setVisible(true);

     
        btn.setBounds(100, 120, 70, 50);
        btn.setForeground(Color.red);
        btn.setBackground(Color.green);
        frm.add(btn);
//==============複選的checkbox作法 ,個別建立checkbox物件=====//      
//        ckb1.setSize(100, 50);
//        ckb2.setSize(100,50);
//        ckb3.setSize(100, 50);
//        ckb1.setLocation(200, 160);
//        ckb2.setLocation(200,200);
//        ckb3.setLocation(200, 230);
     
        ckb1.setBounds(200, 160, 100, 50);
        ckb2.setBounds(200, 200, 100, 50);
        ckb3.setBounds(200, 230, 100, 50);
        frm.add(ckb1);
        frm.add(ckb2);
        frm.add(ckb3);
     
//=========單選的checkbox作法,建立checkbox群組物件,設定checkbox屬於群組物件      
    CheckboxGroup grp = new CheckboxGroup();
    ckb4.setBounds(300, 200, 100, 50);
    ckb5.setBounds(300, 230, 100, 50);
        ckb4.setCheckboxGroup(grp);//將ckb4設定為grp的群組物件
        ckb5.setCheckboxGroup(grp);
     
        ckb4.setState(true);//預設選取
     
        frm.add(ckb4);
        frm.add(ckb5);
     
        frm.setVisible(true);
     
    }
}


Panel物件:面板。屬於containner子類別。可以做版面配置。
可以放進Frame物件。一個Frame可容納多個Panel
Panel可放button edittext checkbox等componemt





import java.awt.*;

public class PanelTest {
    static Frame frm=new Frame("Panel class");
    static Panel pnl = new Panel(new GridLayout(3,3));
//宣告Panel物件,並帶入layout物件。3x3格的]GridLayout
    static Label lab= new Label("Hello",Label.RIGHT);//標籤文字靠右對齊

    public static void main(String[] args) {
       frm.setLayout(null);//取消Frame版面配置,否則無法正確設定frame內部元件的大小
     
        // frm.setSize(600, 500);
     
        frm.setBounds(300,50, 600, 500);
        frm.setBackground(new Color(0x00ff99));
        frm.setResizable(false);//視窗設為固定大小
   
     
        lab.setBounds(20, 40, 60, 40);
        lab.setBackground(Color.red);

        pnl.setBounds(20, 80, 300, 220);
        pnl.setBackground(Color.GRAY);
        for(int i=1;i<=9;i++){
        pnl.add(new Button(Integer.toString(i)));
     
        }
     
        frm.add(lab);
        frm.add(pnl);
        frm.setVisible(true);
    }
}