3.10. Cửa sổ chính

Trong bài học này, chúng ta sẽ tập trung chăm chút cửa sổ chính cho ứng dụng của mình.

Cho tới thời điểm này, chủ yếu là chúng ta vẫn chỉ tạo ra các cửa sổ cơ bản nhờ kế thừa lớp QWidget. Dù như vậy đã là thừa đủ với các ứng dụng nhỏ, thế nhưng theo kích thước tăng dần của các dự án, chúng ta vẫn cần đến những công cụ mạnh mẽ hơn để hỗ trợ.

Lớp QMainWindow được đặc biệt thiết kế để giúp tạo ra các cửa chính dành cho các chương trình phức tạp. Trong số những tính năng mà QMainWindow cung cấp cho chúng ta, có thể dễ dàng thấy được các tính năng liên quan đến thanh danh mục, thanh công cụ cũng như là thanh trạng thái.

Hãy cùng nhau tìm hiểu chúng hoạt động với nhau như thế nào trong bài học dưới đây !

Giới thiệu về QMainWindow

Lớp QMainWindow kế thừa trực tiếp từ lớp QWidget. Đây là widget thường mỗi chương trình chỉ sử dụng 1 lần và chỉ có tác dụng để thiết kế cửa sổ chính của ứng dụng.

Bởi vì những chương trình đơn giản thường không cần sử dụng đến QMainWindow, chúng ta trong bài học này sẽ giả dụ là đang làm việc với 1 chương trình khá phức tạp.

Cấu trúc của QMainWindow

Trước hết, chúng ta cần phải hiểu rõ cấu trúc của cửa sổ tạo ra bởi QMainWindow. Hãy cùng xem hình minh họa dưới đây.

1 cửa sổ chính có thể chứa tất cả các thành phần trên, tuy nhiên không có gì ép buộc chúng ta phải dùng tất cả chúng. Để xác định xem chúng ta cần dùng gì, hãy nghe giới thiệu qua về từng phần.

  • Menu Bar : đây là thanh danh mục, là nơi chúng ta đặt các danh mục như « Thay đổi », « Hiển thị » hay « Hỗ trợ », vv…
  • Toolbars : thanh công cụ. Ví dụ trong trường hợp của ứng dụng soạn thảo văn bản, chúng ta thường có các nút để tạo tệp mới, lưu tệp, vv…
  • Dock Widget : phức tạp và hiếm khi được sử dụng. Đây là phần không gian bao quanh cửa sổ chính, có thể dùng để chứa đựng các công cụ khác nhau. Ví dụ hay thấy về phần không gian này là bảng chứa các công cụ bút vẽ với tẩy chúng ta hay gặp ở các ứng dụng vẽ tranh.
  • Central Widget : phần trung tâm của cửa sổ, nơi chứa nội dung chính.
  • Status Bar : hoặc là thanh trạng thái, nơi hiển thị trạng thái hiện tại của chương trình, kiểu như « Đang xử lý », « Hoàn tất », vv…
Ví dụ về QMainWindow

Để dễ hình dung về các phần khác nhau của cửa sổ trong thực tế, hãy cùng quan sát ví dụ cửa sổ chương trình Qt Designer.

Trên cùng của cửa sổ, chúng ta dễ dàng nhận ra thanh danh mục : "File", "Edit", "Form",…

Ngay dưới đó, chúng ta có thanh công cụ với các biểu tượng khác nhau để tạo dự án, mở dự án cũ, lưu trạng thái, vv…

Xung quanh cửa sổ (chính xác là 2 bên trái, phải), chúng ta có các vùng chứa hay còn gọi là dock.Ở đây, chúng có nhiệm vụ là giúp ta chọn loại widget mà ta muốn sử dụng cũng như thay đổi giá trị các thuộc tính của 1 widget bất kỳ.

Ở trung tâm cửa sổ, phần màu xám chính là phần trung tâm. Khi chúng ta mở 1 đối tượng làm việc thì nó sẽ hiện ra ở đây. Vùng trung tâm này có thể hiển thị đồng thời nhiều đối tượng. Chúng ta sẽ nói về đặc điểm này sau.

Cuối cùng, ở phía dưới là thanh trạng thái. Nhưng Qt Designer không sử dụng tới nó, ít nhất là chúng ta cũng không thay có thông tin gì hiển thị ở đó.

