C++ là một ngôn ngữ lập trình đa mô thức (multiparadigm), biên dịch, định kiểu tĩnh. C++ hỗ trợ lập trình cấu trúc, lập trình hướng đối tượng, lập trình khái lược, lập trình hàm, siêu lập trình dựa trên khuôn hình (template metaprogramming).Tác giả đầu tiên của C++ là Bjarne Stroustrup, cái tên C++ có nghĩa là ngôn ngữ C++ được phát triển từ C. Tuy vậy C++ không phải là một mở rộng của C, và thực tế thì C vẫn có nhiều điểm không tương thích với C++ (chương trình viết bằng C nếu biên dịch bằng trình dịch C++ thì có thể sẽ có lỗi).
Trang 1Chương 1
Tổng quan về các vấn đề liên quan
1.1 Lập trình hướng đối tượng với C++
1.1.1 C++
C++ là một ngôn ngữ lập trình đa mô thức (multi-paradigm), biên dịch, định kiểu tĩnh C++ hỗ trợ lập trình cấu trúc, lập trình hướng đối tượng, lập trình khái lược, lập trình hàm, siêu lập trình dựa trên khuôn hình (template metaprogramming)
Tác giả đầu tiên của C++ là Bjarne Stroustrup, cái tên C++ có nghĩa là ngôn ngữ C++ được phát triển từ
C Tuy vậy C++ không phải là một mở rộng của C, và thực tế thì C vẫn có nhiều điểm không tươngthích với C++ (chương trình viết bằng C nếu biên dịch bằng trình dịch C++ thì có thể sẽ có lỗi)
1.1.2 C++11
Vào tháng 11/2011, ISO đã thông qua chuẩn C++11, thay thế cho chuẩn cũ là C++03 C++11 là sự thayđổi lớn của C++, bao gồm các thay đổi tron bản thân ngôn ngữ đến thay đổi trong thư viện chuẩn.Mục đích của C++11 là [1]:
• Đưa C++ trở thành ngôn ngữ tốt hơn cho lập trình hệ thống và xây dựng thư viện (thông qua một
số tính năng mới như thread, new memory model, pseudo-random number generation,
)
• Làm cho C++ dễ dạy và học hơn (nullptr, range-for, auto, override, )
Có thể tìm hiểu về những cái mới trong C++11 tại [2], [3
Bản nháp của chuẩn C++11 (miễn phí) tại http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf
Dưới đây, ta sẽ tìm hiểu một số tính năng mới của C++ mà sẽ được sử dụng nhiều trong BKPaint
Trang 21.1.2.1 nullptr - con trỏ null
Trong ngôn ngữ C, macro NULL được định nghĩa là (void*)0 Tuy nhiên, C++ lại không thể định nghĩatheo cách này, bởi vì C++ yêu cầu chuyển đổi kiểu tường minh từ void* sang kiểu con trỏ Ví dụ:
1
Sẽ sinh lỗi biên dịch
Do vậy, C++ định nghĩa NULL là 0, nhờ đó câu lệnh trên là hợp lệ
Tuy nhiên, cũng vì thể mà NULL được coi là một hằng nguyên thay vì hằng con trỏ, do đó:
Tham khảo: [4, section 4.10, pg 80]
1.1.2.2 auto - tự động suy diễn kiểu
Trong C++, kiểu của một đối tượng có thể rất dài Ví dụ:
1
2
int * a = NULL ;
void foo (char * ); // 1
void foo (int);
int a = nullptr; // illegal
std :: vector <int>:: iterator vi = v.begin(); for (; vi != v.end(); ++ vi) {
}
Trang 3// auto v; // Compile error
std :: vector <int> v; for (auto vi = v.begin(); vi != v.end(); ++ vi) {
Trang 4Với C++03 trở về trước, phép lặp qua một tập hợp, mảng, sử dụng iterator hoặc lặp theo chỉ sốmảng với cú pháp khá phức tạp C++11 cung cấp Range-for với chức năng tương tự như các ngônngữ khác:
cả các Container của STL đều có thể sử dụng được với Range-for
Range-for của C++11 cho phép tùy chọn kiểu của phần tử:
Tham khảo [4, section 6.5.4, pg 128]
Trang 5quan nhau, A::h() không phải là phương thức ảo Đây có thể là do lỗi của lập trình viên Lỗi này là lỗingữ nghĩa nên khi trình biên dịch không báo, rất khó để phát hiện ra.
C++11 cung cấp chỉ thị override cho phép khai báo tường minh một phương thức của lớp dẫn xuất sẽđịnh nghĩa lại phương thức ảo của lớp cơ sở
Bây giờ, khi biên dịch thì trình dịch sẽ báo lỗi ở khai báo phương thức B::g() và B::h() bởi vì trong lớp
cơ sở của B là A không có phương thức ảo nào có chữ ký giống với những phương thức này Nhờ vậy
mà có thể dễ dàng sửa lỗi
Chú ý: override không phải là một từ khoá mới, do đó vẫn có thể sử dụng override làm định danh, mặc
dù không được khuyến khích
Tham khảo: [4, section 10.3, pg 225]
1.2.1 Giới thiệu
Qt Framework là một bộ công cụ lập trình đa nền tảng dùng để phát triển các ứng dụng GUI cũng nhưcác ứng dụng dòng lệnh Chương trình Qt chỉ cần viết một lần sau đó có thể biên dịch trên nhiều nềntảng, nhiều hệ điều hành khác nhau mà hầu như không cần sửa lại mã nguồn Hiện nay Qt hỗ trợ các
hệ điều hành Linux, MacOS, Windows, Symbian, Meamo, Meego, Qt hiện đang thuộc bản quyềncủa Digia (http://qt.digia.com/) , được phân phối dưới 2 giấy phép khác nhau là giấy phép phầnmềm tự do mã nguồn mở (GPL v2) và giấy phép phần mềm độc quyền (Qt Commericial License) [5]Ngôn ngữ chủ yếu được sử dụng bởi Qt là C++ và QML (một ngôn ngữ script tương tự Javascript).Ngoài ra còn có thể lập trình sử dụng Qt bằng nhiều ngôn ngữ khác như D, Python,
Bản chính thức mới nhất của Qt là Qt 4.8.3
struct B : public A { void f() override;
void g() override; void h()
override;
};
Trang 61.2.2 Lập trình C++ với Qt
Chương trình C++ sử dụng Qt thực chất không phải là C++ chuẩn mà là một mở rộng của C++ Các file
mã nguồn sử dụng các cú pháp của Qt sẽ được dịch ra file mã nguồn C++ trước khi biên dịch bằngtrình dịch C++ như bình thường Chương trình làm nhiệm vụ này là moc (metaobject compiler).Nhờ vậy mà chương trình Qt có nhiều tính năng mới không có trong
C++ như Meta Object, Property, Signal-slot,
Hình 1.1 là sơ đồ quá trình biên dịch một Project Qt Ta thấy:
• Các file tiêu đề khai báo lớp (*.h) được vừa được bao gồm trong file cài đặt tương ứng, vừa đượcmoc dịch thành file cài đặt lớp mới (moc_*.cpp) Những file moc_*.cpp này thực chất là file càiđặt các phương thức riêng của lớp cần thiết cho các tính năng mở rộng của Qt,
• Các file mô tả giao diện chương trình (*.ui) được biên dịch thành file tiêu đề khai báo lớp (dạngui_*.h) File tiêu đề này khai báo một lớp Ui_* mới chứa các thành phần giao diện
cần thiết
• Các file mô tả tài nguyên (*.qrc) được biên dịch thành các file qrc_.cpp Nhưng file này chứa nộidung của các tài nguyên được mô tả trong các file qrc Như vậy, các tài nguyên này trở thành mộtphần của chương trình thay vì tách rời file thực thi riêng, file tài nguyên
riêng
• Các file cài đặt lớp (*.cpp) được biên dịch thằnh object như bình thường,
H ÌNH 1.1: Biên dịch một Project Qt
Trang 7• Các file object sau khi biên dịch sẽ được liên kết với nhau và với các thư viện ngoài cần thiết(trong đó có các thư viện của Qt) để tạo thành file thực thi.
Chỉ những lớp mà trong mô tả có macro Q_OBJECT mới được dịch bằng moc
Qt Framework bao gồm nhiều module như: QtCore, QtGui, QtNetwork, QtXml, Mỗi module baogồm nhiều lớp có nhiệm vụ liên quan đến nhau Các lớp có sẵn của Qt đều bắt đầu bằng chữ ’Q’, đa sốcác lớp đều có tổ tiên là lớp QObject Chi tiết về các module cũng như các lớp của Qt xem tại: http://doc.qt.digia.com/
1.2.3 Một số kỹ thuật hướng đối tượng trong Qt
1.2.3.1 Cơ chế cha-con
Các đối tượng thuộc lớp QObject và các lớp dẫn xuất được tổ chức thành các cây các đối tượng Mỗiđối tượng có thể có một đối tượng cha (parent) và nhiều đối tượng con (children) Trong destructorcủa lớp QObject có lời gọi hủy các đối tượng con Nhờ vậy mà người lập trình có thể tự do tạo đốitượng trên bộ nhớ heap mà không phải quan tâm đến vấn đề hủy đối tượng
Điều này rất có ích đối với các ứng dụng GUI VD: đối tượng mainWindow (cửa sổ chính) là gốc củacây, các đối tượng menuBar (thanh menu), toolBar (thanh công cụ) là con của mainWindow, cácbutton (nút bấm) là con của toolBar Khi mainWindow bị huỷ thì nó sẽ kéo theo các menuBar, toolBar
bị hủy Đến lượt mình, toolBar cũng hủy các button con của nó
Ngoài ra, trong khai báo lớp QObject thì destructor được khai báo là virtual nên cho dù con trỏmainWindow có được cast về QObject* thì lời gọi delete vẫn gọi đúng hàm hủy của lớpQMainWindow
1.2.3.2 Cơ chế signal - slot (tín hiệu - khe cắm)
Đây là một cơ chế giúp cho việc truyền thông điệp giữa các đối tượng trong Qt trở nên đơn giản hơn sovới nhiều Framework khác
Signal (tín hiệu) được một đối tượng "emit (phát ra)" trong quá trình tồn tại của nó Có thể là khinhận được một sự kiện từ bên ngoài, hay cũng có thể là bất cứ lúc nào mà người lập trình mongmuốn
Slot (khe cắm) thực chất là một phương thức của một đối tượng nào đó Slot giống như một phương
thức C++ bình thường ngoại trừ việc nó có thể được tự động gọi khi nhận được một signal nào đó với
điều kiện là trước đó đã được connect (kết nối)
Trang 8Chỉ có những lớp dẫn xuất của QObject mới có thể sử dụng signal và slot.
Ví dụ: Đối tượng button thuộc lớp QPushButton (nút bấm) có signal clicked() được emit khi ngườidùng bấm vào nút đó Ở đối tượng mainWindow thuộc lớp MainWindow (cửa sổ chính), nếu taconnect slot xử lý việc bấm nút buttonClicked() với signal QPushButton::clicked() thì khi ngườidùng bấm nút, phương thức buttonClicked() sẽ được thực hiện 1
Trang 9Xem thêm về signal, slot, connect, emit tại
http://qt-project.org/doc/qt-4.8/signalsandslots.html
Trang 10– Replay painting: nhóm các Use-case thực hiện lại các thao tác vẽ,
– Save: Lưu file,
– Open: Mở file,
– Undo/Redo: Undo / Redo
BKPaint BKPaint
user
Open file Save file Painting Replay painting Zoom Undo / Redo
H ÌNH 2.1: Biểu đồ Use-case tổng quát
Trang 11– Zoom: Phóng to, thu nhỏ
2.1.2 Phân rã Use-case
Painting
Hình 2.2 Các Use-case:
• Draw shape: Vẽ các hình đồ hoạ,
• Erase: Tẩy một phần của bức vẽ,
• Fill Area: Đổ màu
• Set painter: Thay đổi tùy chọn của đối tượng vẽ (nét vẽ, chổi lông, )
2.1.3 Phân ra Use-case Replay painting
H ÌNH 2.3: Phân rã Use-case Replay paintingHình 2.3 Các Use-case:
• Play: Bắt đầu quá trình replay cho đến kết thúc,
BKPaint BKPaint
Painting
H ÌNH 2.2: Phân rã Use-case Painting
BKPaint BKPaint
Replay painting
Trang 12• Pause: Tạm dừng quá trình replay, • Resume: Tiếp
tục quá trình replay,
• Stop: Kết thúc quá trình replay
Trang 132.2 Biểu đồ trình tự
Ở các biểu đồ trình tự dưói đây, đều xuất hiện một đối tượng đặc biệt gọi là GUI Thread Đây làthread chính của chương trình, quản lý các điều khiển trên nó, cũng như giao tiếp với người dùng Tất
cả các hàm xử lý sự kiện đều hoạt động trên thread này
2.2.1 Biểu đồ trình tự cho Use-case Open
load(filename)
reloadPlayer()
actionOpen() open
H ÌNH 2.4: Biểu đồ trình tự cho Use-caseOpen
Trang 14Khi người dùng yêu cầu mở một file một cửa sổ chính (MainWindow) sẽ được tạo ra (thực chất là 1tiến trình mới) độc lập với cửa sổ chính hiện tại và file được mở trên đó.
2.2.2 Biểu đồ trình tự cho Use-case Save
2.2.3 Biểu đồ trình tự cho Use-case Painting
2.2.3.1 Biểu đồ trình tự cho Use-case Draw shape
BKPaint hỗ trợ vẽ nhiều loại shape khác nhau (hình chữ nhật, hình elip, đa giác, ) với cách vẽ khácnhau Nhưng nhìn chung thì quá trình vẽ hình có trình tự kiểu như hình 2.6
User
openon_actionSave_triggered()Request filename
Trang 15H ÌNH 2.6: Biểu đồ trình tự cho Use-case Draw shapeTrong đó:
• Khi nhấn chuột tại một điểm thì sinh ra một thao tác vẽ kiểu MousePress,
• Khi di chuyển chuột thì tùy theo chế độ vẽ hiện tại mà sinh ra một thao tác vẽ có kiểu là lớp dẫnxuất của PaintOperation,
• Khi nhả chuột thì yêu cầu thêm một đối tượng kết thúc chuỗi các thao tác vẽ,
(Player::addFinishChangeShape())
Trang 162.2.3.2 Biểu đồ trình tự cho Use-case Erase
Khi nhấn chuột hoặc nhấn chuột và kèm theo di chuyển chuột, canvas sẽ tạo ra một thao tác Eraseđại diện cho việc xoá màn hình Và thực hiện thao tác đó
2.2.4 Biểu đồ trình tự cho Use-case Replay Painting
sd [ Erase ]
H ÌNH 2.7: Biểu đồ trình tự cho Use-caseErase
Trang 17:User : GuiThread :MainWindow :Player :Canvas : Timer
playNextOp()
start loop [ not end ]
timeout timerTimeout()
stop() ref [ Player.Stop ]
sd [ Replay ]
H ÌNH 2.8: Biểu đồ trình tự cho Use-caseReplay
Trang 18H ÌNH 2.9: Biểu đồ trình tự cho Use-case Pause
H ÌNH 2.10: Biểu đồ trình tự cho Use-case Resume
:User :GuiThread :MainWindow : Player :Canvas : Timer
pause on_actionPause_triggered()
pause()
stop
sd [ Pause ]
User : : GuiThread : MainWindow : Player :Timer
resume on_actionResume_triggered()
resume()
start
sd [ Resume ]
Trang 192.2.5 Biểu đồ trình tự cho Use-case Undo / Redo
:User : GuiThread :MainWindow : Player :Canvas : Timer
stop
on_actionStop_triggered()
stop()
stop stopPlayer()
setMode(old_mode)
stopPlayer() enablePainting(true)
sd [ Player.Stop ]
sd [ Stop ]
H ÌNH 2.11: Biểu đồ trình tự cho Use-caseStop
Trang 20Khi người dùng yêu cầu undo, player sẽ chuyển thao tác vẽ gần nhất vào stack (ở đây là undoStack),sau đó canvas sẽ yêu cầu player vẽ lại từ đầu (trừ thao tác vừa được đưa và
undoStack)
User
: :GuiThread : MainWindow :Canvas : Player
undo on_actionUndo_triggered()
Trang 21Ngược lại, khi có yêu cầu redo, player sẽ chuyển thao tác trên đỉnh của undoStack vào danh sách cácthao tác, sau đó thực hiện thao tác này.
2.3 Biểu đồ lớp
2.3.1 Biểu đồ lớp tổng quan
Hình 2.14 là biểu đồ tổng quan tất cả các lớp của BKPaint Trong đó:
• MainWindow là lớp cửa sổ chính, là chứa tất cả các thành phần giao diện khác,
• ToolBar, ColorPicker, là các thành phần giao diện,
• Canvas là lớp đại diện cho bức vẽ, nơi người dùng thao tác lên để vẽ hình,
• Player là lớp có nhiệm vụ lưu trữ, quản lý các thao tác vẽ,
• PaintOperation là lớp cơ sở cho tất cả các loại thao tác vẽ
:User :GuiThread :MainWindow : Canvas : Player po:PaintOperation
undo on_actionRedo_triggered()
Trang 222.3.2 Biểu đồ lớp chi tiết cho MainWindow và các thành phần giao diện
Trang 242.3.3 Biểu đồ lớp chi tiết cho Canvas và Player
Trang 252.3.4 Biểu đồ lớp chi tiết cho PaintOperation và các lớp liên quan
H ÌNH 2.18: Biểu đồ lớp cho PaintOperation và các lớp liên quan
Trang 26Chương 3
Thiết kế chi tiết lớp
Thiết kế chi tiết lớp dưới đây được sinh tự động từ mã nguồn bằng công cụ doxygen 1
Có thể xem phiên bản web của tài liệu này tại: http://oopk55group12.bitbucket.org/
3.1 Kiến trúc Class
Danh sách kế thừa đã được sắp xếp theo ABC, nhưng chưa đầy đủ:
NewFileOption 99OpPair 102
PaintOperation 103
AddImage 31AddShape 34ChangeShape 54Erase 66Fill 69MousePress 94SetBrush 121SetPen 130SetRenderHint 141
ColorPicker::Palette 107ColorPicker::PaletteColor 107 QObject[external]Player 108QStyle[external]
QCommonStyle[external]
QProxyStyle[external]
ToolBar::LargeIconWidthStyle 72QWidget[external]
Trang 27Canvas 38ColorPicker 60QDialog[external]
AboutDialog 29NewFileOptionDialog 100ResizeDialog 119QMainWindow[external]
MainWindow 73QToolBar[external]
ToolBar 144SetBrushToolBar 124SetPenToolBar 134
Lớp đại diện cho thao tác thay đổi một đối tượng đồ họa đã vẽ 54ColorPicker
Thanh chọn màu 60Erase
Lớp đại diện cho thao tác xoá một phần bức vẽ 66Fill
Lớp đại diện cho thao tác tô màu 69
Trang 28Style với icon có chiều rộng lớn 72MainWindow
Cửa số chính 73MousePress
Lớp đại diện cho thao tác nhấn chuột, bắt đầu cho một chuỗi ChangeShape
hoặc AddShape 94NewFileOption
Các thuộc tính của file mới tạo 99NewFileOptionDialog
Hộp thoại chọn thuộc tính cho file mới tạo 100OpPair
Cặp thao tác vẽ 102PaintOperation
Lớp cơ sở cho tất cả các thao tác vẽ 103ColorPicker::Palette
Lớp đại diện cho một bảng màu 107ColorPicker::PaletteColor
Lớp đại diện cho một màu thuộc bảng màu 107Player
Đối tượng lưu trữ và thực hiện lại các thao tác vẽ 108ResizeDialog
Hộp thoại thay đổi kích thước 119
Trang 29Thông tin về chương trình.
Phương thức khởi tạo.
• QSize getNewSize () const
Lấy kích thước mới.
• void displayFile (QString const &fileName, QString const &title)
Hiện nội dung file.
Trang 30Additional Inherited Members
3.3.1 Mô tả chi tiết
Thông tin về chương trình
Định nghĩa tại dòng 32 trong file aboutdialog.hh
3.3.2 Thông tin về hàm thành viên
3.3.2.1 void AboutDialog::displayFile ( QString const & fileName, QString const & title
) [private]
Hiện nội dung file
Nội dung file sẽ được hiển thị trong một hộp thoại mới
Các tham số
fileName tên file
title tiêu đề của hộp thoại hiển thị
Định nghĩa tại dòng 108 trong file aboutdialog.cc
Thông tin cho class được biên soạn từ các file sau đây:
Trang 31• src/widget/aboutdialog.hh
• src/widget/aboutdialog.cc
Lớp đại diện cho thao tác thêm một hình vào Canvas
#include <addimage.hh> Sơ đồ kế
thừa cho AddImage:
PaintOperation
Các hàm thành viên Public
• AddImage (QImage const &image=QImage(), QPointF topLeft=QPointF())
Phương thức khởi tạo.
• qint32 type () const override
Kiểu của thao tác.
• QRectF operate (QPainter &painter) const override
Thực hiện thao tác.
• void save (QDataStream &stream) const override
Lưu trạng thái của thao tác vẽ vào stream.
• void load (QDataStream &stream) override
Đọc dữ liệu cho thao tác vẽ từ stream.
Các thuộc tính Static Public
• static const qint32 Type = 7
Kiểu của thao tác.
Các thuộc tính Private
• QImage image
Hình sẽ thêm vào.
AddImage
Trang 32• QPointF topLeft
Vị trí của hình sẽ thêm vào trên Canvas
3.4.1 Mô tả chi tiết
Lớp đại diện cho thao tác thêm một hình vào Canvas
Xem thêm
QImage
Định nghĩa tại dòng 34 trong file addimage.hh
3.4.2 Thông tin về Constructor và Destructor
3.4.2.1 AddImage::AddImage ( QImage const & image = QImage () , QPointF topLeft = QPointF () )
Phương thức khởi tạo
Khởi tạo tất các các thuộc tính của lớp AddImage
Xem thêm
image, topLeft
Định nghĩa tại dòng 32 trong file addimage.cc
3.4.3 Thông tin về hàm thành viên
3.4.3.1 void AddImage::load ( QDataStream & stream ) [override] , [virtual]
Đọc dữ liệu cho thao tác vẽ từ stream
Đọc image, topLeft từ stream, Type sẽ được đọc trước đó để xác định kiểu của thao tác vẽ
Các tham số
stream luồng dữ liệu vào
Xem thêm save
(QDataStream &)
Thực hiện PaintOperation
Trang 33Định nghĩa tại dòng 73 trong file addimage.cc.
3.4.3.2 QRectF AddImage::operate ( QPainter & painter ) const [override] ,
Định nghĩa tại dòng 49 trong file addimage.cc
3.4.3.3 void AddImage::save ( QDataStream & stream ) const
[virtual]
Lưu trạng thái của thao tác vẽ vào stream
Ghi Type, image, topLeft vào stream
stream luồng dữ liệu ra
Xem thêm load
(QDataStream &) Thực hiện
PaintOperation
Định nghĩa tại dòng 61 trong file addimage.cc
3.4.3.4 qint32 AddImage::type ( ) const [inline] , [override] , [virtual]
Kiểu của thao tác
Trang 34Thực chất trả về Type Thường được gọi từ một con trỏ kiểu PaintOperation
Định nghĩa tại dòng 59 trong file addimage.hh
Thông tin cho class được biên soạn từ các file sau đây:
• src/paintoperation/addimage.hh
• src/paintoperation/addimage.cc
Lớp đại diện cho thao tác thêm một đối tượng đồ họa vào Canvas
#include <addshape.hh> Sơ đồ kế
thừa cho AddShape:
PaintOperation
Các hàm thành viên Public
• AddShape (QPainterPath const &shape=QPainterPath())
Phương thức khởi tạo.
• qint32 type () const override
Kiểu của thao tác.
• QRectF operate (QPainter &painter) const override
Thực hiện thao tác.
• void save (QDataStream &stream) const override
AddShape
Trang 35Lưu thao tác vẽ vào stream.
• void load (QDataStream &stream) override
Đọc dữ liệu cho thao tác vẽ từ stream.
• void append (AddShape const &as)
Hợp với một thao tác AddShape khác.
Các thuộc tính Static Public
• static const qint32 Type = 1
Kiểu của thao tác.
Các thuộc tính Private
• QPainterPath shape
Đối tượng đồ họa cần thêm vào.
3.5.1 Mô tả chi tiết
Lớp đại diện cho thao tác thêm một đối tượng đồ họa vào Canvas
Đối tượng đồ họa có thể là một đường thẳng, hình chữ nhật, hình elip hay tổ hợp của các đối tượng cơbản đó Thuộc tính shape kiểu QPainterPath sẽ lưu tất cả các loại đối tượng này.
Có thể gộp hai thao tác AddShape thành một thao tác bằng phương thức append (AddShape
const &)
Xem thêm
QPainterPath
Định nghĩa tại dòng 39 trong file addshape.hh
3.5.2 Thông tin về Constructor và Destructor
3.5.2.1 AddShape::AddShape ( QPainterPath const & shape = QPainterPath () )
Phương thức khởi tạo
Khởi tạo thuộc tính shape
Xem thêm shape
Trang 36Định nghĩa tại dòng 32 trong file addshape.cc.
3.5.3 Thông tin về hàm thành viên
3.5.3.1 void AddShape::append ( AddShape const & as )
Hợp với một thao tác AddShape khác
shape sẽ lưu thêm đối tượng đồ hoạ được lưu bởi as.shape Thực hiện thao tác này sẽ tương đươngvới thực hiện hai thao tác cũ
Các tham số
as đối tượng AddShape sẽ được ghép với đối tượng hiện tại
Xem thêm shape
Định nghĩa tại dòng 88 trong file addshape.cc
3.5.3.2 void AddShape::load ( QDataStream & stream ) [override] , [virtual]
Đọc dữ liệu cho thao tác vẽ từ stream
Nhập shape từ stream, Type sẽ được đọc trước đó để xác định kiểu của thao tác vẽ
Các tham số
stream luồng dữ liệu ra
Xem thêm save
(QDataStream &)
Thực hiện PaintOperation
Định nghĩa tại dòng 65 trong file addshape.cc
3.5.3.3 QRectF AddShape::operate ( QPainter & painter ) const [override] ,
[virtual]
Thực hiện thao tác
Vẽ đối tượng QPainterPath shape vào thiểt bị vẽ (QPaintDevice) gắn với painter
Các tham số
Trang 37painter đối tượng vẽ sẽ thao tác
Giá trị trả về
Vùng bức vẽ sẽ bị thay đổi sau khi thực hiện
Thực hiện PaintOperation
Định nghĩa tại dòng 50 trong file addshape.cc
3.5.3.4 void AddShape::save ( QDataStream & stream ) const
[virtual]
Lưu thao tác vẽ vào stream
Ghi Type, shape vào stream
stream luồng dữ liệu vào
Xem thêm load
(QDataStream &)
Thực hiện PaintOperation
Định nghĩa tại dòng 76 trong file addshape.cc
3.5.3.5 qint32 AddShape::type ( ) const [inline] , [override] , [virtual]
Kiểu của thao tác
Thực chất trả về Type
Xem thêm
Type
Thực hiện PaintOperation
Định nghĩa tại dòng 63 trong file addshape.hh
Thông tin cho class được biên soạn từ các file sau đây:
Trang 38• src/paintoperation/addshape.hh
• src/paintoperation/addshape.cc
Bức vẽ
#include <canvas.hh> Sơ đồ kế
thừa cho Canvas:
Public Types
• enum DrawMode {
FreeDraw, DrawLine, DrawRect, DrawEllipse,
DrawPolygon, DrawRegularPolygon, DrawStar, DrawCurve,
EraseArea, FillArea, ZoomIn, ZoomOut,
• void setRenderHint (QPainter::RenderHint hint, bool on)
Thay đổi renderHint.
• void setBrush (QBrush const &brush)
Thay đổi chổi lông.
• void setEraseRadius (int radius)
Thay đổi bán kính vùng tẩy.
• void setNoCorner (int)
CanvasQWidgetQObject QPaintDevice
Trang 39Thay đổi số đỉnh của đa giác đều hoặc ngôi sao.
• void setZoomFactor (int percent)
Thay đổi tỉ lệ phóng to/thu nhỏ
• void cursorMoved (QPointF)
Tín hiệu được phát ra khi chuôt di chuyển đển một điểm trên Canvas
Các hàm thành viên Public
• Canvas (Player ∗player, QWidget ∗parent=0)
Phương thức khởi tạo.
• virtual ∼Canvas ()
Phương thức hủy.
• bool save (QString const &file)
Lưu nội dung bức vẽ vào file ảnh.
• bool load (QString const &file)
Tải nội dung file ảnh lên bức vẽ
• void reloadPlayer ()
Cập nhật sự thay đổi của player.
• void setMode (DrawMode m)
Trang 40Các hàm Static Public
• static void initCursors ()
Khởi tạo các con trỏ chuột.
• static QCursor genEraseCursor (qreal radius)
Sinh con trỏ chuột cho chế đô tẩy (DrawMode::EraseArea)
• static QPolygonF regularPolygon (int, QPointF const &, QPointF const &)
Tính các đỉnh của đa giác đều.
• static QPolygonF regularStar (int, QPointF const &, QPointF const &)
Tính các đỉnh của hình sao.
Các thuộc tính Static Public
• static QCursor cursors [ModeCount]
Con trỏ chuột tương ứng với các chế độ vẽ khác nhau.
• void mouseMoveEvent (QMouseEvent ∗event) override
Sự kiện di chuyển chuột.
• void mouseReleaseEvent (QMouseEvent ∗event) override
Sự kiện nhả chuột.
Private Slots
• void playNextOp (QRectF const &rect)
Thực hiện thao tác vẽ tiếp theo ở chế độ Replay.