cg_gui.py 24.9 KB
Newer Older
SongYC's avatar
SongYC committed
1
2
3
4
5
#!/usr/bin/env python
# -*- coding:utf-8 -*-

import sys
import cg_algorithms as alg
6
import copy
SongYC's avatar
SongYC committed
7
8
from typing import Optional
from PyQt5.QtWidgets import (
ddlfighter's avatar
ddlfighter committed
9
    QFileDialog,
10
    QColorDialog,
SongYC's avatar
SongYC committed
11
12
13
14
15
16
17
18
19
20
    QApplication,
    QMainWindow,
    qApp,
    QGraphicsScene,
    QGraphicsView,
    QGraphicsItem,
    QListWidget,
    QHBoxLayout,
    QWidget,
    QStyleOptionGraphicsItem)
21
from PyQt5.QtGui import QPainter, QMouseEvent, QColor, QIcon, QPixmap, QWheelEvent
22
from PyQt5.QtCore import QRectF, Qt
SongYC's avatar
SongYC committed
23

24
# 全局变量定义
25
color = QColor(0, 0, 0)  # 默认画笔颜色为黑色
26

SongYC's avatar
SongYC committed
27
28
29
30
31

class MyCanvas(QGraphicsView):
    """
    画布窗体类,继承自QGraphicsView,采用QGraphicsView、QGraphicsScene、QGraphicsItem的绘图框架
    """
32

SongYC's avatar
SongYC committed
33
34
35
36
37
38
39
40
41
42
43
    def __init__(self, *args):
        super().__init__(*args)
        self.main_window = None
        self.list_widget = None
        self.item_dict = {}
        self.selected_id = ''

        self.status = ''
        self.temp_algorithm = ''
        self.temp_id = ''
        self.temp_item = None
44
        self.temp_move = []
45
        self.p_list = []
46
        self.last_click_button = None
ddlfighter's avatar
ddlfighter committed
47
48
49
50
        self.center_p = []     # 缩放,旋转所需点
        self.base_scale = 1    # 缩放倍数
        self.r = 0             # 旋转角度
        self.windows = []      # 窗口左上和右下坐标
51
52


53
54
55
56
57
58
    def reset_canvas(self):
        self.item_dict = {}
        self.list_widget.clear()  # 清楚label
        self.scene().clear()
        self.status = ''

ddlfighter's avatar
ddlfighter committed
59
60
61
62
63
64
65
66
67
68
    def save_canvas(self, filename, w, h):
        painter = QPainter()
        pixmap = QPixmap(w, h)          # Size
        pixmap.fill(QColor(255, 255, 255)) # 背景填充
        painter.begin(pixmap)
        for i in self.item_dict:
            self.item_dict[i].paint(painter, QStyleOptionGraphicsItem)
        painter.end()
        pixmap.save(filename)

SongYC's avatar
SongYC committed
69
70
71
72
73
    def start_draw_line(self, algorithm, item_id):
        self.status = 'line'
        self.temp_algorithm = algorithm
        self.temp_id = item_id

74
75
76
77
78
79
80
81
82
    def start_draw_ellipse(self, item_id):
        self.status = 'ellipse'
        self.temp_id = item_id

    def start_draw_polygon(self, algorithm, item_id):
        self.status = 'polygon'
        self.temp_algorithm = algorithm
        self.temp_id = item_id

83
    def start_draw_curve(self, algorithm, item_id):
84
85
86
87
        self.status = 'curve'
        self.temp_algorithm = algorithm
        self.temp_id = item_id

88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
    def start_translate(self):
        if self.selected_id == '':
            self.status = ''
            return
        self.status = 'translate'
        self.temp_id = self.selected_id
        # self.temp_item

    def start_rotate(self):
        '''
        此处旋转不含椭圆操作
        '''
        if self.selected_id == '' or \
                self.item_dict[self.selected_id].item_type == 'ellipse':
            self.status = ''
            return
        self.status = 'rotate'
        self.temp_id = self.selected_id

    def start_scale(self):
        if self.selected_id == '':
            self.status = ''
            return
        self.status = 'scale'
        self.temp_id = self.selected_id

114
    def start_clip(self, algorithm):
ddlfighter's avatar
ddlfighter committed
115
116
        if self.selected_id == '' or \
                self.item_dict[self.selected_id].item_type != 'line':
117
118
            self.status = ''
            return