Trong bài học này, chúng ta sẽ cùng thảo luận về những phần quan trọng và hay được dùng nhất, đó là thanh danh mục, thành trạng thái và vùng trung tâm. Vùng chứa xung quanh thì quá hiếm khi được sử dụng còn thanh trạng thái thì dễ sử dụng đến mức tôi không nghĩ có ai với trình độ các bạn sẽ gặp khó khăn thao tác với nó, nhất là khi đã đọc tài liệu hướng dẫn Qt.

Mã nguồn cơ bản

Trong phần tiếp theo của bài học, chúng ta sẽ tạo lớp riêng của chúng ta để thao tác với cửa sổ chính. Lớp này kế thừa trực tiếp tự QMainWindow. Đây cũng là phương pháp được dùng trong 99,99% trường hợp cần thao tác với QMainWindow.

Dự án của chúng ta sẽ bao gồm 3 tệp mã nguồn :

  • main.cpp : tệp chứa hàm main().
  • CuaSoChinh.h : định nghĩa lớp CuaSoChinh, kế thừa lớp QMainWindow.
  • CuaSoChinh.cpp : mã xử lý của lớp CuaSoChinh.

main.cpp

#include <QApplication>
#include <QtWidgets>
#include "CuaSoChinh.h"

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    CuaSoChinh cuaSo;
    cuaSo.show();
 
    return app.exec();
}

CuaSoChinh.h

#ifndef CUASOCHINH_H
#define CUASOCHINH_H
#include <QtWidgets>

class CuaSoChinh : public QMainWindow {
    public:
      CuaSoChinh();

    private:
};
#endif

CuaSoChinh.cpp

#include "CuaSoChinh.h"
CuaSoChinh::CuaSoChinh () {

}

Kết quả

Nếu không có vấn đề gì xảy ra, chúng ta phải nhận được kết quả là 1 cửa sổ trông như sau.

Nếu các bạn cũng nhận được kết quả tương tự thì mọi thứ đều ổn và chúng ta có thể bắt đầu.

Vùng trung tâm (SDI và MDI)

Vùng trung tâm của cửa sổ chính được thiết kế để chứa 1 và chỉ 1 widget. Cơ chế này giống với cơ chế chúng ta từng gặp ở QTabWidget. Vì thế chúng ta sẽ đặt vào trong đó 1 đối tượng QWidget hoặc thực thể của các lớp con của nó để dùng làm widget chứa, nếu cần, của tất cả các widget khác.

Chúng ta sẽ thực hành lại thao tác trên để chắc chắn là mọi người đều hiểu tôi đang nói đến điều gì.

Tuy nhiên, trước đó, chúng ta cần phân biệt 2 loại cửa sổ QMainWidget.

  • Giao diện 1 đối tượng hay SDI (Single Document Interface) : Nó chỉ cho phép hiển thị mỗi lần 1 đối tượng. Ví dụ có thể dễ dàng tìm thấy là phần mềm Notepad trong Windows.
  • Giao diện đa đối tượng hay MDI (Multiple Document Interface) : Bên trong nó có thể hiển thị đồng thời nhiều thực thể của đối tượng. Chúng ta nhìn thấy chúng dưới dạng nhiều cửa sổ con bên trong vùng trung tâm như trường hợp của Qt Designer.

Định dạng vùng trung tâm (kiểu SDI)

Chúng ta dùng đến phương thức setCentralWidget() của lớp QMainWindow để chỉ ra chúng ta muốn chứa widget nào trong vùng trung tâm. Câu lệnh này được đặt trong phương thức khởi tạo cảu lớp CuaSoChinh.

#include "CuaSoChinh.h"
CuaSoChinh::CuaSoChinh() {
    QWidget *vungTrungTam = new QWidget();
    setCentralWidget(vungTrungTam);
}

Chúng ta vẫn chưa thể thấy có gì khác biệt. Thế nhưng cần hiểu là bây giờ chúng ta đã có 1 đối tượng QWidget dùng để chứa các widget khác trong vùng trung tâm.

Tiếp đó, chúng ta có thể thêm vào đó các widget mà chúng ta muốn.

#include "CuaSoChinh.h"
CuaSoChinh::CuaSoChinh() {
    QWidget *vungTrungTam = new QWidget();

    QLineEdit *ho = new QLineEdit();
    QLineEdit *ten = new QLineEdit();
    QLineEdit *tuoi = new QLineEdit();

    QFormLayout *lop = new QFormLayout();
    lop->addRow("Họ :", ho);
    lop->addRow("Tên :", ten);
    lop->addRow("Tuổi :", tuoi);
    vungTrungTam->setLayout(lop);

    setCentralWidget(vungTrungTam);
}

