class MainWindow(QMainWindow): def reset_canvas_action(self): self.item_cnt = 0 self.canvas_widget.reset_canvas() #self.list_widget.clear() self.list_widget.currentTextChanged.disconnect( self.canvas_widget.selection_changed) self.list_widget.clear() self.list_widget.currentTextChanged.connect( self.canvas_widget.selection_changed) self.scene = QGraphicsScene(self) self.scene.setSceneRect(1, 1, 601, 601) #挪一个像素,不然会有边框线 self.item_cnt = 0 self.statusBar().showMessage('重置画布') self.canvas_widget.setScene(self.scene) #self.canvas_widget = MyCanvas(self.scene, self.Image_window) #解决了一个bug参考 https://blog.csdn.net/yaowangII/article/details/80929261 def save_canvas_action(self): # pixMap = view->grab(view->sceneRect().toRect()); # QString # fileName = QFileDialog::getSaveFileName(this, "Save image", # QCoreApplication::applicationDirPath(), "BMP Files (*.bmp);;JPEG (*.JPEG);;PNG (*.png)" ); # filename=QFileDialog.getSaveFileName("Save image",QCoreApplication.applicationDirPath(),"BMP Files (*.bmp);;JPEG (*.JPEG);;PNG (*.png)") filename, ok2 = QFileDialog.getSaveFileName( self, "Save Image", QDir.currentPath(), "BMP Files (*.bmp);;JPEG (*.JPEG);;PNG (*.png)") # pixmap = QPixmap() pixmap = self.canvas_widget.grab( self.canvas_widget.sceneRect().toRect()) pixmap.save(filename) def theme1_action(self): self.setStyleSheet(css1) def theme2_action(self): self.setStyleSheet(css2) def Menu_init(self): menubar = self.menuBar() # 菜单栏 mfile = menubar.addMenu("文件") themefile = menubar.addMenu("主题") # 重置 reset_canvas_act = QAction(QIcon("./icon/file.png"), "重置画布", self) reset_canvas_act.triggered.connect( self.reset_canvas_action) # To be done # 保存 save_canvas_act = QAction(QIcon("./icon/save.png"), "保存画布", self) save_canvas_act.triggered.connect(self.save_canvas_action) #默认主题: theme1_act = QAction("Blue theme", self) theme1_act.triggered.connect(self.theme1_action) theme2_act = QAction("Coffee theme", self) theme2_act.triggered.connect(self.theme2_action) # 将action添加到file上面 mfile.addAction(reset_canvas_act) mfile.addAction(save_canvas_act) #将action添加到theme上面 themefile.addAction(theme1_act) themefile.addAction(theme2_act) # 工具栏 toolbar = QToolBar() toolbar.setMovable(False) self.addToolBar(toolbar) toolbar.addAction(reset_canvas_act) toolbar.addAction(save_canvas_act) def pen_width(self): w = self.spinbox_penwidth.text() w = int(w) # print("w:" + w) self.canvas_widget.setpenWidth(w) self.statusBar().showMessage('宽度为%d' % (w)) def pen_color(self): c = QColorDialog.getColor() self.frame_color.setPalette(QPalette(c)) # assert(0) self.frame_color.setStyleSheet("QWidget { background-color: %s }" % c.name()) # self.frame_color.setStyleSheet("QFrame{background-color: rgba("+c.red()+","+c.green()+","+c.blue()+",1);border:none}") # print(c.red()) # 参考了https://www.cnblogs.com/icat-510/p/10166882.html self.canvas_widget.setpenColor(c) def Color_init(self): colorbar = QToolBar("画笔属性栏") self.addToolBar(colorbar) colorbar.setMovable(True) label_penwidth = QLabel("画笔宽度") self.spinbox_penwidth = QSpinBox() self.spinbox_penwidth.setRange(1, 50) self.spinbox_penwidth.setValue(2) self.color_botton = QPushButton("画笔颜色") self.frame_color = QFrame(self) self.frame_color.setObjectName("colorframe") self.frame_color.setFrameShape(QFrame.Box) self.frame_color.setPalette(QPalette(Qt.black)) self.frame_color.setAutoFillBackground(True) self.frame_color.setFixedSize(30, 30) self.frame_color.setStyleSheet( "QFrame{background-color: rgba(0,0,0,1);border:none}") # 槽函数 self.spinbox_penwidth.valueChanged[int].connect(self.pen_width) self.color_botton.clicked.connect(self.pen_color) # 布局 color_layout = QHBoxLayout() color_layout.setAlignment(Qt.AlignLeft) color_layout.addWidget(label_penwidth) color_layout.addWidget(self.spinbox_penwidth) color_layout.addWidget(self.color_botton) color_layout.addWidget(self.frame_color) color_widget = QWidget() color_widget.setLayout(color_layout) colorbar.addWidget(color_widget) def layout_init(self): # p=self.takeCentralWidget() self.setDockNestingEnabled(True) # 允许嵌套 self.Tool_window = QDockWidget("工具栏") self.setCentralWidget(self.Image_window) self.addDockWidget(Qt.TopDockWidgetArea, self.Tool_window) self.addDockWidget(Qt.RightDockWidgetArea, self.List_window) def line_action(self, algorithm): self.canvas_widget.start_draw_line(algorithm, self.get_id()) self.statusBar().showMessage(algorithm + '算法绘制线段:左键点击绘制,松开结束') self.list_widget.clearSelection() self.canvas_widget.clear_selection() def DDA_line_draw_action(self): self.line_action('DDA') def Bresenham_line_draw_action(self): self.line_action('Bresenham') def polygon_action(self, algorithm): self.canvas_widget.start_draw_polygon(algorithm, self.get_id()) self.statusBar().showMessage(algorithm + '算法绘制多边形:左键点击设置控制点,右键或者切换其他工具栏图标结束') self.list_widget.clearSelection() self.canvas_widget.clear_selection() def DDA_polygon_draw_action(self): self.polygon_action('DDA') def Bresenham_polygon_draw_action(self): self.polygon_action('Bresenham') def ellipse_draw_action(self): self.canvas_widget.start_draw_ellipse(self.get_id()) self.statusBar().showMessage('中心圆算法绘制椭圆:左键点击设置控制点1,拖动松开后设置控制点2,完成绘制') self.list_widget.clearSelection() self.canvas_widget.clear_selection() def curve_draw_action(self, algorithm): self.canvas_widget.start_draw_curve(algorithm, self.get_id()) self.statusBar().showMessage(algorithm + '算法绘制曲线:左键点击设置控制点,右键或者点击其他工具栏图标结束绘制') self.list_widget.clearSelection() self.canvas_widget.clear_selection() def Bezier_curve_draw_action(self): self.curve_draw_action('Bezier') def B_spline_curve_draw_action(self): self.curve_draw_action('B-spline') def translate_draw_action(self): self.canvas_widget.start_draw_translate() self.statusBar().showMessage('平移图元:选择图元之后任意拖动,松开结束') # self.list_widget.clearSelection() # self.canvas_widget.clear_selection() def rotate_draw_action(self): self.canvas_widget.start_draw_rotate() self.statusBar().showMessage('旋转图元:选择图元之后任意旋转,松开结束') def scale_draw_action(self): self.canvas_widget.start_draw_scale() self.statusBar().showMessage('缩放图元:选择图元之后任意移动,松开结束') def clip_draw_action(self, algorithm): self.canvas_widget.start_draw_clip(algorithm) self.statusBar().showMessage(algorithm + '裁剪线段:选择线段图元之后,左键点击拖动得到红色的裁剪框,松开结束') def Cohen_Sutherland_clip_draw_action(self): self.clip_draw_action("Cohen-Sutherland") def Liang_Barsky_clip_draw_action(self): self.clip_draw_action("Liang-Barsky") def cursor_draw_action(self): self.canvas_widget.start_cursor_selection() self.statusBar().showMessage('鼠标选择:左键点击任意图元进行选择') def fill_draw_action(self): self.canvas_widget.start_fill_polygon() self.statusBar().showMessage('多边形填充:选择多边形图元之后根据颜色框颜色填充') def polygon_clip_draw_action(self): self.canvas_widget.start_cut_polygon() self.statusBar().showMessage('多边形裁剪:选择多边形图元之后左键点击拖动得到绿色裁剪框进行裁剪') def x_mirror_draw_action(self): self.canvas_widget.start_x_mirror_draw() self.statusBar().showMessage('水平方向镜像:选择图元之后点击按钮') def y_mirror_draw_action(self): self.canvas_widget.start_y_mirror_draw() self.statusBar().showMessage('竖直方向镜像:选择图元之后点击按钮') def copy_draw_action(self): self.canvas_widget.start_copy_draw(self.get_id()) self.statusBar().showMessage('复制粘贴:选择图元之后点击按钮,在原位置复制') def delete_draw_action(self): self.canvas_widget.start_delete_draw() self.statusBar().showMessage('删除图元:选择图元之后点击按钮删除') def tool_init(self): # line相关,使用的https://www.walletfox.com/course/customqtoolbutton.php做的可选算法button self.line_action_1 = QAction("DDA line") self.line_action_2 = QAction("Bresenham line") self.line_action_1.setIcon(QIcon("./icon/line.png")) self.line_action_2.setIcon(QIcon("./icon/line.png")) self.line_action_1.triggered.connect(self.DDA_line_draw_action) self.line_action_2.triggered.connect(self.Bresenham_line_draw_action) self.line_menu = QMenu() self.line_menu.addAction(self.line_action_1) self.line_menu.addAction(self.line_action_2) self.line_tool_button = CusToolButton() self.line_tool_button.setMenu(self.line_menu) self.line_tool_button.setDefaultAction(self.line_action_1) self.line_tool_bar = QToolBar(self) self.line_tool_bar.addWidget(self.line_tool_button) # polygon相关 self.polygon_action_1 = QAction("DDA polygon") self.polygon_action_2 = QAction("Bresenham polygon") self.polygon_action_1.setIcon(QIcon("./icon/polygon.png")) self.polygon_action_2.setIcon(QIcon("./icon/polygon.png")) self.polygon_action_1.triggered.connect(self.DDA_polygon_draw_action) self.polygon_action_2.triggered.connect( self.Bresenham_polygon_draw_action) self.polygon_menu = QMenu() self.polygon_menu.addAction(self.polygon_action_1) self.polygon_menu.addAction(self.polygon_action_2) self.polygon_tool_button = CusToolButton() self.polygon_tool_button.setMenu(self.polygon_menu) self.polygon_tool_button.setDefaultAction(self.polygon_action_1) self.polygon_tool_bar = QToolBar(self) self.polygon_tool_bar.addWidget(self.polygon_tool_button) # ellipse相关 self.ellipse_action = QAction("Ellipse") self.ellipse_action.setIcon(QIcon("./icon/ellipse.png")) self.ellipse_action.triggered.connect(self.ellipse_draw_action) self.ellipse_tool_bar = QToolBar(self) self.ellipse_tool_bar.addAction(self.ellipse_action) # curve相关 self.curve_action_1 = QAction("Bezier Curve") self.curve_action_1.setIcon(QIcon("./icon/curve.png")) self.curve_action_2 = QAction("B-spline Curve") self.curve_action_2.setIcon(QIcon("./icon/curve.png")) self.curve_action_1.triggered.connect(self.Bezier_curve_draw_action) self.curve_action_2.triggered.connect(self.B_spline_curve_draw_action) self.curve_menu = QMenu() self.curve_menu.addAction(self.curve_action_1) self.curve_menu.addAction(self.curve_action_2) self.curve_tool_button = CusToolButton() self.curve_tool_button.setMenu(self.curve_menu) self.curve_tool_button.setDefaultAction(self.curve_action_1) self.curve_tool_bar = QToolBar(self) self.curve_tool_bar.addWidget(self.curve_tool_button) # translate相关(平移) self.translate_action = QAction("Translate") self.translate_action.setIcon(QIcon("./icon/move.png")) self.translate_action.triggered.connect(self.translate_draw_action) self.translate_tool_bar = QToolBar(self) self.translate_tool_bar.addAction(self.translate_action) # rotate相关 旋转 self.rotate_action = QAction("Rotate") self.rotate_action.setIcon(QIcon("./icon/rotate.png")) self.rotate_action.triggered.connect(self.rotate_draw_action) self.rotate_tool_bar = QToolBar(self) self.rotate_tool_bar.addAction(self.rotate_action) # scale相关,缩放; self.scale_action = QAction("Scale") self.scale_action.setIcon(QIcon("./icon/scale.png")) self.scale_action.triggered.connect(self.scale_draw_action) self.scale_tool_bar = QToolBar(self) self.scale_tool_bar.addAction(self.scale_action) # clip 裁剪 self.clip_action_1 = QAction("Cohen-Sutherland Clip") self.clip_action_2 = QAction("Liang-Barsky Clip") self.clip_action_1.setIcon(QIcon("./icon/crop.png")) self.clip_action_2.setIcon(QIcon("./icon/crop.png")) self.clip_action_1.triggered.connect( self.Cohen_Sutherland_clip_draw_action) self.clip_action_2.triggered.connect( self.Liang_Barsky_clip_draw_action) self.clip_menu = QMenu() self.clip_menu.addAction(self.clip_action_1) self.clip_menu.addAction(self.clip_action_2) self.clip_tool_button = CusToolButton() self.clip_tool_button.setMenu(self.clip_menu) self.clip_tool_button.setDefaultAction(self.clip_action_1) self.clip_tool_bar = QToolBar(self) self.clip_tool_bar.addWidget(self.clip_tool_button) #鼠标选择相关; self.cursor_action = QAction("Cursor") self.cursor_action.setIcon(QIcon("./icon/cursor.png")) self.cursor_action.triggered.connect(self.cursor_draw_action) self.cursor_tool_bar = QToolBar(self) self.cursor_tool_bar.addAction(self.cursor_action) #多边形填充相关: self.fill_action = QAction("Fill") self.fill_action.setIcon(QIcon("./icon/fill.png")) self.fill_action.triggered.connect(self.fill_draw_action) self.fill_tool_bar = QToolBar(self) self.fill_tool_bar.addAction(self.fill_action) #多边形裁剪相关: self.polygon_clip_action = QAction("Polygon Clip") self.polygon_clip_action.setIcon(QIcon("./icon/cut_polygon.png")) self.polygon_clip_action.triggered.connect( self.polygon_clip_draw_action) self.polygon_clip_tool_bar = QToolBar(self) self.polygon_clip_tool_bar.addAction(self.polygon_clip_action) #x轴镜像相关: self.x_mirror_action = QAction("X Axis Mirror") self.x_mirror_action.setIcon(QIcon("./icon/flip_horizontal.png")) self.x_mirror_action.triggered.connect(self.x_mirror_draw_action) self.x_mirror_tool_bar = QToolBar(self) self.x_mirror_tool_bar.addAction(self.x_mirror_action) #y轴镜像相关: self.y_mirror_action = QAction("Y Axis Mirror") self.y_mirror_action.setIcon(QIcon("./icon/flip_vertical.png")) self.y_mirror_action.triggered.connect(self.y_mirror_draw_action) self.y_mirror_tool_bar = QToolBar(self) self.y_mirror_tool_bar.addAction(self.y_mirror_action) #复制粘贴相关: self.copy_action = QAction("Copy paste") self.copy_action.setIcon(QIcon("./icon/copy.png")) self.copy_action.triggered.connect(self.copy_draw_action) self.copy_tool_bar = QToolBar(self) self.copy_tool_bar.addAction(self.copy_action) #删除图元相关: self.delete_action = QAction("Delete") self.delete_action.setIcon(QIcon("./icon/trash.png")) self.delete_action.triggered.connect(self.delete_draw_action) self.delete_tool_bar = QToolBar(self) self.delete_tool_bar.addAction(self.delete_action) # #布局 tools_layout = QGridLayout() tools_layout.setAlignment(Qt.AlignLeft) tools_layout.addWidget(self.line_tool_bar, 0, 0) tools_layout.addWidget(self.polygon_tool_bar, 0, 1) tools_layout.addWidget(self.ellipse_tool_bar, 0, 2) tools_layout.addWidget(self.curve_tool_bar, 0, 3) tools_layout.addWidget(self.translate_tool_bar, 0, 4) tools_layout.addWidget(self.rotate_tool_bar, 0, 5) tools_layout.addWidget(self.scale_tool_bar, 0, 6) tools_layout.addWidget(self.clip_tool_bar, 0, 7) tools_layout.addWidget(self.cursor_tool_bar, 0, 8) tools_layout.addWidget(self.fill_tool_bar, 0, 9) tools_layout.addWidget(self.polygon_clip_tool_bar, 0, 10) tools_layout.addWidget(self.x_mirror_tool_bar, 0, 11) tools_layout.addWidget(self.y_mirror_tool_bar, 0, 12) tools_layout.addWidget(self.copy_tool_bar, 0, 13) tools_layout.addWidget(self.delete_tool_bar, 0, 14) # 加入tool_window tools_widget = QWidget(self.Tool_window) tools_widget.setLayout(tools_layout) self.Tool_window.setWidget(tools_widget) self.Tool_window.setFeatures(QDockWidget.DockWidgetMovable | QDockWidget.DockWidgetFloatable) # # # #按钮组 通过按钮组的值连接槽函数确定状态 # toolbuttons=QButtonGroup() # toolbuttons.addButton(line_button_1,1) # # # toolbuttons.buttonClicked[int].connect(self.tool_clicked) # def tool_clicked(self,type:int): # a=type def __init__(self): super().__init__() self.item_cnt = 0 ## 主窗口布局 # 图片与标题 QMainWindow.setWindowIcon(self, QIcon("./picture/icon.png")) QMainWindow.setWindowTitle(self, "Image Editor By ytr") # self.setWindowTitle('CG Demo') # 界面大小位置 # QMainWindow.resize(self,QApplication.desktop().width()*0.9,QApplication.desktop().height()*0.9) # QMainWindow.move(self,QApplication.desktop().width()*0.05,QApplication.desktop().height()*0.05) self.Menu_init() self.Color_init() self.Image_window = QDockWidget("图像编辑框") self.Image_window.setFeatures(QDockWidget.DockWidgetMovable | QDockWidget.DockWidgetFloatable) self.Image_window.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) self.Image_window.setMinimumSize(620, 620) #大一点点 不然会有边框线 self.List_window = QDockWidget("图元列表") self.List_window.setFeatures(QDockWidget.DockWidgetMovable) self.list_widget = QListWidget(self.List_window) self.list_widget.setMinimumWidth(200) self.scene = QGraphicsScene(self) self.scene.setSceneRect(1, 1, 601, 601) #挪一个像素,不然会有边框线 self.canvas_widget = MyCanvas(self.scene, self.Image_window) self.canvas_widget.setFixedSize(610, 610) #这样就没有滑动条了 self.canvas_widget.main_window = self self.canvas_widget.list_widget = self.list_widget self.List_window.setWidget(self.list_widget) self.Image_window.setWidget(self.canvas_widget) self.setCentralWidget(self.Image_window) height = self.Image_window.height() width = self.Image_window.width() center_y = (self.canvas_widget.geometry().height() - height) / 2 center_x = (self.canvas_widget.geometry().width() - width) / 2 self.canvas_widget.setGeometry(center_x, center_y, self.canvas_widget.geometry().width(), self.canvas_widget.geometry().height()) self.canvas_widget.setAlignment(Qt.AlignCenter) # 槽函数 self.list_widget.currentTextChanged.connect( self.canvas_widget.selection_changed) self.layout_init() self.tool_init() self.setStyleSheet(css) # 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.Image_window) # self.central_widget.setLayout(self.hbox_layout) # self.setCentralWidget(self.central_widget) self.statusBar().showMessage('空闲') self.resize(600, 600) def get_id(self): _id = str(self.item_cnt) self.item_cnt += 1 return _id