ddlfighter's avatar
ddlfighter committed
119

120
121
122
123
        self.status = 'clip'
        self.temp_id = self.selected_id
        self.temp_algorithm = algorithm

SongYC's avatar
SongYC committed
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
    def finish_draw(self):
        self.temp_id = self.main_window.get_id()

    def clear_selection(self):
        if self.selected_id != '':
            self.item_dict[self.selected_id].selected = False
            self.selected_id = ''

    def selection_changed(self, selected):
        self.main_window.statusBar().showMessage('图元选择: %s' % selected)
        if self.selected_id != '':
            self.item_dict[self.selected_id].selected = False
            self.item_dict[self.selected_id].update()
        self.selected_id = selected
        self.item_dict[selected].selected = True
        self.item_dict[selected].update()
        self.status = ''
        self.updateScene([self.sceneRect()])
142
143
144
145
    def get_item_at_click(self, event):
        pos = event.pos()
        item = self.itemAt(pos)
        return item
SongYC's avatar
SongYC committed
146

147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171

    def wheelEvent(self, event: QWheelEvent) -> None:
        '''
        鼠标滑轮每动一格, angleY的变化值为15
        '''
        angle = event.angleDelta()/8
        angleY = angle.y()
        if self.status == 'scale':
            if angleY > 0:
                self.base_scale += 0.1
            else:
                self.base_scale -= 0.1
                if self.base_scale < 0:
                    self.base_scale = 0
            if self.center_p is not None:
                temp_list = copy.deepcopy(self.p_list)
                self.temp_item.p_list = alg.scale(temp_list, self.center_p[0], self.center_p[1], self.base_scale)
            self.updateScene([self.sceneRect()])
        elif self.status == 'rotate':
            self.r += angleY
            if self.center_p is not None:
                temp_list = copy.deepcopy(self.p_list)
                self.temp_item.p_list = alg.rotate(temp_list, self.center_p[0], self.center_p[1], self.r)
            self.updateScene([self.sceneRect()])

SongYC's avatar
SongYC committed
172
    def mousePressEvent(self, event: QMouseEvent) -> None:
173
174
175
        # item = self.get_item_at_click(event)
        # if isinstance(item, QGraphicsItem):
        #     print('YYYYYYYYYES')
SongYC's avatar
bug fix    
SongYC committed
176
177
178
        pos = self.mapToScene(event.localPos().toPoint())
        x = int(pos.x())
        y = int(pos.y())
SongYC's avatar
SongYC committed
179
        if self.status == 'line':
180
181
            self.temp_item = MyItem(self.temp_id, self.status, [[x, y], [x, y]], self.temp_algorithm)
            self.scene().addItem(self.temp_item)
182
183
184
185
186
187
188
189
190
191
192
193
        elif self.status == 'ellipse':
            if event.button() == Qt.LeftButton:  # 检测鼠标按键是否为左键
                self.temp_item = MyItem(self.temp_id, self.status, [[x, y], [x, y]], self.temp_algorithm)
                self.scene().addItem(self.temp_item)
        elif self.status == 'polygon':
            '''
            操作逻辑:第一次press时,记录下起点和终止点位置,同时move和release与line操作一致
            随后的press操作仅记录终止点位置,以上一次终点的位置为起点进行绘制
            最终收到右键操作时,将起点添加到p_list中,完成绘制
            '''
            if event.button() == Qt.LeftButton:
                self.last_click_button = Qt.LeftButton
194
195
                if self.temp_item is None:  # 如果为空
                    self.temp_item = MyItem(self.temp_id, self.status, [[x, y], [x, y]], self.temp_algorithm)
196
197
198
                    self.scene().addItem(self.temp_item)
                else:
                    self.temp_item.p_list.append([x, y])
199
            elif event.button() == Qt.RightButton:  # 右键操作:如果为空,默认不进行操作
200
                self.last_click_button = Qt.RightButton
201
                if self.temp_item is not None:  # 如果不为空,向p_list中添加起点
202
203
                    x = copy.deepcopy(self.temp_item.p_list[0])
                    self.temp_item.p_list.append(x)
204
205
206
        elif self.status == 'curve':
            if event.button() == Qt.LeftButton:
                self.last_click_button = Qt.LeftButton
207
208
                if self.temp_item is None:
                    self.temp_item = MyItem(self.temp_id, self.status, [[x, y], [x, y]], self.temp_algorithm)