Chúng ta đơn giản là sử dụng lại đoạn mã đã từng dùng trong bài học về lớp sắp xếp.

Đến giờ thì vẫn không có kết quả nào khác so với trước. Nhưng điều quan trong là các bạn đã biết cách làm sao để tạo ra 1 widget làm vùng trung tâm cho cửa sổ chính.

Định dạng vùng trung tâm (kiểu MDI)

Mọi thứ đương nhiên sẽ trở nên phức tạp hơn nhiều khi các bạn muốn tạo 1 chương trình kiểu MDI, ví dụ như trình soạn thảo mà các bạn có thể thực hiện quản lý nhiều tài liệu cùng lúc.

Để làm việc này, chúng ta sẽ cần đến QMdiArea, là 1 loại widget lớn, có khả năng chứa đựng bên trong nó nhiều cửa sổ nhỏ.

Vậy là, chúng ta sẽ đặt đối tượng QMdiArea vào vùng trung tâm của cửa sổ.

#include "CuaSoChinh.h"
CuaSoChinh::CuaSoChinh() {
    QMdiArea *vungTrungTam = new QMdiArea();
    setCentralWidget(vungTrungTam);
}

Thế là cửa sổ của chúng ta bây giờ đã có thể chứa đựng các cửa sổ con bên trong nó. Chúng ta sẽ tạo ra các cửa sổ con này nhờ phương thức addSubWindow() của QMdiArea. Phương thức này nhận tham số là widget mà cửa sổ con sẽ chứa bên trong nó.

Ở đây, chúng ta lại 1 lần nữa áp dụng kỹ thuật tạo ra 1 đối tượng QWidget để làm vật chứa cho tất cả các widget khác.

Để đơn giản hóa mọi thứ, trong ví dụ này, chúng ta sẽ chỉ yêu cầu các cửa sổ con chứa 1 trường QTextEdit.

#include "CuaSoChinh.h"
CuaSoChinh::CuaSoChinh() {
    QMdiArea *vungTrungTam = new QMdiArea();
    QTextEdit *truongVanBan1 = new QTextEdit();
    QTextEdit *truongVanBan2 = new QTextEdit();

    QMdiSubWindow *cuaSoCon1 = vungTrungTam->addSubWindow(truongVanBan1);
    QMdiSubWindow * cuaSoCon2 = vungTrungTam->addSubWindow(truongVanBan2);
    setCentralWidget(vungTrungTam);
}

Kết quả là chúng ta nhận được cửa sổ chính với nhiều cửa sổ con ở bên trong.

Các cửa sổ này có thể dễ dàng được phóng to, thu nhỏ tùy ý trong phạm vi cửa sổ chính. Chúng ta cũng có thể đưa cho từng cửa sổ con tiêu đề riêng cũng như biểu tượng riêng bằng cách dùng các phương thức quen thuộc setWindowTitle() với setWindowIcon(), vv…

Chỉ với vài dòng lệnh ngắn ngủi mà chúng ta cũng làm được nhiều thứ phết nhỉ !

Các bạn để ý rằng addSubWindow() trả về 1 con trỏ trên đối tượng QMdiSubWindow : con trỏ này trỏ lên cửa sổ con vừa được tạo ra. Tốt nhất là nên ghi nhớ con trỏ này bởi sau đó chúng ta có thể dùng nó để xóa cửa sổ với phương thức removeSubWindow().

Nếu không, bất cứ lúc nào chúng ta cũng có thể lấy ra danh sách các cửa sổ con nhờ phương thức subWindowList(). Phương thức này gửi trả kết quả là 1 danh sách QMdiSubWindow chứa trong QMdiArea.

Các danh mục

QMainWindow có thể hiển thị 1 thanh danh mục chứa các danh mục kiểu “Tệp”, “Thay đổi”, “Hiển thị”, “Hỗ trợ”, vv… Vậy làm sao để tạo ra chúng.

Tạo 1 danh mục cho cửa sổ chính

Thanh danh mục có thể được truy cập thông qua phương thức menuBar(). Phương thức này trả về 1 con trỏ trên đối tượng QMenuBar. Đối tượng này có 1 phương thức là addMenu() dùng để thêm các danh mục. Kết quả trả về của phương thức là 1 con trỏ trên đối tượng thuộc kiểu QMenu.

Ví dụ thực tế thì hơn xa là tốn nước bọt, vậy nên hãy cùng nghiên cứu đoạn mã sau đây.

#include "CuaSoChinh.h"
CuaSoChinh::CuaSoChinh() {
    QMenu *danhMucTep = menuBar()->addMenu("&Tệp");
    QMenu *danhMucThayDoi = menuBar()->addMenu("T&hay đổi");
    QMenu *danhMucHienThi = menuBar()->addMenu("&Hiển thị");
}

Chỉ vậy là chúng ta đã tạo ra 3 danh mục đồng thời có 3 con trỏ trỏ lên chúng (danhMucTep, danhMucThayDoidanhMucHienThi). Các bạn chắc vẫn nhớ dấu & dùng để chỉ định phím tắt cho thành phần tương ứng.

Vậy là bây giờ chúng ta sẽ có cửa sổ với các danh mục như sau.

Thế nhưng các danh mục này lại không hiển thị gì cả. Đơn giản bởi đến giờ chúng nó vẫn chưa có thành viên nào.

Thêm các thành viên vào danh mục

Các thành viên của danh mục chính là các thao tác hay hành động (action). Lớp dùng để quản lý chúng là QAction.

? Tại sao tên lớp lại là QAction thay vì dễ hiểu hơn như QSubMenu để đại diện cho danh mục con ?

Thực ra, QAction là các thành phần của các danh mục nói chung. Chúng ta vừa có thể dùng chúng cho các danh mục, vừa có thể dùng cho các công cụ trên thanh công cụ trong phần sau.

Lấy ví dụ thành phần “Tạo mới” cho phép tạo ra 1 mục tiêu làm việc mới, nằm trong danh mục “Tệp”. Chúng ta có thể có nhiều cách để sử dụng nó :

  • Trong danh mục Tệp > Tạo mới
  • Trên thanh công cụ, công cụ “Tạo mới” với biểu tượng là 1 tệp tin trắng.

Cùng 1 đối tượng QAction có thể dùng cho cả 2 thành phần trên.

Các lập trình viên Qt đã nhận ra các thao tác trong danh mục rất hay trùng lặp với các công cụ trên thanh công cụ. Vậy nên họ đã tạo ra lớp QAction dành cho cả 2 mục đích trên.

Để tạo 1 thao tác, chúng ta có 2 cách :

  • Tạo ra thao tác, rồi tạo ra thành phần trong danh mục tương ứng với nó.
  • Tạo trực tiếp thành phần trong danh mục rồi nhận về con trỏ trên đối tượng QAction vừa được tự động tạo ra.

Trong đoạn mã dưới đây, chúng ta thực hiện theo cách đầu tiên.

#include "CuaSoChinh.h"
CuaSoChinh::CuaSoChinh() {
    QMenu *danhMucTep = menuBar()->addMenu("&Tệp");
    QAction *thaoTacThoat = new QAction("Th&oát", this);
    danhMucTep->addAction(thaoTacThoat);
    QMenu *danhMucThayDoi = menuBar()->addMenu("T&hay đổi");
    QMenu *danhMucHienThi = menuBar()->addMenu("&Hiển thị");
}

Trong ví dụ trên đây, chúng ta trước tiên tạo ra 1 QAction tương ứng với thao tác « Thoát ». Tham số thứ 2 của phương thức khởi tạo là con trỏ lên cửa sổ chính (this), vốn là widget chứa của thao tác.

Sau đó chúng ta thêm thao tác vừa tạo ra vào trong danh mục « Tệp ».

Danh mục con

Các danh mục con cũng được quản lý bởi QMenu.

Hãy tưởng tượng rằng chúng ta sẽ tạo ra 1 danh mục con tên là « Tệp gần đây ». Danh mục con này là 1 danh sách các tệp được chương trình mở ra trong thời gian gần đây.

Thay vì sử dụng addAction() của QMenuBar, lần này chúng ta sẽ dùng đến addMenu().

QMenu *tepGanDay = danhMucTep->addMenu("Tệp &gần đây");
tepGanDay->addAction("Tệp nháp 1.txt");
tepGanDay->addAction("Tệp nháp 2.txt");
tepGanDay->addAction("Tệp nháp 3.txt");

Tiếp đó mới đến việc thêm các thao tác vào danh mục con.

