Xây dựng chương trình vẽ hình mở rộng BKPaint Xây dựng chương trình vẽ hình mở rộng BKPaint Xây dựng chương trình vẽ hình mở rộng BKPaint Xây dựng chương trình vẽ hình mở rộng BKPaint Xây dựng chương trình vẽ hình mở rộng BKPaint
Trang 1Báo cáo môn học Lập trình hướng đối tượng
Đề tài: De02C - Xây dựng chương trình vẽ hình
mở rộng - BKPaint
Nguời thực hiện
Trần Quang Kiên - 20101744 - 01242886369 Nguyễn Duy Thành - 20102737 - 01698679162 Bạch Văn Hải - 20101464 - 01649612854 Nguyễn Xuân Hoà - 20101559 - 0988219953
Trang 2Mục lục
1.1 Lập trình hướng đối tượng với C++ 1
1.1.1 C++ 1
1.1.2 C++11 1
1.1.2.1 nullptr- con trỏ null 2
1.1.2.2 auto- tự động suy diễn kiểu 3
1.1.2.3 Range-for 3
1.1.2.4 Chỉ thịoverride 4
1.2 Qt Framework 5
1.2.1 Giới thiệu 5
1.2.2 Lập trình C++ với Qt 6
1.2.3 Một số kỹ thuật hướng đối tượng trong Qt 7
1.2.3.1 Cơ chế cha-con 7
1.2.3.2 Cơ chếsignal - slot (tín hiệu - khe cắm) 7 2 Phân tích thiết kế mức kiến trúc 9 2.1 Biểu đồ Use-case 9
2.1.1 Biểu đồ Use-case tổng quát 9
2.1.2 Phân rã Use-case Painting 10
2.1.3 Phân ra Use-case Replay painting 10
2.2 Biểu đồ trình tự 12
2.2.1 Biểu đồ trình tự cho Use-caseOpen 12
2.2.2 Biểu đồ trình tự cho Use-caseSave 13
2.2.3 Biểu đồ trình tự cho Use-casePainting 13
2.2.3.1 Biểu đồ trình tự cho Use-caseDraw shape 13
2.2.3.2 Biểu đồ trình tự cho Use-caseErase 15
2.2.4 Biểu đồ trình tự cho Use-caseReplay Painting 16
2.2.5 Biểu đồ trình tự cho Use-caseUndo / Redo 19
2.3 Biểu đồ lớp 21
Trang 32.3.1 Biểu đồ lớp tổng quan 21
2.3.2 Biểu đồ lớp chi tiết choMainWindowvà các thành phần giao diện 22
2.3.3 Biểu đồ lớp chi tiết choCanvasvàPlayer 24
2.3.4 Biểu đồ lớp chi tiết choPaintOperationvà các lớp liên quan 25
3 Thiết kế chi tiết lớp 26 3.1 Kiến trúc Class 26
3.2 Danh mục các Class 27
3.3 AboutDialog Class Tham chiếu 29
3.3.1 Mô tả chi tiết 30
3.3.2 Thông tin về hàm thành viên 30
3.3.2.1 displayFile 30
3.4 AddImage Class Tham chiếu 31
3.4.1 Mô tả chi tiết 32
3.4.2 Thông tin về Constructor và Destructor 32
3.4.2.1 AddImage 32
3.4.3 Thông tin về hàm thành viên 32
3.4.3.1 load 32
3.4.3.2 operate 33
3.4.3.3 save 33
3.4.3.4 type 34
3.5 AddShape Class Tham chiếu 34
3.5.1 Mô tả chi tiết 35
3.5.2 Thông tin về Constructor và Destructor 35
3.5.2.1 AddShape 35
3.5.3 Thông tin về hàm thành viên 36
3.5.3.1 append 36
3.5.3.2 load 36
3.5.3.3 operate 37
3.5.3.4 save 37
3.5.3.5 type 37
3.6 Canvas Class Tham chiếu 38
3.6.1 Mô tả chi tiết 42
3.6.2 Thông tin về Member Enumeration 43
3.6.2.1 DrawMode 43
3.6.3 Thông tin về Constructor và Destructor 43
3.6.3.1 Canvas 43
3.6.4 Thông tin về hàm thành viên 44
3.6.4.1 fillBackground 44
Trang 43.6.4.2 genEraseCursor 44
3.6.4.3 getBrush 44
3.6.4.4 getBuffer 45
3.6.4.5 getPen 45
3.6.4.6 getRenderHints 45
3.6.4.7 initCursors 45
3.6.4.8 load 46
3.6.4.9 mouseMoveEvent 46
3.6.4.10 mousePressEvent 46
3.6.4.11 mouseReleaseEvent 47
3.6.4.12 operate 47
3.6.4.13 paintEvent 47
3.6.4.14 playNextOp 48
3.6.4.15 redo 48
3.6.4.16 regenerateBuffer 48
3.6.4.17 regularPolygon 49
3.6.4.18 regularStar 49
3.6.4.19 reloadPlayer 50
3.6.4.20 setBrush 50
3.6.4.21 setEraseRadius 50
3.6.4.22 setMode 51
3.6.4.23 setNoCorner 51
3.6.4.24 setPen 51
3.6.4.25 setRenderHint 52
3.6.4.26 setZoomFactor 52
3.6.4.27 startPlayer 53
3.6.4.28 stopPlayer 53
3.6.4.29 undo 53
3.6.4.30 updateCursor 53
3.6.5 Thông tin về Member Data 54
3.6.5.1 mousePressed 54
3.7 ChangeShape Class Tham chiếu 54
3.7.1 Mô tả chi tiết 56
3.7.2 Thông tin về Constructor và Destructor 56
3.7.2.1 ChangeShape 56
3.7.3 Thông tin về hàm thành viên 57
3.7.3.1 getAddShape 57
3.7.3.2 load 57
3.7.3.3 operate 58
Trang 53.7.3.4 save 58
3.7.3.5 setChangedPart 58
3.7.3.6 setLastTopLeft 59
3.7.3.7 type 59
3.7.4 Thông tin về Member Data 60
3.7.4.1 changedPart 60
3.7.4.2 lastTopLeft 60
3.8 ColorPicker Class Tham chiếu 60
3.8.1 Mô tả chi tiết 63
3.8.2 Thông tin về Constructor và Destructor 63
3.8.2.1 ColorPicker 63
3.8.3 Thông tin về hàm thành viên 64
3.8.3.1 colorAt 64
3.8.3.2 initContexMenu 64
3.8.3.3 initPalette 64
3.8.3.4 mouseMoveEvent 65
3.8.3.5 mousePressEvent 65
3.8.3.6 paletteAction_triggered 66
3.8.3.7 setPalette 66
3.9 Erase Class Tham chiếu 66
3.9.1 Mô tả chi tiết 67
3.9.2 Thông tin về Constructor và Destructor 67
3.9.2.1 Erase 67
3.9.3 Thông tin về hàm thành viên 68
3.9.3.1 load 68
3.9.3.2 save 68
3.9.3.3 type 69
3.10 Fill Class Tham chiếu 69
3.10.1 Mô tả chi tiết 70
3.10.2 Thông tin về Constructor và Destructor 70
3.10.2.1 Fill 70
3.10.3 Thông tin về hàm thành viên 71
3.10.3.1 load 71
3.10.3.2 operate 71
3.10.3.3 save 71
3.10.3.4 type 72
3.11 ToolBar::LargeIconWidthStyle Class Tham chiếu 72
3.11.1 Mô tả chi tiết 73
3.12 MainWindow Class Tham chiếu 73
Trang 63.12.1 Mô tả chi tiết 81
3.12.2 Thông tin về Member Enumeration 82
3.12.2.1 anonymous enum 82
3.12.2.2 FileType 82
3.12.3 Thông tin về Constructor và Destructor 82
3.12.3.1 MainWindow 82
3.12.3.2 MainWindow 83
3.12.4 Thông tin về hàm thành viên 83
3.12.4.1 closeEvent 83
3.12.4.2 enablePainting 83
3.12.4.3 hoveredColor 84
3.12.4.4 init 84
3.12.4.5 initActions 84
3.12.4.6 initMenus 84
3.12.4.7 initStatusBar 85
3.12.4.8 initToolbars 85
3.12.4.9 initWidgets 85
3.12.4.10 loadFile 85
3.12.4.11 maybeSave 86
3.12.4.12 openBrushColorDialog 86
3.12.4.13 openPenColorDialog 86
3.12.4.14 playerModified 87
3.12.4.15 playerStopped 87
3.12.4.16 readSettings 87
3.12.4.17 reloadControl 87
3.12.4.18 saveGraphicFile 88
3.12.4.19 saveReplayFile 88
3.12.4.20 setBrushColor 89
3.12.4.21 setBrushStyle 89
3.12.4.22 setCurrentFile 89
3.12.4.23 setPenColor 90
3.12.4.24 setPenStyle 90
3.12.4.25 setPenWidth 90
3.12.4.26 setRenderHint 91
3.12.4.27 strippedName 91
3.12.4.28 updateLabelPosition 92
3.12.4.29 updateRecentFileActions 92
3.12.4.30 writeSettings 92
3.12.5 Thông tin về Member Data 92
Trang 73.12.5.1 actionAntialiasing 92
3.12.5.2 actionHighQualityAntialiasing 93
3.12.5.3 actionNonCosmeticDefaultPen 93
3.12.5.4 actionSmoothPixmapTransform 93
3.12.5.5 actionTextAntialiasing 93
3.12.5.6 colorPicker 94
3.12.5.7 colorPickerToolBar 94
3.12.5.8 menuBar 94
3.13 MousePress Class Tham chiếu 94
3.13.1 Mô tả chi tiết 96
3.13.2 Thông tin về hàm thành viên 96
3.13.2.1 load 96
3.13.2.2 operate 97
3.13.2.3 save 97
3.13.2.4 setChangedPart 98
3.13.2.5 setLastTopLeft 98
3.13.2.6 type 98
3.13.3 Thông tin về Member Data 99
3.13.3.1 changedPart 99
3.13.3.2 lastTopLeft 99
3.14 NewFileOption Struct Tham chiếu 99
3.14.1 Mô tả chi tiết 100
3.14.2 Thông tin về Member Data 100
3.14.2.1 size 100
3.15 NewFileOptionDialog Class Tham chiếu 100
3.15.1 Mô tả chi tiết 101
3.15.2 Thông tin về hàm thành viên 102
3.15.2.1 dialogAccepted 102
3.15.2.2 getNewFileOption 102
3.16 OpPair Struct Tham chiếu 102
3.16.1 Mô tả chi tiết 103
3.17 PaintOperation Class Tham chiếu 103
3.17.1 Mô tả chi tiết 104
3.17.2 Thông tin về Constructor và Destructor 104
3.17.2.1 ∼PaintOperation 105
3.17.3 Thông tin về hàm thành viên 105
3.17.3.1 load 105
3.17.3.2 operate 105
3.17.3.3 save 106
Trang 83.17.3.4 type 106
3.18 ColorPicker::Palette Struct Tham chiếu 107
3.18.1 Mô tả chi tiết 107
3.19 ColorPicker::PaletteColor Struct Tham chiếu 107
3.19.1 Mô tả chi tiết 107
3.20 Player Class Tham chiếu 108
3.20.1 Mô tả chi tiết 111
3.20.2 Thông tin về Constructor và Destructor 111
3.20.2.1 Player 111
3.20.2.2 Player 112
3.20.2.3 ∼Player 112
3.20.3 Thông tin về hàm thành viên 112
3.20.3.1 addFinishChangeShape 112
3.20.3.2 addOperation 113
3.20.3.3 background 113
3.20.3.4 canRedoChanged 113
3.20.3.5 canUndoChanged 114
3.20.3.6 getBuffer 114
3.20.3.7 isEmpty 115
3.20.3.8 load 115
3.20.3.9 loadImage 115
3.20.3.10 pause 116
3.20.3.11 play 116
3.20.3.12 playerStopped 116
3.20.3.13 redo 116
3.20.3.14 repaint 117
3.20.3.15 resizeBuffer 117
3.20.3.16 resume 117
3.20.3.17 save 117
3.20.3.18 setIntervalBySpeed 118
3.20.3.19 size 118
3.20.3.20 stop 118
3.20.3.21 timerTimeout 119
3.20.3.22 undo 119
3.20.3.23 zoom 119
3.21 ResizeDialog Class Tham chiếu 119
3.21.1 Mô tả chi tiết 120
3.21.2 Thông tin về hàm thành viên 121
3.21.2.1 dialogAccepted 121
Trang 93.21.2.2 getNewSize 121
3.22 SetBrush Class Tham chiếu 121
3.22.1 Mô tả chi tiết 122
3.22.2 Thông tin về hàm thành viên 123
3.22.2.1 load 123
3.22.2.2 operate 123
3.22.2.3 save 123
3.22.2.4 type 124
3.23 SetBrushToolBar Class Tham chiếu 124
3.23.1 Mô tả chi tiết 126
3.23.2 Thông tin về Constructor và Destructor 126
3.23.2.1 SetBrushToolBar 126
3.23.2.2 SetBrushToolBar 127
3.23.3 Thông tin về hàm thành viên 127
3.23.3.1 brushColorNeeded 127
3.23.3.2 brushStyleChanged 127
3.23.3.3 init 128
3.23.3.4 initActions 128
3.23.3.5 initWidgets 128
3.23.3.6 reloadBrushColorIcon 129
3.23.3.7 reloadBrushStyleIcon 129
3.23.4 Thông tin về Member Data 129
3.23.4.1 actionBrushColor 129
3.23.4.2 brushStyleActionGroup 130
3.23.4.3 brushStyleMenu 130
3.23.4.4 brushStyleSignalMapper 130
3.24 SetPen Class Tham chiếu 130
3.24.1 Mô tả chi tiết 131
3.24.2 Thông tin về hàm thành viên 132
3.24.2.1 load 132
3.24.2.2 operate 132
3.24.2.3 save 133
3.24.2.4 type 133
3.25 SetPenToolBar Class Tham chiếu 134
3.25.1 Mô tả chi tiết 135
3.25.2 Thông tin về Constructor và Destructor 136
3.25.2.1 SetPenToolBar 136
3.25.2.2 SetPenToolBar 136
3.25.3 Thông tin về hàm thành viên 136
Trang 103.25.3.1 init 136
3.25.3.2 initActions 137
3.25.3.3 initWidgets 137
3.25.3.4 penColorNeeded 137
3.25.3.5 penStyleChanged 137
3.25.3.6 penWidthChanged 138
3.25.3.7 reloadPenColorIcon 138
3.25.3.8 reloadPenStyleIcon 138
3.25.3.9 setPenWidth 139
3.25.4 Thông tin về Member Data 139
3.25.4.1 actionPenColor 139
3.25.4.2 penStyleActionGroup 139
3.25.4.3 penStyleMenu 140
3.25.4.4 penStyleSignalMapper 140
3.25.4.5 penWidthSlider 140
3.26 SetRenderHint Class Tham chiếu 141
3.26.1 Mô tả chi tiết 142
3.26.2 Thông tin về hàm thành viên 142
3.26.2.1 load 142
3.26.2.2 operate 142
3.26.2.3 save 143
3.26.2.4 type 143
3.27 ToolBar Class Tham chiếu 144
3.27.1 Mô tả chi tiết 145
3.27.2 Thông tin về Constructor và Destructor 145
3.27.2.1 ToolBar 145
3.27.2.2 ToolBar 146
3.27.2.3 ∼ToolBar 146
3.27.3 Thông tin về hàm thành viên 146
3.27.3.1 addSpace 146
3.27.3.2 genColorIcon 147
3.27.4 Thông tin về Member Data 147
3.27.4.1 LargeIconWidth 147
4 Giải pháp kỹ thuật 148 4.1 Cài đặt tính năng Replay 148
4.1.1 Giải pháp lưu trữ 148
4.1.2 PaintOperation- lớp cơ sở cho tất cả các thao tác vẽ 149
4.1.3 Cài đặt tính năng Replay 149
Trang 114.2 Kỹ thuật bộ đệm (buffer) 149
4.3 Phóng to / thu nhỏ 150
4.4 Undo / Redo 151
5 Kết luận và đánh giá 153 5.1 Kết luận và đánh giá 153
5.2 Phân công công việc trong nhóm 154
5.2.1 Phân công công việc 154
5.2.2 Kế hoạch làm việc và lịch họp nhóm 155
Tài liệu tham khảo 156 Danh sách hình vẽ 1.1 Biên dịch một Project Qt 6
2.1 Biểu đồ Use-case tổng quát 9
2.2 Phân rã Use-case Painting 10
2.3 Phân rã Use-caseReplay painting 10
2.4 Biểu đồ trình tự cho Use-caseOpen 12
2.5 Biểu đồ trình tự cho Use-caseSave 13
2.6 Biểu đồ trình tự cho Use-caseDraw shape 14
2.7 Biểu đồ trình tự cho Use-caseErase 15
2.8 Biểu đồ trình tự cho Use-caseReplay 16
2.9 Biểu đồ trình tự cho Use-casePause 17
2.10 Biểu đồ trình tự cho Use-caseResume 17
2.11 Biểu đồ trình tự cho Use-caseStop 18
2.12 Biểu đồ trình tự cho Use-caseUndo 19
2.13 Biểu đồ trình tự cho Use-caseRedo 20
2.14 Biểu đồ lớp tổng quan 21
2.15 Biểu đồ lớp choMainWindowvà GUI 22
2.16 Biểu đồ lớp choMainWindowvà GUI (tiếp theo) 23
2.17 Biểu đồ lớp choCanvasvàPlayer 24
2.18 Biểu đồ lớp choPaintOperationvà các lớp liên quan 25
Trang 124.1 Kích thước bình thường 150
4.2 Phóng to với tỉ lệ 3:1 151
Danh sách bảng 5.1 Phân công công việc trong nhóm - Phân tích / thiết kế 154
5.2 Phân công công việc trong nhóm - coding 154
5.3 Phân công công việc trong nhóm - Viết báo cáo 154
5.4 Đánh giá mức độ đóng góp 155
5.5 Kế hoạch làm việc 155
Trang 13OOP Graphical User Interface : Giao diện đồ hoạ người dùng
OOP Object Oriented Programming : Lập trình hướng đối tượng
Trang 14For/Dedicated to/To my .
Trang 15Chương 1
Tổng quan về các vấn đề liên quan
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ựatrê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áttriể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ểmkhô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)
1.1.2 C++11
Vào tháng 11/2011, ISO đã thông qua chuẩnC++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 quamộ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
Trang 16Bả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
1.1.2.1 nullptr- con trỏ null
Trong ngôn ngữC, macroNULLđược định nghĩa là(void*)0 Tuy nhiên,C++lại không thểđịnh nghĩa theo cách này, bởi vì C++ yêu cầu chuyển đổi kiểu tường minh từvoid*sang kiểucon trỏ Ví dụ:
1 int * = NULL;
Sẽ sinh lỗi biên dịch
Do vậy, C++ định nghĩaNULLlà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 đó:
1 void foo (char *); // 1
3
4 foo (NULL);
Câu lệnh foo (NULL)sẽ gọi hàmfoo() thứ 2, rõ ràng không phải điều mà lập trình viênmong muốn Nếu muốn gọi hàm foo thứ nhất thì phải sử dụng phép chuyển kiểu tường minh.C++11 cung cấp từ khoá nullptr, nó đại diện cho hằng con trỏ nguyên nullptrcó kiểu
lànullptr_t, có thể đượng chuyển kiểu không tường minh sang kiểu con trỏ bất kỳ và kiểu
bool Nếu muốn chuyển sang kiểu nguyên phải ép kiểu
10 int a = nullptr; // illegal
Tham khảo: [4, section 4.10, pg 80]
Trang 171.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 std::vector<int>::iterator vi = v.begin();
2 for (; vi != v.end(); ++vi) {
4 }
Với từ khoá auto, kiểu của biến khi khởi tạo sẽ tự động được suy diễn bởi trình dịch trongthời gian biên dịch (compile-time) dựa vào giá trị trả về của biểu thức khởi tạo cho biến [4,section 7.1.6.4, pg 148] Nhờ vậy mà mã nguồn ngắn gọn, dễ hiểu hơn: Ví dụ:
1 // auto v; // Compile error
14 auto const v2 = v; // const std::vector<int>
15 auto vi2 = v2.begin() // std::vector<int>::const_iterator
Chú ý: ý nghĩa cũ của từ khoáauto(auto local storage) ở C++11 không còn hợp lệ
Trang 183
4 }
Với C++03 trở về trước, phép lặp qua một tập hợp, mảng, sử dụngiteratorhoặc lặp theochỉ số mảng với cú pháp khá phức tạp C++11 cung cấpRange-forvới chức năng tương tựnhư các ngôn ngữ khác:
Range-forcủa C++11 cho phép tùy chọn kiểu của phần tử:
1 for (int & : l) {
2 i *= 2;
3 }
Ở đây,ilà một tham chiếu của một phần tử thuộcl, thay vì là một phiên bản copy Nhờ vậy màphép gán bên trong vòng lặp có thể thay đổi được nội dung củal So với vòng lặp trongJava,không thể thay đổi được nội dung của mảng
Tham khảo [4, section 6.5.4, pg 128]
Trang 19Lập trình viên có ý định định nghĩa lại các phương thức ảof(), g(), h()củaAtạiB Nhưngvới đoạn mã trên chỉ cóf()là được định nghĩa lại, trong khiA::g() constvàB::g()làhai phương thức không liên quan 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ỗi ngữ 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ịoverridecho phép khai báo tường minh một phương thức của lớp dẫnxuấ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ứcB::g()vàB::h()bởi
vì trong lớp cơ sở củaBlàAkhông có phương thức ảo nào có chữ ký giống với những phươngthức này Nhờ vậy mà có thể dễ dàng sửa lỗi
Chú ý:overridekhông phải là một từ khoá mới, do đó vẫn có thể sử dụngoverridelà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 GUIcũ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ịchtrên nhiều nền tả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, Qthiện đang thuộc bản quyền của Digia (http://qt.digia.com/), được phân phối dưới 2giấy phép khác nhau là giấy phép phần mềm tự do mã nguồn mở (GPL v2) và giấy phép phầnmề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
Trang 20HÌNH1.1: Biên dịch một Project Qt
1.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êndịch bằng trình dịch C++ như bình thường Chương trình làm nhiệm vụ này làmoc (meta-
C++ như Meta Object, Property, Signal-slot,
Hình1.1là 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đượcmocdị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ạng ui_*.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ệncầ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àychứa nội dung của các tài nguyên được mô tả trong các file qrc Như vậy, các tài nguyênnày trở thành một phần của chương trình thay vì tách rời file thực thi riêng, file tài nguyênriêng
• Các file cài đặt lớp (*.cpp) được biên dịch thằnh object như bình thường,
Trang 21• 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ầnthiế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ó macroQ_OBJECTmới được dịch bằng moc
Qt Framework bao gồm nhiều module như: QtCore, QtGui, QtNetwork, QtXml, Mỗi modulebao gồ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ằngchữ ’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) Trongdestructor củ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 đối tượ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ốccủa cây, các đối tượng menuBar (thanh menu), toolBar (thanh công cụ) là con của mainWin-dow, các button (nút bấm) là con của toolBar Khi mainWindow bị huỷ thì nó sẽ kéo theo cácmenuBar, 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ớpQObjectthì destructor được khai báo làvirtualnên cho dùcon trỏ mainWindow có được cast vềQObject*thì lời gọideletevẫn gọi đúng hàm hủy của
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ảnhơn so vớ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à khi nhậ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ậptrình mong muốn
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 đó đã đượcconnect (kết nối)
Chỉ có những lớp dẫn xuất củaQObjectmới có thể sử dụng signal và slot
Trang 22Ví dụ: Đối tượng button thuộc lớp QPushButton (nút bấm) có signal clicked() được emitkhi người dùng bấm vào nút đó Ở đối tượng mainWindow thuộc lớp MainWindow (cửa sổchính), nếu ta connect slot xử lý việc bấm nútbuttonClicked() với signal QPushBut-
thực hiện.1
1 Xem thêm về signal, slot, connect, emit tại 4.8/signalsandslots.html
Trang 23Open fileSave filePaintingReplay paintingZoomUndo / Redo
HÌNH2.1: Biểu đồ Use-case tổng quát
Trang 24– Save: Lưu file,
– Open: Mở file,
– Undo/Redo: Undo / Redo
– Zoom: Phóng to, thu nhỏ
2.1.2 Phân rã Use-case Painting
BKPaintBKPaint
Painting
HÌNH2.2: Phân rã Use-case Painting
Hình2.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
BKPaintBKPaint
Replay painting
H 2.3: Phân rã Use-caseReplay painting
Trang 25Hình2.3 Các Use-case:
• Play: Bắt đầu quá trình replay cho đến kết thúc,
• 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 262.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ườidù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ÌNH2.4: Biểu đồ trình tự cho Use-caseOpen
Khi 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à 1 tiế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 đó
Trang 272.2.2 Biểu đồ trình tự cho Use-case Save
:User :GuiThread :MainWindow :Player
openon_actionSave_triggered()
Request filename
Input filename
save(filename)
sd [ Save ]
HÌNH2.5: Biểu đồ trình tự cho Use-caseSave
2.2.3 Biểu đồ trình tự cho Use-case Painting
2.2.3.1 Biểu đồ trình tự cho Use-caseDraw shape
BKPainthỗ 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ác nhau Nhưng nhìn chung thì quá trình vẽ hình có trình tự kiểu như hình2.6
Trang 28HÌNH2.6: Biểu đồ trình tự cho Use-caseDraw shape
Trong đó:
• Khi nhấn chuột tại một điểm thì sinh ra một thao tác vẽ kiểuMousePress,
• 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ẫn xuất củaPaintOperation,
• 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 292.2.3.2 Biểu đồ trình tự cho Use-caseErase
sd [ Erase ]
HÌNH2.7: Biểu đồ trình tự cho Use-caseErase
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 đó
Trang 302.2.4 Biểu đồ trình tự cho Use-case Replay Painting
playNextOp()
startloop [ not end ]
timeouttimerTimeout()
stop()ref [ Player.Stop ]
sd [ Replay ]
HÌNH2.8: Biểu đồ trình tự cho Use-caseReplay
Trang 31:User :GuiThread :MainWindow :Player :Canvas :Timer
pauseon_actionPause_triggered()
pause()
stop
sd [ Pause ]
HÌNH2.9: Biểu đồ trình tự cho Use-casePause
:User :GuiThread :MainWindow :Player :Timer
resumeon_actionResume_triggered()
Trang 32:User :GuiThread :MainWindow :Player :Canvas :Timer
stop
on_actionStop_triggered()
stop()
stopstopPlayer()
setMode(old_mode)
stopPlayer()enablePainting(true)
sd [ Player.Stop ]
sd [ Stop ]
HÌNH2.11: Biểu đồ trình tự cho Use-caseStop
Trang 332.2.5 Biểu đồ trình tự cho Use-case Undo / Redo
:User :GuiThread :MainWindow :Canvas :Player
undoon_actionUndo_triggered()
HÌNH2.12: Biểu đồ trình tự cho Use-caseUndo
Khi 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)
Trang 34:User :GuiThread :MainWindow :Canvas :Player po:PaintOperation
undoon_actionRedo_triggered()
HÌNH2.13: Biểu đồ trình tự cho Use-caseRedo
Ngược lại, khi có yêu cầu redo,playersẽ chuyển thao tác trên đỉnh của undoStack vào danhsách các thao tác, sau đó thực hiện thao tác này
Trang 352.3 Biểu đồ lớp
2.3.1 Biểu đồ lớp tổng quan
Hình2.14là biểu đồ tổng quan tất cả các lớp củaBKPaint Trong đó:
• MainWindowlà 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,
• Canvaslà lớp đại diện cho bức vẽ, nơi người dùng thao tác lên để vẽ hình,
• Playerlà lớp có nhiệm vụ lưu trữ, quản lý các thao tác vẽ,
• PaintOperationlà lớp cơ sở cho tất cả các loại thao tác vẽ
1
1 ColorPicker
1 ResizeDialog
1
1 1
NewFileOption
1
1 1
AddImage
SetRenderHint
SetPen
Player 1
SetBrush AddShape MousePress
ToolBar
«typedef» OperationList
1
MainWindow
1 Fill
Trang 362.3.2 Biểu đồ lớp chi tiết cho MainWindow và các thành phần giao diện
+ initPalette(dir : QDir const&) + setPalette( : PaletteIter, : int)
# penColorPicked( : QColor const &)
# brushColorPicked( : QColor const &)
# colorHovered(colorName : QString const&)
- authorsButtonClicked()
- licenseButtonClicked()
- displayFile(fileName : QString const&, title : QString const&)
NewFileOption + isFromClipboard : bool + isTransparent : bool + size : QSize
Trang 37+ MainWindow(nfOption : NewFileOption const*)
+ MainWindow(filename : QString const&, ft : FileTypes)
- saveGraphicFile(filename : QString const&) : bool
- saveReplayFile(filename : QString const&) : bool
- loadFile(filename : QString const&, ft : FileTypes)
- setCurrentFile(filename : QString const&)
+ reloadPenColorIcon( : QColor const&) + setPenWidth( : int)
+ reloadBrushColorIcon( : QColor const&)
+ IconHeight : const int + LargeIconWidth : const int + ToolBar(parent : QWidget*) + ToolBar(title : QString const&, parent : QWidget*)
-player
1
-player
1 1
-canvas 1 1
1
HÌNH2.16: Biểu đồ lớp choMainWindowvà GUI (tiếp theo)
Trang 382.3.3 Biểu đồ lớp chi tiết cho Canvas và Player
- changedPart : QSharedPointer< QImage >
- lastTopLeft : QSharedPointer< QPointF >
+∼Player()
+ addOperation(operation : PaintOperation*) + addFinishChangeShape() : PaintOperation*
+ save(file : QFile&) + load(file : QFile&) : bool + loadImage(image : QImage const&) + isEmpty() : bool
+ repaint(painter : QPainter&) + zoom(sf : qreal)
+ undo() + redo(painter : QPainter&) + resizeBuffer(newSize : QSize const&) + getBuffer() : QImage const*
+ size() : QSize + background() : QColor
+ pause() + resume() + stop() + setIntervalBySpeed(speed : int)
- timerTimeout()
- clearAll() + zoom(sf : qreal)
1 1
Canvas + cursors : QCursor[]
+ genEraseCursor(radius : qreal) : QCursor
+ regularPolygon( : int, : QPointF const&, : QPointF const&) : QPolygonF
+ regularStar( : int, : QPointF const&, : QPointF const&) : QPolygonF
+ save(file : QString const&) : bool
+ load(file : QString const&) : bool
+ setPen(pen : QPen const&)
+ setRenderHint(hint : QPainter::RenderHint, on : bool)
+ setBrush(brush : QBrush const&)
Trang 392.3.4 Biểu đồ lớp chi tiết cho PaintOperation và các lớp liên quan
1
OpPair + effOp : OperationPointer + ops : OperationList
1 +ops
«typedef»
OperationPointer
1
SetPen + Type : const qint32
- pen : QPen + SetPen(pen : QPen const&)
+ type() : qint32 + operate(painter : QPainter&) : QRectF + save(stream : QDataStream&) + load(stream : QDataStream&)
MousePress + Type : const qint32
+ setChangedPart(pointer : QSharedPointer< QImage > const&)
+ setLastTopLeft(pointer : QSharedPointer< QPointF > const&)
*
Fill + Type : const qint32
- seedPoint : QPoint + Fill(seedPoint : QPoint)
+ type() : qint32 + operate(painter : QPainter&) : QRectF + save(stream : QDataStream&) + load(stream : QDataStream&)
1
1
Player
Erase + Type : const qint32
- centre : QPointF
- radius : qint16 + Erase(centre : QPointF, radius : qint16)
+ type() : qint32 + operate(painter : QPainter&) : QRectF + save(stream : QDataStream&) + load(stream : QDataStream&)
SetBrush + Type : const qint32
- brush : QBrush + SetBrush(brush : QBrush const&)
+ type() : qint32 + operate(painter : QPainter&) : QRectF + save(stream : QDataStream&) + load(stream : QDataStream&)
SetRenderHint + Type : const qint32
- hint : QPainter::RenderHint
- on : bool + SetRenderHint(hint : QPainter::RenderHint, on : bool)
+ type() : qint32 + operate(painter : QPainter&) : QRectF + save(stream : QDataStream&) + load(stream : QDataStream&)
AddImage + Type : const qint32
+ setChangedPart(pointer : QSharedPointer< QImage > const&)
+ setLastTopLeft(pointer : QSharedPointer< QPointF > const&)
Trang 40Chươ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: