รูปปกบทความ ทำความรู้จัก Basic Widgets

1. 🎯 ตอนที่ 5: สร้างฟอร์มล็อกอินด้วย 3 ทหารเสือ Basic Widgets

2. 📖 เปิดฉาก (The Hook)

สวัสดีครับน้องๆ โปรแกรมเมอร์! กลับมาลุยกันต่อในซีรีส์ ลุยโปรเจกต์ Cross-Platform GUI ด้วย C++ และ Qt ครับ

ในตอนที่แล้วเราได้เรียนรู้วิธีการจัดหน้าจอ (Layout Management) กันไปแล้ว เปรียบเสมือนเราสร้างโครงสร้างและแบ่งห้องให้กับบ้านของเราได้สำเร็จ ทีนี้ก็ถึงเวลาเอา “เฟอร์นิเจอร์” เข้ามาตกแต่งในบ้านกันแล้วครับ!

เฟอร์นิเจอร์ในโลกของ Qt ก็คือสิ่งที่เราเรียกว่า Widget นั่นเองครับ ในอดีตการสร้างปุ่มสักปุ่มด้วย C++ บนระบบปฏิบัติการเพียวๆ เราต้องคำนวณการวาดสี่เหลี่ยม วาดเงา และดักจับการคลิกเมาส์เองทั้งหมด แต่โชคดีที่ Qt เตรียม Widget สำเร็จรูปมาให้เราใช้งานอย่างจุใจ โดยในบทนี้ พี่จะพาไปรู้จักกับ “3 ทหารเสือ” ที่เป็น Basic Widgets พื้นฐานที่สุดที่ทุกโปรแกรมต้องมี นั่นคือ QLabel, QLineEdit และ QPushButton พร้อมกับนำทั้งสามตัวนี้มาประกอบร่างกันเป็น “หน้าต่างล็อกอิน (Login Form)” แบบง่ายๆ กันครับ!

3. 🧠 แก่นวิชา (Core Concepts)

ในโลกของ Qt คลาสของ Widget ทุกตัวจะสืบทอดมาจากคลาสแม่ที่ชื่อว่า QWidget ทำให้มันมีคุณสมบัติพื้นฐานร่วมกัน เช่น การตั้งค่าขนาด สี หรือฟอนต์ แต่ 3 ทหารเสือที่เราจะพูดถึงวันนี้ มีหน้าที่เฉพาะตัวดังนี้ครับ:

  • QLabel (ป้ายข้อความ): ใช้สำหรับแสดงผลข้อความ (Text) หรือรูปภาพ (Image) บนหน้าจอแบบอ่านได้อย่างเดียว (Read-only) เปรียบเสมือนป้ายชื่อหน้าห้อง หรือข้อความบอกใบ้ว่าช่องนี้ต้องกรอกอะไร
  • QLineEdit (ช่องกรอกข้อความบรรทัดเดียว): เป็นกล่องให้ผู้ใช้พิมพ์ข้อความสั้นๆ ลงไปได้ เช่น ชื่อผู้ใช้ หรือรหัสผ่าน สามารถจำกัดความยาวของตัวอักษรได้ด้วยฟังก์ชัน setMaxLength()
  • QPushButton (ปุ่มกด): ปุ่มมาตรฐานสำหรับรับคำสั่งจากผู้ใช้ เมื่อผู้ใช้นำเมาส์ไปคลิก มันจะเปล่ง Signal ที่ชื่อว่า clicked() ออกมาให้เรานำไปผูกกับ Slot เพื่อสั่งงานโปรแกรมต่อไป

กระบวนท่าการดึงและกำหนดค่า: text() และ setText() สิ่งที่น้องๆ ต้องใช้บ่อยที่สุดในการทำงานกับ Widget เหล่านี้คือการอ่านและเขียนข้อมูลครับ

  • ถ้าต้องการ “ดึงค่า” ที่อยู่ในช่องกรอกข้อความ เราจะใช้ฟังก์ชัน text() ซึ่งจะคืนค่ากลับมาเป็นออบเจกต์ของคลาส QString (คลาสจัดการสตริงที่ทรงพลังของ Qt)
  • ถ้าต้องการ “ตั้งค่า” หรือเขียนข้อความลงไปบนป้ายหรือปุ่ม เราจะใช้ฟังก์ชัน setText(const QString &) เข้าไปแทนที่ครับ

ฟีเจอร์ลับสำหรับรหัสผ่าน: ในการทำฟอร์มล็อกอิน หากผู้ใช้พิมพ์รหัสผ่าน เราคงไม่อยากให้คนข้างๆ เห็นใช่ไหมครับ? QLineEdit มีไม้ตายที่เรียกว่า setEchoMode() โดยเราสามารถส่งพารามิเตอร์ QLineEdit::Password เข้าไป เพื่อเปลี่ยนตัวอักษรที่พิมพ์ให้กลายเป็นจุดสีดำหรือดอกจัน (Dot/Asterisk) ได้อัตโนมัติครับ

แผนภาพแสดงการดึงข้อมูลจาก QLineEdit เข้าสู่กระบวนการของ QPushButton

4. 💻 ร่ายมนต์โค้ด (Show me the Code)

เรามาดูตัวอย่างการประกอบร่าง 3 ทหารเสือให้กลายเป็น Login Form กันครับ ในตัวอย่างนี้พี่จะจำลองว่าเราออกแบบหน้าจอผ่าน Qt Designer และสร้างปุ่ม Login ไว้เรียบร้อยแล้ว จากนั้นเราจะมาเขียนลอจิก C++ เพื่อดักจับ Event การคลิกกันครับ

#include "logindlg.h"
#include "ui_logindlg.h"
#include <QMessageBox> // สำหรับแสดงหน้าต่างแจ้งเตือน
#include <QDebug>

