Pages

แสดงบทความที่มีป้ายกำกับ javax.swing-series แสดงบทความทั้งหมด
แสดงบทความที่มีป้ายกำกับ javax.swing-series แสดงบทความทั้งหมด

วันจันทร์, เมษายน 11, 2554

Vavar ปะทะ Java Swing #5 : Component Painting

จาก ตอนที่ 4 ที่ได้พูดถึง EDT และ Swing MVC ไปแล้ว

ในตอนที่ 5 นี้เลยจะพูดถึง Painting ครับ

ประกาศ : บทความเหล่านี้เขียนด้วยความคิดเห็นของตัวเองล้วนๆ ... 
ผิดถูกยังไง สามารถเสนอแนะโดย post comment ด้านล่างได้ครับ :)




Swing Component หรือแม้แต่  AWT Component ใน Java นั้นสิ่งที่จำเป็นมากๆ
ในการออกแบบ UI ก็คือการทำ Custom Paint ที่ให้ LookAndFeel  ของตัว Component นั้น
เป็นอย่างที่เราได้ออกแบบไว้ ... โชคร้ายของ AWT Component ที่ ​Java ไม่ได้ออกแบบตรงจุดนี้มาให้
โดยให้เหตุผลว่า AWT เป็น Heavy Weight Class ที่ออกแบบมาให้เป็น Native Component ของ OS นั้นๆ
การจะปรับเปลี่ยน LookAndFeel สำหรับ AWT จึงไม่ใช่ทางออกนัก ....

แต่ก็เป็นโชคดีสำหรับ ​Swing Component ที่ Sun ทำ LookAndFeel Architecture มาให้ใช้
โดยตัว Swing เองอย่างที่เป็น Sequence Diagram ในตอนที่ 4 จะเห็นว่า
JComponent ทั้งหลายเปรียบเสมือน Controller เท่านั้น ส่วนที่เป็น View คือส่วนที่เป็น UI Class
ที่ฝังอยู่ใน LookAndFeel ....

ข้อดีของการแยก Class ดังกล่าวทำให้เราสามารถปรับเปลี่ยนหน้าตาของ UI
โดยไม่กระทบกับ Behavior ที่มีของ Component นั้นๆ ได้ ....
ยกตัวอย่างเช่น

ปุุ่ม .....
หน้าที่ของปุ่มคือรอรับ event การ click โดยจะ click ซ้าย หรือ ขวา ก็ขึ้นอยู่กับ
manage code ที่ทำการตอบรับ action นั้น

แน่นอนว่าหากการเปลี่ยน UI แล้วกระทบกับ Behavior ดังกล่าวดูจะแปลกๆ
ตั้งแต่ลักษณะการ Design ของ Behavior ก่อนหน้านี้แล้ว ....

การ Paint บน Swing Component จึงได้เปลี่ยนการทำงานใหม่ที่แตกต่างไปจาก AWT Component
ที่มีการเรียก paint() method แล้วทำการวาด Component ทั้งหมด

ใน Best Practice ของ Swing Component แนะนำว่าหากต้องการทำ Custom Paint ที่ไม่ขึ้นกับ
LookAndFeel ก็สามารถทำได้โดยการ override paintComponent() (ไม่มี s) method เพื่อให้สามารถ
แสดงผลได้อย่างที่เราต้องการ .....

สิ่งที่สำคัญสำหรับการ paint ใน Swing Component คงจะหนีไม่พ้น 3 สิ่งดังต่อไปนี้

1. Opaque - การแสดงผลแบบ Transparent Background.
2. Border - ขอบของ Component ที่ต้องการให้แสดงผล
3. Inset -  ขอบช่องว่างที่ต้องการให้แสดงผล มักจะถูก set จาก Border

ซึ่งหากเปรียบเทียบกับการเขียน CSS ทั้งสามส่วนนี้คงหนีไม่พ้น คำสั่งดังต่อไปนี้

1. background:
2. border:
3. padding:

จะเห็นได้ว่าจริงๆ แล้ว Component ของ Swing นั้นก็ไม่ได้แตกต่างจาก
การเขียน HTML เท่าไหร่นัก เพียงแต่การใช้งานจะต้องมีการจัด layout
เพื่อให้ได้รูปแบบตามที่เราต้องการ ได้ยากกว่าเท่านั้นเอง ...
แต่โชคร้ายของ Swing Component ที่ Sun ออกแบบมาไม่ดีนัก
ที่ระบุให้ Border เป็น Component ที่ถูกวาดหลังสุด ทำให้การที่เราจะทำ
Component ที่มีขอบ ตามประเภท Border ที่เรา assign ให้กับ Component นั้น ยากมาก
ซึ่งจะต้องหาวิธีมาประยุกต์ใช้เพื่อทำงานในลักษณะดังกล่าว ...

ทำให้มี trick มากมายในการประยุกต์ใช้เพื่อให้ได้รูปแบบตามที่เราต้องการ ....

โดยส่วนตัวคิดว่าไม่ค่อยดีนักสำหรับ การ open ให้ implement เยอะขนาดนี้ เพราะหาก
Developer ไม่สนใจที่จะอ่าน Architect ของ Swing จะทำให้การ ​Manage sourcecode นั้นลำบากมาก
ด้วยอายุของ Swing Toolkit ก็ปาไปเกือบ 10 ปี แล้วจึงคิดว่า javaFX น่าจะมีอะไรเปลี่ยนแปลง
ในจุดนี้ไม่มาก ... ก็น้อย ....

แต่ชีวิตก็ยังต้องดำเนินต่อไป  .... ไปเขียน silverlight ดีกว่า ๕๕๕

วันอาทิตย์, กุมภาพันธ์ 27, 2554

Vavar ปะทะ Java Swing #3 : Why Swing ?

UI สุดเมพ สมัย ป.โท ..
ประกาศ : บทความเหล่านี้เขียนด้วยความคิดเห็นของตัวเองล้วนๆ ... 
ผิดถูกยังไง สามารถเสนอแนะโดย post comment ด้านล่างได้ครับ :)

ตลอดเวลาที่นั่ง code มา 2-3 เดือน คอยถามตัวเองเสมอว่า
"ทำไมต้อง Swing ?"
"เขียน AWT อย่างเดิมไม่ดีกว่าเหรอ ?"

ก็เหมือนยังเป็นคำถามมาตลอดเวลาภายในหัวสมอง...
เหมือน ตัวมาร กะ ตัวดี ปะทะกันจนปวดหัวไปหลายๆ รอบ ...
แต่พอได้ ลงมือ เขียนจริงๆจังๆ พบว่า ...

ถ้าจะทำ Client GUI ... โดย Java ... ในขณะนี้ ...
คงมีเพียง Swing ที่เป็นคำตอบสุดท้าย ...

จริงๆ แล้วการทำ GUI ด้วย java
ก็ไม่ใช่เรื่องเลวร้ายซักเท่าไหร่ ...
แต่ต้องยอมรับอย่างนึงว่าช่วงตั้งแต่ JRE 1.4 - 1.5 ...
SUN ไปเน้นหนักทาง J2EE มากเกินไป ...
จน Java Desktop มันย่ำแย่ซะจน Developer หลายๆ คน
ตั้งเป็น slogan ให้ว่า

"จาวาค้างส์" 

กันเลยทีเดียว ...

ถ้าอยากรู้ว่ามัน "แย่" ขนาดไหนแนะนำให้รัน app
ที่เป็น JRE 1.5 กับ JRE 1.6 ครับ ... จะเห็นความแตกต่างอย่างรู้สึกได้ :)

อ้อ อีกอย่าง ... ไม่ได้สนับสนุนว่า "จาวาเร็วส์" นะครับ
และก็ไม่ได้เป็น zealot ด้วย .... กลับมาดู Swing ของเรากันต่อดีกว่า ...

ด้วยอายุของ Java Swing แล้ว ... คงปฎิเสธ ไม่ได้ว่าเป็น Techonology ที่ค่อนข้าง "เก่า"
เพราะมัน 10 ปี มาแล้ว ... แต่ยังแก่น้อยกว่าอย่าง MFC
ที่เป็น lib ของ Microsoft อยู่เยอะหน่อย :)

Firewall App บ้านๆ ที่เคยเขียนสมัย ป.ตรี (MFC + C++)

