3.2. Biên dịch chương trình cửa sổ đầu tiên

Tôi có 1 tin tức tốt dành cho các bạn : sự kiên trì của các bạn cuối cùng cũng được đền bù xứng đáng.

Trong bài học này, chúng ta sẽ viết chương trình đầu tiên sử dụng Qt và các bạn sẽ có cơ hội tạo ra cửa sổ chương trình đầu tiên của mình.

Chúng ta sẽ chuyển IDE từ Code::Block sang Qt Creator vì nó giúp việc phát triển chương trình sử dụng Qt trở nên dễ dàng hơn. Đừng lo, chúng ta sẽ cùng nhau tìm hiểu cách sử dụng Qt Creator ngay sau đây.

Giới thiệu Qt Creator

Qt Creator mà chúng ta đã cài đặt cùng với Qt trong bài học trước là IDE lý tưởng nhất để làm việc với các dự án Qt. Nó sẽ giúp chúng ta tránh được phải thực hiện những cài đặt không cần thiết và bắt tay ngay vào viết chương trình của chúng ta.

Hình ảnh dưới đây là cửa sổ giao diện chính của IDE này.

Tạo dự án Qt mới

Chúng ta sẽ tạo 1 dự án mới qua thanh công cụ File > New File or Project. Chương trình đưa ra cho chúng ta khá nhiều lựa chọn về kiểu dự án mà chúng ta muốn thực hiện : ứng dụng giao diện đồ họa máy tính, ứng dụng di động, vv… Bới vì chúng ta vừa bắt đầu, tôi đề nghị tạo 1 dự án trống, như thế sẽ dễ dàng hơn cho chúng ta làm quen dần dần.

Các bạn sẽ chọn Other Project > Empty qmake Project.

Quá trình tạo dự án sẽ được hướng dẫn bởi Qt Creator.

Tôi đặt tên dự án của mình là « test » nhưng các bạn có thể chọn 1 cái tên khác nếu muốn.

Sau đó IDE sẽ hỏi bạn muốn dùng gói biên dịch nào của Qt. Trước mắt, chúng ta cứ sử dụng những lựa chọn mặc định mà IDE đề nghị.

Cuối cùng, cửa sổ tiếp theo sẽ yêu cầu chúng ta 1 số thông tin hơi lạ về trình quản lý phiên bản.

Chúng ta có thể liên kết dự án của chúng ta với 1 hệ thống quản lý phiên bản như SVN hay Git. Đây là những công cụ khá hữu hiệu đặc biệt là khi nhiều người cùng thao tác trên 1 khối mã nguồn. Tạm thời thì chúng ta sẽ không để ý đến chúng, các bạn hãy ấn « Finish ».

Thế là 1 dự án trống đã được tạo ra.

Dự án chỉ bao gồm 1 tệp .pro. Tệp này là tệp của Qt dùng để tùy chỉnh dự án khi chúng ta muốn biên dịch chương trình.

Thêm tệp main.cpp

Chúng ta cần phải có ít nhất 1 tệp main.cpp để có thể bắt đầu chương trình.

Để thêm tệp này vào dự án, các bạn hãy chọn File > New File or Project > C++ > C++ Source File và khi được IDE yêu cầu tên của tệp thì ghi main.cpp.

Và thế là tệp main.cpp đã được thêm vào dự án.

Chúng ta sẽ bắt đầu đoạn mã của chúng ta trong tệp này.

Để biên dịch chương trình, các bạn chỉ cần ấn vào hình tam giác xanh trong cột bên trái hoặc sử dụng tổ hợp phím tắt Ctrl+R.

Lập trình cửa sổ đầu tiên
Đoạn mã tối thiểu của ứng dụng Qt

Các bạn hãy thêm đoạn mã sau vào tệp main.cpp.

#include <QApplication>
int main(int argc, char *argv[]){
   QApplication app(argc, argv);
   return app.exec();
}

Đây là đoạn mã tối thiểu cần phải có của 1 ứng dụng sử dụng Qt.

Như các bạn có thể thấy là nó thật sự rất ngắn. So sánh với những thư viện khác đòi hỏi nhiều dòng mã trước khi chúng ta có thể bắt đầu viết chương trình, Qt khá là nhanh và đơn giản.

Sau đây, chúng ta sẽ cùng phân tích để hiểu từng dòng của đoạn mã này.

Thêm gói QApplication

#include <QApplication>

Ban đầu thì đây là gói duy nhất chúng ta cần bao gồm thêm vào chương trình. Các bạn có thể quên iostream đi vì với Qt thì nó không còn cần thiết với chúng ta nữa.

Hãy chú ý là tôi cố tình không thêm .h vào phía sau. Đây là hành động có chủ đích, vậy nên các bạn nên làm giống như thế.

Dòng mã bên trên cho phép chúng ta sử dụng lớp QApplication, là lớp cơ bản của tất cả các ứng dụng dùng Qt.

Lớp cơ bản QApplication

QApplication app(argc, argv);