Trong ví dụ này thì tôi không ghi nhớ lại con trỏ trỏ đến các thao tác được tạo ra. Trong thực tế thì việc này là cần thiết vì tiếp đó chúng ta sẽ cần kết nối tín hiệu mà chúng tạo ra với các slot để làm thành chuỗi hành động. Ở đây, để đơn giản mọi thứ nên tôi đã bỏ qua phần đó.

! Chúng ta cũng có thể dùng cách này để tạo nên các danh mục tình huống. Danh mục tình huống là các danh mục xuất hiện khi chúng ta kích chuột phải lên trên 1 widget nào đó. Xử lý nào có chút phức tạp hơn. Tôi để dành tài liệu lớp QWidget cho các bạn đọc để xem làm sao để tạo ra loại danh mục này khi chúng ta cần đến.

Thao tác nâng cao với QAction

1 đối tượng QAction được tạo thành từ ít nhất 1 đoạn văn bản nhỏ. Thế nhưng đấy không phải là tất cả những gì nó làm được.

Kết nối các tín hiệu với các slot

Chúng ta cần biết là các QAction tạo ra các tín hiệu mà chúng ta có thể dùng để kết nối với các slot. Lớp này tạo ra rất nhiều tín hiệu nhưng cái được sử dụng nhiều nhất có lẽ là triggered(), tín hiệu được phát ra khi người dùng chọn đối tượng.

Chẳng hạn chúng ta có thể kết nối thao tác “Thoát” với slot quit() của chương trình.

connect(thaoTacThoat, SIGNAL(triggered()), qApp, SLOT(quit()));

Vậy là khi chúng ta chọn thao tác Tệp > Thoát, chương trình sẽ kết thúc.

Ngoài ra, chúng ta cũng có tín hiệu hovered() được phát ra khi chúng ta trỏ con chuột lên thao tác.

Thêm phím tắt

Tương ứng với mỗi thao tác, chúng ta có thể gắn cho nó tổ hợp phím tắt. Chúng ta thực hiện điều đó qua phương thức addShortcut().

Có nhiều cách để sử dụng phương thức này nhưng dễ nhất là cung cấp cho nó tham số thuộc kiểu QKeySequence.

thaoTacThoat->setShortcut(QKeySequence("Ctrl+Q"));

Vậy là chỉ cần gọi phương thức tạo của lớp QKeySequence và Qt sẽ tự lo liệu để hiểu về tổ hợp phím tắt bạn muốn dùng. Bắt đầu từ giờ,  các bạn chỉ cần bấm tổ hợp phím CtrlQ là cửa sổ chương trình sẽ đóng do thao tác “Thoát” được gọi sử dụng.

Thêm biểu tượng

Mỗi thao tác có thể sở hữu 1 biểu tượng riêng. Khi là 1 thành phần nằm trong danh mục, biểu tượng của thao tác sẽ hiển thị ở phía bên trái. Tuy nhiên đừng quên là các thao tác sẽ còn được sử dụng trong thanh công cụ. Lúc đó chúng ta sẽ thấy tác dụng của việc có 1 biểu tượng riêng cho các thao tác.

Để thêm biểu tượng cho thao tác, chúng ta gọi phương thức setIcon() và cung cấp cho nó 1 tham số là đối tượng QIcon.

thaoTacThoat->setIcon(QIcon("thoat.png"));

Đánh dấu 1 thao tác

1 thao tác có thể ở 2 trạng thái : kích hoạt và không kích hoạt. Chúng ta có thể trao khả năng kích hoạt nó cho người dùng bằng cách dùng phương thức setCheckable().

Ví dụ chúng ta có thành phần Thay đổi > In đậm trong danh mục.

inDam->setCheckable(true);

Vậy là thành phần đó giờ đã có 2 trạng thái và có thể được kích hoạt. Khi được kích hoạt, chúng ta sẽ thấy có dấu tích ở bên trái.

Lúc này, chúng ta có thể kiểm tra xem thao tác có được kích hoạt không bằng isChecked().

Khi thao tác nằm trên thanh công cụ, chúng ta sẽ thấy là nút bấm tương ứng với thao tác này sẽ ở trạng thái bị ấn khi thao tác được kích hoạt. Đây chính là điều các bạn hay thấy trong trình soạn thảo văn bản kiểu Microsoft Word.

Đây là những kiến thức chính cần nắm được về danh mục. Từ này đến giờ, đã mấy lần tôi đề cập đến thanh công cụ. Giờ là lúc thực sự thảo luận về nó.