// ... [โค้ดส่วน Constructor] ...

// สล็อต (Slot) ที่จะทำงานเมื่อปุ่มถูกคลิก
void loginDlg::on_loginBtn_clicked() 
{
    // 1. ใช้ฟังก์ชัน text() ดึงค่าจาก QLineEdit มาเก็บไว้ใน QString
    // เคล็ดลับ: ใช้ trimmed() เพื่อตัดช่องว่าง (Space) ที่ผู้ใช้อาจเผลอพิมพ์ติดมาที่หัวหรือท้ายข้อความ
    QString username = ui->usrLineEdit->text().trimmed(); 
    QString password = ui->pwdLineEdit->text(); 

    qDebug() << "กำลังตรวจสอบผู้ใช้:" << username;

    // 2. ตรวจสอบเงื่อนไข Username และ Password (ในของจริงมักจะเช็กกับ Database)
    if (username == "admin" && password == "123456") 
    {
        // ถ้าถูกต้อง ให้เรียกฟังก์ชัน accept() เพื่อปิดหน้าต่างและส่งสัญญาณว่าล็อกอินสำเร็จ
        accept(); 
    } 
    else 
    {
        // ถ้าผิดพลาด ให้แสดงหน้าต่างแจ้งเตือน (QMessageBox)
        QMessageBox::warning(this, "Warning", "User name or password error!", QMessageBox::Yes);
        
        // 3. ใช้เคล็ดลับ UX: ล้างช่องข้อมูลและเด้งเคอร์เซอร์กลับไปที่ช่อง Username
        ui->usrLineEdit->clear(); // หรือใช้ ui->usrLineEdit->setText(""); ก็ได้
        ui->pwdLineEdit->clear(); 
        ui->usrLineEdit->setFocus(); 
    }
}

(อ้างอิงโค้ดลอจิกจาก)

5. 🛡️ เคล็ดลับจากคัมภีร์ลับ (Under the Hood / Pro-Tips)

ในฐานะ Senior พี่ขอหยิบข้อควรระวังและเคล็ดลับที่มักจะเจอบ่อยในหน้างานจริงมาฝากครับ:

  1. พลังของ trimmed(): น้องๆ สังเกตไหมครับว่าในโค้ดพี่ใช้ ui->usrLineEdit->text().trimmed() เสมอเมื่อรับค่า Username เพราะบ่อยครั้งที่ผู้ใช้ก็อปปี้ชื่อมาวางแล้วมี “ช่องว่าง” (Whitespace) ติดมาด้วย หากเราเอาไปเทียบกับค่าในระบบตรงๆ มันจะแจ้งว่ารหัสผิดทันที การใช้ trimmed() จะช่วยตัดช่องว่างหัวท้ายทิ้งให้โดยอัตโนมัติครับ
  2. จัดการหน่วยความจำผ่าน Parent-Child: เมื่อน้องๆ ใช้คำสั่ง new QPushButton(this); ตัวแปร this ที่โยนเข้าไปใน Constructor จะเป็นการบอกว่าหน้าต่างนี้คือ “แม่ (Parent)” ดังนั้นเมื่อหน้าต่างถูกปิดและถูกลบออกจากหน่วยความจำ Qt จะทำการกวาดล้าง Widget ลูกๆ ทั้งหมดให้เองโดยอัตโนมัติ ไม่ต้องมานั่งเขียน delete เองให้เสี่ยงต่ออาการ Memory Leak ครับ!
  3. การตั้ง Tab Order: สิ่งหนึ่งที่โปรแกรมเมอร์มือใหม่มักมองข้ามคือ User Experience (UX) ครับ เวลาผู้ใช้พิมพ์ Username เสร็จ เขามักจะกดปุ่ม Tab บนคีย์บอร์ดเพื่อเลื่อนเคอร์เซอร์ไปช่อง Password ทันที ใน Qt Designer น้องๆ สามารถกดโหมด Edit Tab Order เพื่อตั้งลำดับการโฟกัสของ Widget ให้เรียงจากบนลงล่างได้อย่างถูกต้อง

6. 🏁 บทสรุป (To be continued…)

เป็นอย่างไรบ้างครับกับ 3 ทหารเสือ QLabel, QLineEdit และ QPushButton เพียงแค่เรานำ Widget พื้นฐานเหล่านี้มาประกอบกัน และใช้คำสั่ง text(), setText() ร่วมกับกลไก Signals & Slots เราก็สามารถสร้างแอปพลิเคชันที่มีการโต้ตอบกับผู้ใช้แบบเบื้องต้นได้แล้วครับ

แต่เดี๋ยวก่อน! แอปพลิเคชันในโลกความเป็นจริงไม่ได้มีแค่ปุ่มหรือช่องกรอกข้อความเท่านั้น ในตอนต่อไป พี่จะพาไปรู้จักกับ Widget ระดับที่ซับซ้อนขึ้นอย่าง QComboBox (รายการแบบดรอปดาวน์) และ QCheckBox (กล่องทำเครื่องหมาย) ที่จะช่วยให้โปรแกรมของเรารับข้อมูลทางเลือกจากผู้ใช้ได้แม่นยำขึ้น ติดตามกันให้ดีนะครับ!


ต้องการที่ปรึกษาด้านการออกแบบสถาปัตยกรรมซอฟต์แวร์ C++ หรือระบบ Cross-Platform GUI ให้กับองค์กรของคุณ? ทีมงาน WP Solution พร้อมให้บริการออกแบบและพัฒนาซอฟต์แวร์แบบครบวงจร ดูรายละเอียดบริการของเราได้ที่: www.wpsolution2017.com หรือพูดคุยปรึกษาเบื้องต้นได้ที่ Line: wisit.p