แต่หากด้วยใครเคยเขียน MFC มาบ้าง ก็จะรู้สึกทันทีว่าการเขียน GUI บน Java นั้น ...
ไม่ได้ยากเท่า MFC แต่อาจจะต้องใช้จินตนาการ นิดหน่อย
เพราะหากเขียน code แบบ AWT มันไม่มี Visual Tool ให้ดูขณะที่กำลังเขียน code อยู่ ...
ซึ่งใน Swing ก็มีให้อยู่พอสมควร ดังเช่น netbean หรือ window builder pro ...

โดยตัว Swing เองมีการใช้ MVC Framework เป็น Core Architect
อยู่ตรงกลางโดยแบ่งออกเป็น 3 ส่วนหลักๆ คือ

  1. Model
    ใช้ในการเก็บข้อมูลต่างๆ ไม่ว่าจะเป็น การ enabled / disabled
    หรือพูดง่ายๆ ว่า Attribute ทุกอย่างของ Component นั้นจะถูกเก็บอยู่ที่ Model ....
    อย่าง ปุ่ม ( JButton ) ก็จะมี ButtonModel ที่เก็บข้อมูลของปุ่มที่เราสร้างขึ้นนั้นไว้ ...
    เราสามารถเรียกข้อมูลจาก Model มาเพื่ออ่านค่า หรือเปลี่ยนแปลงค่าได้ ...
    ซึ่งการเรียกค่าต่างๆ นั้น จะต้องทำมาจาก Controller หากเราต้องการเปลี่ยนค่าภายใน Model โดยไม่ผ่าน Controller เราจำเป็นที่จะต้อง "Fire" หรือบอกให้ Controller รู้ด้วยว่า ...
    ค่าใน Model มีการเปลี่ยนแปลง ... Controller เองก็จะทำการดึงข้อมูลเพื่อให้
    View ทำการแสดงผลข้อมูลใหม่ให้ถูกต้อง ...  
  2. Controller
    หรือเรียกง่ายๆ ว่า Component ... ตัว Controller จะทำหน้าที่จัดการ
    "Behavior" หรือ User Input ต่างๆ ที่ สามารถกระทำกับ Component นั้นให้ได้ถูกต้องตามลักษณะ
    ยกตัวอย่างเช่น setEnabled หรือ setVisible จะเป็น "Behavior" ของ Component ทุกอันที่จะต้องมี ...
  3. View
    หรือที่เรียกอีกอย่างว่า UI ... การที่ Component จะทำงานได้ ไม่ได้ขึ้นอยู่กับว่าหน้าตาของ
    Component นั้น มีหน้าตาเป็นอย่างไร ... ตัวอย่างง่ายๆคือ ปุ่มแบบ Turn On/Off  ...
    เราอาจจะใช้ RadioButton แทนการใช้ Button ธรรมดาที่จะต้องมานั่งเขียน Code
    ในการเปลี่ยนสถานะปุ่มอื่นๆ ที่อยู่ภายใต้เงื่อนไขเดียวกันแทนก็ได้ ...

ซึ่งในการเปลี่ยน View หรือ UI นั้น ใน Swing เรียกว่า UI Delegate โดยมีลักษณะตาม
Sequence Diagram ข้างล่างนี้


จะเห็นได้ว่า แต่ละ Component จะมีการไปเรียกใช้ UIManager ซึ่งเป็น class กลางของ Swing ...
จึงทำให้เกิด Concept ที่เรียกว่า LookAndFeel ขึ้นมา ... ทำให้เราสามารถปรับเปลี่ยน UI
ได้อย่างที่เราต้องการ

สรุปแล้วโดย Architect ของ Swing เองก็ออกแบบ มาได้ค่อนข้างมีประสิทธิภาพมาก
มีความเป็น "Mature" UI ToolKit ที่เหมาะในการทำ Application พอสมควร ....

ซึ่งเนื่องจาก Application เดิม เป็น AWT Component ทั้งหมด จึงต้องมีภารกิจในการเปลี่ยน
ให้เป็น Swing เพื่อใช้ Architect ที่ว่านี้ ....
แล้วจะทำได้ยังไงบ้าง ? เจอกันตอนหน้าครับ :)