Câu lệnh đầu tiên trong main() dùng để tạo ra 1 đối tượng QApplication. Đối tượng này tên là app nhưng các bạn có thể chọn 1 cái tên khác nếu muốn. Phương thức tạo của QApplication yêu cầu chúng ta phải cung cấp cho nó các tham số của chương trình, nghĩa là các tham số argcargv mà hàm main() đã nhận vào. Việc này cho phép chương chương bắt đầu chạy với 1 số tùy chỉnh. Tuy nhiên chúng ta sẽ chưa sử dụng đến chúng vội.

Chạy ứng dụng

return app.exec();

Dòng lệnh này thực hiện 2 xử lý :

  1. Gọi phương thức exec() của đối tượng app. Phương thức này sẽ khởi động chương trình của chúng ta và hiện ra các cửa sổ. Nếu các bạn không làm thế, chương trình sẽ không thực hiện gì cả.
  2. Trả về kết quả của phương thức exec() để thông báo là chương trình diễn ra bình thường hay không. Lệnh return được gọi ở cuối của hàm main(), cũng là cuối của chương trình.

Trong 1 câu lệnh nhưng thật ra có rất nhiều xử lý diễn ra. Các bạn cần nhớ là, chương trình của các bạn chỉ bắt đầu hoạt động kể từ dòng lệnh này. Trên thực tế, phương thức exec() được quản lý bởi Qt để cho phép chương trình được bắt đầu khi phương thức này được gọi thực hiện. Khi phương thức exec() kết thúc xử lý thì chương trình cũng kết thúc.

Hiển thị 1 widget

Trong phần lớn các thư viện GUI, bao gồm cả Qt, các thành phần đồ họa của của sổ được gọi là widget. Tôi sẽ không dịch từ này ra tiếng Việt vì khó tìm được từ tương ứng nhưng 1 số người khác có thể sử dụng “các điều khiển” để chỉ các thành phần này.

Các nút bấm, các ô chọn, các hình ảnh, vv… đều là các widget. Thậm chỉ cả bản thân cửa sổ cũng được coi là 1 widget.

Để gọi hiển thì của 1 cửa sổ, chúng ta chỉ cần yêu cầu hiển thị bất kỳ 1 widget nào đó, ví dụ như 1 nút bấm.

Đây là ví dụ mà tôi muốn các bạn sử dụng. Trong này có đoạn mã tối thiểu mà chúng ta đã nhắc đến bên trên, thêm vào đó là 1 số dòng lệnh để hiển thị 1 nút bấm.

#include <QApplication>
#include <QPushButton>

int main(int argc, char *argv[]){
   QApplication app(argc, argv);

   QPushButton nutBam("Xin chào Tân Binh !");
   nutBam.show();

   return app.exec();
}

Các bạn có thể dễ dàng nhận thấy là chúng ta đã thêm vào 3 dòng.

#include <QPushButton>

Dòng lệnh này cho phép chúng ta làm việc với các đối tượng QPushButton, chính là các nút bấm. Các bạn sẽ thấy là tên của các lớp của Qt luôn bắt đầu bằng Q.

QPushButton nutBam("Xin chào Tân Binh !");

Chúng ta tạo ra 1 đối tượng QPushButton và đắt tên là nutBam. Phương thức khởi tạo của lớp này cho phép nhận vào 1 chuỗi ký tự làm nhãn hiển thị bên trên nút.

Tuy nhiên thì việc tạo ra 1 nút bấm thì sẽ không hiển thị nút bấm đấy ra màn hình nên chúng ta sẽ cần gọi đến phương thức show().

nutBam.show();

Dòng lệnh này hiển thị nút bấm mà chúng ta đã tạo ra màn hình. Bởi vì nút bấm không thể tự nhiên lơ lửng trên màn hình của bạn, Qt sẽ tự động tạo ra 1 cửa sổ để chứa nó. Vậy là chúng ta có 1 cửa sổ chương trình chỉ chứa 1 nút bấm.

Các bạn cần hiểu rằng trong 1 chương trình thực tế thì chúng ta phải tạo ra cửa sổ trước rồi mới thêm dần các widget vào trong đó. Ở đây, chúng ta đã làm tắt đi 1 số bước vì ví dụ khá đơn giản.

Chạy đoạn mã

Khi mã nguồn đã sẵn sàng, làm cách nào để chúng ta thử nghiệm nó ?

Để có thể biên dịch cửa sổ, trước tiên chúng ta cần phải thực hiện vài cấu hình nho nhỏ của Qt. Thực tế, chúng ta sẽ phải thông báo là chúng ta muốn sử dụng module QtWidget để hiển thị các cửa sổ. Đây là 1 module phụ trách 1 tính năng của Qt như tôi đã từng nhắc đến trong bài trước.

Chúng ta cần phải thay đổi tệp .pro của dự án. Đây là nội dung tệp mà chúng ta có ban đầu, trong đấy chứa danh sách các tệp của dự án.

SOURCES += \   
    main.cpp

Chúng ta sẽ cần thêm vào dòng QT += widgets để yêu cầu Qt nạp module QtWidget.

QT += widgets

SOURCES += \
    main.cpp