Thanh công cụ

Thanh công cụ thường là tập hợp của các biểu tượng, nằm bên dưới thanh danh mục.

Như đã nói bên trên, trong Qt, thanh công cụ cũng giống như danh mục được tạo thành từ các thao tác. Vì chúng ta vừa mới nói chưa dứt lời về các thao tác ở phần trên, tôi không nghĩ sẽ có khó khăn gì khi chúng ta xây dựng thanh công cụ trong phần này.

Để thêm thanh công cụ vào trong cửa sổ chính, chúng ta dùng phương thức addToolBar() của QMainWindow. Cũng giống như với các danh mục, các thao tác được thêm vào thanh công cụ thông qua addAction(). Phương thức này nhận vào tham số là 1 đối tượng QAction.

Ưu điểm của QAction sẽ được thể hiện ra ở đây khi chúng ta có thể trực tiếp sử dụng những thao tác đã được tạo ra trước đấy dành cho danh mục để thêm vào thanh công cụ.

#include "CuaSoChinh.h"
CuaSoChinh::CuaSoChinh() {
    QMenu *danhMucTep = menuBar()->addMenu("&Tệp");
    QAction *thaoTacThoat = new QAction("Th&oát", this);
    thaoTacThoat->setShortcut(QKeySequence("Ctrl+Q"));
    danhMucTep->addAction(thaoTacThoat);

    QMenu *danhMucThayDoi = menuBar()->addMenu("T&hay đổi");
    QMenu *danhMucHienThi = menuBar()->addMenu("&Hiển thị");

    QToolBar *thanhCongCuTep = addToolBar("Tệp");
    thanhCongCuTep->addAction(thaoTacThoat);

    connect(thaoTacThoat, SIGNAL(triggered()), qApp, SLOT(quit()));
}

Trong ví dụ trên, chúng ta đã tạo ra 1 thao tác để thêm vào danh mục rồi dùng lại nó sau đấy để xây dựng thanh công cụ.

1 mũi tên trúng 2 con chim B-)

Thêm 1 widget

Các thanh công cụ thường chứa các QAction nhưng đấy không phải là tất cả. Đôi khi chúng ta cần chèn những widget khác hơi phức tạp hơn 1 chút.

Trong thực tế, thật may là QToolBar hỗ trợ tất cả các loại widget.

Chúng ta có thể thêm các widget vào thanh công cụ nhờ phương thức addWidget() giống như chúng ta vẫn hay làm với các lớp sắp xếp.

QFontComboBox *phongChu = new QFontComboBox();
congCuTep->addWidget(phongChu);

Chúng ta vừa thực hiện chèn 1 hộp danh sách thả. Widget này sẽ được thêm vào thanh công cụ.

! Phương thức addWidget() tự động tạo ra 1 đối tượng QAction. Nó trả về kết quả là 1 con trỏ trên đối tượng QAction đó. Ở đây chúng ta không ghi nhớ lại con trỏ.Nhưng giống như mọi khi, nếu các bạn cần thực hiện thao tác gì đó với đối tượng QAction vừa được tạo ra, tốt nhất là nên ghi nhớ nó.

Thêm vào vách ngăn

Khi mà thanh công cụ trở nên quá lớn và chứa nhiều thành phần khác nhau, chia nhỏ nó thành các nhóm ngăn cách nhau bởi các vách ngăn là 1 ý tưởng không tồi. Qt hỗ trợ chúng ta làm việc này với các đối tượng gọi là separators (nghĩa là vách ngăn).

Chúng ta chỉ cần gọi phương thức addSeparator() ở nơi mà chúng ta muốn tạo ra vách ngăn là được.

congCuTep->addSeparator();
Tóm tắt bài học :
  • QMainWindow dùng để tạo ra các cửa sổ chính. Nó có thể chứa các cửa sổ con, thanh danh mục, thanh công cụ, thanh trạng thái, vv…
  • 1 cửa sổ SDI là cửa sổ thao tác với 1 đối tượng mỗi lần. 1 cửa sổ MDI cho phép thao tác đồng thời nhiều đối tượng trong nhiều cửa sổ con.
  • Thanh công cụ có thể chứa tất cả các loại widget.
  • Thanh công cụ và danh mục đều có cấu tạo chủ yếu từ các thành phần QAction. 1 đối tượng QAction vừa có thể dùng trong danh mục, vừa có thể đồng thời dùng trong thanh công cụ.