209
210
211
                    self.scene().addItem(self.temp_item)
                else:
                    self.temp_item.p_list.append([x, y])
212
213

            elif event.button() == Qt.RightButton:  # 此处的右键仅起结束作用
214
                self.last_click_button = Qt.RightButton
215
216
217
218
219
220
221
222
        elif self.status == 'translate':
            '''
            Version 1.0: 直接判断press点和release点之间的dx,dy,进行平移操作
            '''
            self.temp_item = self.item_dict[self.temp_id]
            if event.button() == Qt.LeftButton:
                self.last_click_button = Qt.LeftButton
                self.temp_move = [[x, y], [x, y]]
223
224
225
226
227
228
229
230
231
232
233
234
235

        elif self.status == 'scale' or self.status == 'rotate':
            '''
            Version 1.0: 鼠标左键确定点,滑轮确定缩放倍数;必须先确定点,再进行缩放
            '''
            self.temp_item = self.item_dict[self.temp_id]
            if event.button() == Qt.LeftButton:
                self.p_list = copy.deepcopy(self.temp_item.p_list)
                self.last_click_button = Qt.LeftButton
                self.center_p = [x, y]
            elif event.button() == Qt.RightButton:  # 右键作为结束标志
                self.last_click_button = Qt.RightButton

236
        elif self.status == 'clip':
ddlfighter's avatar
ddlfighter committed
237
238
239
240
241
            self.temp_item = self.item_dict[self.temp_id]
            if event.button() == Qt.LeftButton:
                self.p_list = copy.deepcopy(self.temp_item.p_list)
                self.last_click_button = Qt.LeftButton
                self.windows = [[x, y], [x, y]]
242

SongYC's avatar
SongYC committed
243
244
245
246
        self.updateScene([self.sceneRect()])
        super().mousePressEvent(event)

    def mouseMoveEvent(self, event: QMouseEvent) -> None:
247

SongYC's avatar
bug fix    
SongYC committed
248
249
250
        pos = self.mapToScene(event.localPos().toPoint())
        x = int(pos.x())
        y = int(pos.y())
251

SongYC's avatar
SongYC committed
252
253
        if self.status == 'line':
            self.temp_item.p_list[1] = [x, y]
254
255
256
257
        elif self.status == 'ellipse':
            self.temp_item.p_list[1] = [x, y]
        elif self.status == 'polygon':
            if self.last_click_button == Qt.LeftButton:
258
                self.temp_item.p_list[len(self.temp_item.p_list) - 1] = [x, y]
259
260
        elif self.status == 'curve':
            if self.last_click_button == Qt.LeftButton:
261
262
263
                self.temp_item.p_list[len(self.temp_item.p_list) - 1] = [x, y]
        elif self.status == 'translate':
            if self.last_click_button == Qt.LeftButton:
ddlfighter's avatar
ddlfighter committed
264
                # self.temp_item = self.item_dict[self.temp_id]
265
266
267
                self.temp_move[1] = [x, y]
                dx = self.temp_move[1][0] - self.temp_move[0][0]
                dy = self.temp_move[1][1] - self.temp_move[0][1]
268
269
270
                self.p_list = copy.deepcopy(self.temp_item.p_list)
                self.temp_item.p_list = alg.translate(self.p_list, dx, dy)
                self.temp_move[0] = [x, y]
ddlfighter's avatar
ddlfighter committed
271
272
273
274
275
276
        elif self.status == 'clip':
            if self.last_click_button == Qt.LeftButton:
                self.windows[1] = [x, y]
                p0, p1 = self.windows[0], self.windows[1]
                temp_list = copy.deepcopy(self.p_list)
                self.temp_item.p_list = alg.clip(temp_list, p0[0], p0[1], p1[0], p1[1], self.temp_algorithm)
SongYC's avatar
SongYC committed
277
278
279
280
281
282
283
        self.updateScene([self.sceneRect()])
        super().mouseMoveEvent(event)

    def mouseReleaseEvent(self, event: QMouseEvent) -> None:
        if self.status == 'line':
            self.item_dict[self.temp_id] = self.temp_item
            self.list_widget.addItem(self.temp_id)
284
            self.temp_item = None
SongYC's avatar
SongYC committed
285
            self.finish_draw()
286
287
288
        elif self.status == 'ellipse':
            self.item_dict[self.temp_id] = self.temp_item
            self.list_widget.addItem(self.temp_id)
289
            self.temp_item = None
290
291
292
293
294
295
            self.finish_draw()
        elif self.status == 'polygon':
            if self.last_click_button == Qt.RightButton:
                self.item_dict[self.temp_id] = self.temp_item
                self.list_widget.addItem(self.temp_id)
                self.finish_draw()
296
                self.temp_item = None
297
298
299
300
301
302
                self.last_click_button = None
        elif self.status == 'curve':
            if self.last_click_button == Qt.RightButton:
                self.item_dict[self.temp_id] = self.temp_item
                self.list_widget.addItem(self.temp_id)
                self.finish_draw()
303
                self.temp_item = None
304
                self.last_click_button = None
305
306
307
        elif self.status == 'translate':
            if self.last_click_button == Qt.LeftButton:
                self.finish_draw()
308
                self.p_list = []
309
310
                self.temp_item = None
                self.last_click_button = None
311
                self.selected_id = ''
312
313
314
315
316
317
318
319
320
        elif self.status == 'scale' or self.status == 'rotate':
            if self.last_click_button == Qt.RightButton:
                self.finish_draw()
                self.center_p = []
                self.p_list = []
                self.base_scale = 1
                self.temp_item = None
                self.last_click_button = None
                self.selected_id = ''
ddlfighter's avatar
ddlfighter committed
321
322
323
324
325
326
327
328
        elif self.status == 'clip':
            if self.last_click_button == Qt.LeftButton:
                self.finish_draw()
                self.windows = []
                self.p_list = []
                self.temp_item = None
                self.last_click_button = None
                self.selected_id = ''
329

SongYC's avatar
SongYC committed
330
331
332
333
334
335
336
        super().mouseReleaseEvent(event)


class MyItem(QGraphicsItem):
    """
    自定义图元类,继承自QGraphicsItem
    """
337

SongYC's avatar
SongYC committed
338
339
340
341
342
343
344
345
346
347
    def __init__(self, item_id: str, item_type: str, p_list: list, algorithm: str = '', parent: QGraphicsItem = None):
        """

        :param item_id: 图元ID
        :param item_type: 图元类型,'line'、'polygon'、'ellipse'、'curve'等
        :param p_list: 图元参数
        :param algorithm: 绘制算法,'DDA'、'Bresenham'、'Bezier'、'B-spline'等
        :param parent:
        """
        super().__init__(parent)
348
        self.id = item_id  # 图元ID
SongYC's avatar
SongYC committed
349
        self.item_type = item_type  # 图元类型,'line'、'polygon'、'ellipse'、'curve'等
350
        self.p_list = p_list  # 图元参数
SongYC's avatar
SongYC committed
351
352
353
354
        self.algorithm = algorithm  # 绘制算法,'DDA'、'Bresenham'、'Bezier'、'B-spline'等
        self.selected = False

    def paint(self, painter: QPainter, option: QStyleOptionGraphicsItem, widget: Optional[QWidget] = ...) -> None:
355
        global color  # 通过全局变量控制画笔颜色
SongYC's avatar
SongYC committed
356
        if self.item_type == 'line':
357
            painter.setPen(color)
SongYC's avatar
SongYC committed
358
359
360
361
            item_pixels = alg.draw_line(self.p_list, self.algorithm)
            for p in item_pixels:
                painter.drawPoint(*p)
            if self.selected:
362
                painter.setPen(QColor(255, 0, 0))
SongYC's avatar
SongYC committed
363
364
                painter.drawRect(self.boundingRect())
        elif self.item_type == 'polygon':
365
366
367
368
369
370
371
            painter.setPen(color)
            item_pixels = alg.draw_polygon(self.p_list, self.algorithm)
            for p in item_pixels:
                painter.drawPoint(*p)
            if self.selected:
                painter.setPen(QColor(255, 0, 0))
                painter.drawRect(self.boundingRect())
SongYC's avatar
SongYC committed
372
        elif self.item_type == 'ellipse':
373
374
375
376
377
378
379
            painter.setPen(color)
            item_pixels = alg.draw_ellipse(self.p_list)
            for p in item_pixels:
                painter.drawPoint(*p)
            if self.selected:
                painter.setPen(QColor(255, 0, 0))
                painter.drawRect(self.boundingRect())
SongYC's avatar
SongYC committed
380
        elif self.item_type == 'curve':
381
            painter.setPen(color)
382
383
384
            lst = copy.deepcopy(self.p_list)
            # item_pixels = alg.draw_curve(self.p_list, self.algorithm)
            item_pixels = alg.draw_curve(lst, self.algorithm)
385
386
387
388
389
            for p in item_pixels:
                painter.drawPoint(*p)
            if self.selected:
                painter.setPen(QColor(255, 0, 0))
                painter.drawRect(self.boundingRect())
SongYC's avatar
SongYC committed
390

391
    # TODO: 补充另外三种图元
SongYC's avatar
SongYC committed
392
393
394
395
396
397
398
399
400
401
    def boundingRect(self) -> QRectF:
        if self.item_type == 'line':
            x0, y0 = self.p_list[0]
            x1, y1 = self.p_list[1]
            x = min(x0, x1)
            y = min(y0, y1)
            w = max(x0, x1) - x
            h = max(y0, y1) - y
            return QRectF(x - 1, y - 1, w + 2, h + 2)
        elif self.item_type == 'polygon':
402
403
404
405
406
407
408
            x_list = [i[0] for i in self.p_list]
            y_list = [i[1] for i in self.p_list]
            x = min(x_list)
            y = min(y_list)
            w = max(x_list) - x
            h = max(y_list) - y
            return QRectF(x - 1, y - 1, w + 2, h + 2)
SongYC's avatar
SongYC committed
409
        elif self.item_type == 'ellipse':
410
411
412
413
414
415
416
            x0, y0 = self.p_list[0]
            x1, y1 = self.p_list[1]
            x = min(x0, x1)
            y = min(y0, y1)
            w = max(x0, x1) - x
            h = max(y0, y1) - y
            return QRectF(x - 1, y - 1, w + 2, h + 2)
SongYC's avatar
SongYC committed
417
        elif self.item_type == 'curve':
418
419
420
421
422
423
424
            x_list = [i[0] for i in self.p_list]
            y_list = [i[1] for i in self.p_list]
            x = min(x_list)
            y = min(y_list)
            w = max(x_list) - x
            h = max(y_list) - y
            return QRectF(x - 1, y - 1, w + 2, h + 2)
SongYC's avatar
SongYC committed
425

426

SongYC's avatar
SongYC committed
427
428
429
430
class MainWindow(QMainWindow):
    """
    主窗口类
    """
431

SongYC's avatar
SongYC committed
432
433
    def __init__(self):
        super().__init__()
434
        # self.item_cnt = -1
SongYC's avatar
SongYC committed
435
436
437
438
439
440
441
442
443
444
445
446
447

        # 使用QListWidget来记录已有的图元,并用于选择图元。注:这是图元选择的简单实现方法,更好的实现是在画布中直接用鼠标选择图元
        self.list_widget = QListWidget(self)
        self.list_widget.setMinimumWidth(200)

        # 使用QGraphicsView作为画布
        self.scene = QGraphicsScene(self)
        self.scene.setSceneRect(0, 0, 600, 600)
        self.canvas_widget = MyCanvas(self.scene, self)
        self.canvas_widget.setFixedSize(600, 600)
        self.canvas_widget.main_window = self
        self.canvas_widget.list_widget = self.list_widget

448
449
450
451
        # 设置图标
        icon = QIcon()
        icon.addPixmap(QPixmap(r"paint.ico"), QIcon.Normal, QIcon.Off)
        self.setWindowIcon(icon)
SongYC's avatar
SongYC committed
452
453
454
455
456
        # 设置菜单栏
        menubar = self.menuBar()
        file_menu = menubar.addMenu('文件')
        set_pen_act = file_menu.addAction('设置画笔')
        reset_canvas_act = file_menu.addAction('重置画布')
ddlfighter's avatar
ddlfighter committed
457
        save_canvas_act = file_menu.addAction('保存画布')