Tiếp đó, để Qt chấp nhận thay đổi này của tệp .pro, chúng ta cần chạy 1 tiện ích nhỏ tên là qmake. Hãy ấn chuột phải vào tên dự án của bạn và chọn Run qmake.

! Các bạn sẽ không cần phải thay đổi tệp .pro và thực thi qmake thường xuyên. Ở đây, chúng ta cần làm thế để thực hiện 1 vài chỉnh sửa nho nhỏ. Trong phần tiếp theo, các bạn chỉ cần ấn Run là được.

Chúng ta sẽ biên dịch chương trình bằng cách ấn nút Run hình tam giác màu xanh lá cây.

Khi chương trình chạy, cái cửa sổ nhỏ của chúng ta sẽ xuất hiện 1 cách thần kỳ.

Chiếc nút chúng ta tạo ra sẽ có kích thước vừa đủ để chứa nhãn của nó. Cửa sổ được tạo ra tự động để chứa nút cũng chỉ có kích thước vừa đủ cho chiếc nút. Vậy nên chúng ta sẽ có 1 cửa sổ bé tí hin.

Thế nhưng chúng ta hoàn toàn có thể thay đổi kích thước cửa sổ này, thậm chí phóng lớn nó ra để chiếm hết màn hình. Trong trường hợp đó, nút bấm mà chúng ta tạo ra sẽ thay đổi kích thước, có thể trở nên rất lớn, để phù hợp với kích thước cửa sổ.

Chia sẻ chương trình

Để chạy thử chương trình với Qt Creator thì khá là dễ dàng, chỉ cần ấn lên nút tam giác xanh là đủ. Tuy nhiên nếu các bạn lấy tệp thực thi .exe được sinh ra khi biên dịch và gửi cho những người xung quanh để chia sẻ thì có thể chương trình sẽ không hoạt động trên máy họ. Lý do là để chạy chương trình này sẽ đòi hỏi máy mục tiêu phải có 1 số tệp DLL (Dynamic Link Library – tệp thư viện đường dẫn động của Windows) nhất định.

Các chương trình Qt cần có các tệp DLL đi kèm để có thể hoạt động được.

Khi chúng ta chạy thử chương trình với Qt Creator thì vị trí các tệp DLL đều được IDE biết trước nên chương trình có thể chạy mà không gặp phải vấn đề gì.

Thế nhưng nếu các bạn thử chạy chương trình bằng cách ấn vào tệp thực thi mà Qt đã tạo ra cho chúng ta (trong thư mục Debug trong build-**), chúng ta sẽ được chào đón bởi 1 thông báo lỗi.

Thực tế, nếu thiếu những tệp DLL này thì chương trình của chúng ta sẽ trở nên vô dụng. Vậy nên để có thể chạy trực tiếp được tệp thực thi này (hoặc thực thi nó trên máy những người khác), các bạn cần đặt tất cả các tệp DLL còn thiếu mà chương trình yêu cầu vào cùng 1 thư mục với tệp thực thi .exe. Các bạn có thể tìm thấy các tệp này trên ổ cứng tro thư mục mà các bạn đã cài đặt Qt.

Tùy từng trường hợp nhưng đôi khi chúng ta cần thêm vào khá nhiều DLL để chương trình có thể hoạt động được. Vậy nên thói quen của tôi là mỗi lần thêm từng tệp DLL thiếu được nêu trong thông báo cho tới khi chương trình có thể hoạt động bình thường.

! Qt Creator có thể hoạt động với nhiều trình biên dịch khác nhau, có thể là Mingw hoặc MS Visual C++. Ngoài việc có thể thay đổi trình biên dịch, chúng ta cũng có thể thay đổi chế độ biên dịch: Debug hoặc Release. Debug thích hợp cho các phiên bản thử nghiệm để kiểm tra lỗi. Còn các phiên bản chính thức để phân phối cho người dùng thì nên được biên dịch với chế độ Release. Các DLL đi kèm thay đổi tùy chế độ dịch nên các bạn cần chú ý. Các DLL của chế độ Release thường nhẹ hơn những DLL tương tự cần thiết khi biên dịch chế độ Debug.

Cuối cùng thì các bạn cũng có thể chạy được tệp thực thi của chương trình mà mình tạo ra. Chú ý, khi gửi ứng dụng cho những người xung quanh hoặc tải lên mạng cho người dùng khác, hãy nhớ đính kèm các tệp DLL cần thiết. Điều này là rất quan trọng.

Tóm tắt bài học :
  • Qt Creator là 1 IDE được thiết kế chuyên biệt để phát triển các dự án Qt.
  • Qt Creator đơn giản hóa quá trình biên dịch vốn cần thao tác khá tinh tế của các ứng dụng Qt.
  • Tất cả các thành phần của cửa sổ được gọi là widget.
  • Các widget được đại diện bởi các lớp trong mã nguồn, ví dụ như lớp QPushButton là dành cho các nút bấm.
  • Khi chỉa sẻ 1 chương trình Qt với những người khác, chúng ta cần phải đính kèm các tệp DLL nếu muốn chương trình có thể chạy bình thường.