SongYC's avatar
SongYC committed
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
        exit_act = file_menu.addAction('退出')
        draw_menu = menubar.addMenu('绘制')
        line_menu = draw_menu.addMenu('线段')
        line_naive_act = line_menu.addAction('Naive')
        line_dda_act = line_menu.addAction('DDA')
        line_bresenham_act = line_menu.addAction('Bresenham')
        polygon_menu = draw_menu.addMenu('多边形')
        polygon_dda_act = polygon_menu.addAction('DDA')
        polygon_bresenham_act = polygon_menu.addAction('Bresenham')
        ellipse_act = draw_menu.addAction('椭圆')
        curve_menu = draw_menu.addMenu('曲线')
        curve_bezier_act = curve_menu.addAction('Bezier')
        curve_b_spline_act = curve_menu.addAction('B-spline')
        edit_menu = menubar.addMenu('编辑')
        translate_act = edit_menu.addAction('平移')
        rotate_act = edit_menu.addAction('旋转')
        scale_act = edit_menu.addAction('缩放')
        clip_menu = edit_menu.addMenu('裁剪')
        clip_cohen_sutherland_act = clip_menu.addAction('Cohen-Sutherland')
        clip_liang_barsky_act = clip_menu.addAction('Liang-Barsky')

        # 连接信号和槽函数
        exit_act.triggered.connect(qApp.quit)
481
482
483
484
        # Pen_signal
        set_pen_act.triggered.connect(self.set_pen_action)
        # Canvas_signal
        reset_canvas_act.triggered.connect(self.reset_canvas_action)
ddlfighter's avatar
ddlfighter committed
485
        save_canvas_act.triggered.connect(self.save_canvas_action)
486
        # Line_signal
SongYC's avatar
SongYC committed
487
        line_naive_act.triggered.connect(self.line_naive_action)
181860021's avatar
181860021 committed
488
489
        line_dda_act.triggered.connect(self.line_dda_action)
        line_bresenham_act.triggered.connect(self.line_bresenham_action)
490
        # Polygon_signal
181860021's avatar
181860021 committed
491
        polygon_dda_act.triggered.connect(self.polygon_dda_action)
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
        polygon_bresenham_act.triggered.connect(self.polygon_bresenham_action)
        # Ellipse_signal
        ellipse_act.triggered.connect(self.ellipse_action)
        # Curve_signal
        curve_bezier_act.triggered.connect(self.curve_bezier_action)
        curve_b_spline_act.triggered.connect(self.curve_b_spline_action)
        # Translate_signal
        translate_act.triggered.connect(self.translate_action)
        # Rotate_signal
        rotate_act.triggered.connect(self.rotate_action)
        # Scale_signal
        scale_act.triggered.connect(self.scale_action)
        # Clip_signal
        clip_cohen_sutherland_act.triggered.connect(self.clip_cohen_sutherland_action)
        clip_liang_barsky_act.triggered.connect(self.clip_liang_barsky_action)
181860021's avatar
181860021 committed
507

SongYC's avatar
SongYC committed
508
509
510
511
512
513
514
515
516
        self.list_widget.currentTextChanged.connect(self.canvas_widget.selection_changed)

        # 设置主窗口的布局
        self.hbox_layout = QHBoxLayout()
        self.hbox_layout.addWidget(self.canvas_widget)
        self.hbox_layout.addWidget(self.list_widget, stretch=1)
        self.central_widget = QWidget()
        self.central_widget.setLayout(self.hbox_layout)
        self.setCentralWidget(self.central_widget)
517
        self.statusBar().showMessage('空闲')  # MainWindow对象下端状态栏
SongYC's avatar
SongYC committed
518
519
520
521
        self.resize(600, 600)
        self.setWindowTitle('CG Demo')

    def get_id(self):
522
        ''' # version 1: 【缺点】在进行切换时,会导致序号+1. 例如:id=0为DDA画线,切换为Naive后,所得序号为2,跨越序号1
SongYC's avatar
SongYC committed
523
        self.item_cnt += 1
524
        _id = str(self.item_cnt)
SongYC's avatar
SongYC committed
525
        return _id
526
527
        '''
        return str(len(self.canvas_widget.list_widget))
528

529
530
    # ResetCanvas Action

531
532
533
534
535
536
537
538
    # Pen Action
    def set_pen_action(self):
        global color
        color = QColorDialog.getColor()
        self.statusBar().showMessage("设置画笔")

    # Canvas Action
    def reset_canvas_action(self):
539
        # self.item_cnt = 0  # 重置计数
540
541
        self.canvas_widget.reset_canvas()
        self.statusBar().showMessage("重置画布")
542

ddlfighter's avatar
ddlfighter committed
543
544
545
546
547
548
549
550
551
552
    def save_canvas_action(self):
        self.statusBar().showMessage("保存画布")
        dialog = QFileDialog()
        file_name = dialog.getSaveFileName(filter="Image Files(*.jpg *.png *.bmp)")
        if file_name[0]:
            self.canvas_widget.save_canvas(file_name[0], 600, 600)




553
    # Line Action
SongYC's avatar
SongYC committed
554
555
556
557
558
559
    def line_naive_action(self):
        self.canvas_widget.start_draw_line('Naive', self.get_id())
        self.statusBar().showMessage('Naive算法绘制线段')
        self.list_widget.clearSelection()
        self.canvas_widget.clear_selection()

181860021's avatar
181860021 committed
560
561
562
563
564
    def line_dda_action(self):
        self.canvas_widget.start_draw_line('DDA', self.get_id())
        self.statusBar().showMessage('DDA算法绘制线段')
        self.list_widget.clearSelection()
        self.canvas_widget.clear_selection()
SongYC's avatar
SongYC committed
565

181860021's avatar
181860021 committed
566
567
568
569
570
    def line_bresenham_action(self):
        self.canvas_widget.start_draw_line('Bresenham', self.get_id())
        self.statusBar().showMessage('Bresenham算法绘制线段')
        self.list_widget.clearSelection()
        self.canvas_widget.clear_selection()
571
572

    # Polygon Action
181860021's avatar
181860021 committed
573
    def polygon_dda_action(self):
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
        self.canvas_widget.start_draw_polygon('DDA', self.get_id())
        self.statusBar().showMessage('DDA算法绘制多边形')
        self.list_widget.clearSelection()
        self.canvas_widget.clear_selection()

    def polygon_bresenham_action(self):
        self.canvas_widget.start_draw_polygon('Bresenham', self.get_id())
        self.statusBar().showMessage('Bresenham算法绘制多边形')
        self.list_widget.clearSelection()
        self.canvas_widget.clear_selection()

    # Ellipse Action
    def ellipse_action(self):
        self.canvas_widget.start_draw_ellipse(self.get_id())
        self.statusBar().showMessage('椭圆绘制')
        self.list_widget.clearSelection()
        self.canvas_widget.clear_selection()

    # Curve Action
    def curve_bezier_action(self):
594
595
596
597
        self.canvas_widget.start_draw_curve('Bezier', self.get_id())
        self.statusBar().showMessage('Bezier算法绘制曲线')
        self.list_widget.clearSelection()
        self.canvas_widget.clear_selection()
598
599

    def curve_b_spline_action(self):
600
601
602
603
        self.canvas_widget.start_draw_curve('B-spline', self.get_id())
        self.statusBar().showMessage('B-spline算法绘制曲线')
        self.list_widget.clearSelection()
        self.canvas_widget.clear_selection()
604
605

    def translate_action(self):
606
607
608
609
        self.canvas_widget.start_translate()
        self.statusBar().showMessage('平移')
        self.list_widget.clearSelection()
        self.canvas_widget.clear_selection()
ddlfighter's avatar
ddlfighter committed
610

611
612

    def rotate_action(self):
613
614
615
616
        self.canvas_widget.start_rotate()
        self.statusBar().showMessage('旋转')
        self.list_widget.clearSelection()
        self.canvas_widget.clear_selection()
617
618

    def scale_action(self):
619
620
621
622
        self.canvas_widget.start_scale()
        self.statusBar().showMessage('缩放')
        self.list_widget.clearSelection()
        self.canvas_widget.clear_selection()
623
624

    def clip_cohen_sutherland_action(self):
625
626
627
628
629
        self.canvas_widget.start_clip('Cohen-Sutherland')
        self.statusBar().showMessage('Cohen-Sutherland算法裁剪')
        self.list_widget.clearSelection()
        self.canvas_widget.clear_selection()

630
    def clip_liang_barsky_action(self):
ddlfighter's avatar
ddlfighter committed
631
632
        self.canvas_widget.start_clip('Liang-Barsky')
        self.statusBar().showMessage('Liang-Barsky算法裁剪')
633
634
        self.list_widget.clearSelection()
        self.canvas_widget.clear_selection()
635

636

SongYC's avatar
SongYC committed
637
638
639
640
641
if __name__ == '__main__':
    app = QApplication(sys.argv)
    mw = MainWindow()
    mw.show()
    sys.exit(app.exec_())