画板示例程序(PYQT5,用标签控件作画板实现画直线,矩形,文本等)

结合我的上一篇多线程画板DEMO小程序,我又边学边作了可实现画直线、矩形、填充矩形、圆、椭圆、随手画、文本的画板程序。为减少代码量,所画形状的颜色、线宽、线型、填充形状、字体、字号等采用随机方式,主要是看效果,框架已搭好有兴趣的朋友继续深化代码完成即可。

主界面上设置两个绘画区,左侧画板(实际就是QT5或QT6的标签控件)支持鼠标操作当画板用来绘制各种型号图形,右侧画板(实际也是QT5或QT6的标签控件)采用多线程自动绘制彩色同心圆和彩色文本。

本程序有完整的界面框架:主窗体、主窗体上的菜单栏、工具栏、状态栏。子窗体及子窗体同主窗体交互,各种事件的重载,信号槽的定义和使用,多线程的定义和多线程同窗体数据的通信等都有涉及,仅作为练手学习用,细节没有太深化,没有详细检测BUG,有兴趣的朋友可以继续完善代码和界面。

代码中的t1.png等图片名称在运行时自行准备和更改替换代码,为方便小白运行,自定义的几个类都放在一个文件里了便于复制和运行,可以按类名称拆分到几个模块中方便管理

运行界面如下:

# -*- coding: utf-8 -*-
import sys,random,time,math,copy
import PyQt5
from PyQt5 import *
from PyQt5 import QtCore   #不加此行要报错,上行不是全导入了嘛,没懂
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
#from turtle import *   #本示例没有使用turtle库无需导入

#定义主窗口类(继承自QMainWindow)
class MypaintWindow(QMainWindow):  
    def __init__(self):
        super().__init__()
        #self.setGeometry(300, 300, 300, 200)
        self.resize(1600, 905)
        self.setMaximumSize(1428,905)
        self.setWindowTitle('PYQT简易画板')
        self.initUi()
    def initUi(self):
        # 创建状态栏
        self.statusbar = self.statusBar()
        self.statusbar.showMessage('准备')

        #创建标签画板(本类要重载继承QLabel),在窗体右侧,作为画板区域)
        self.label_Draw =  MyLabel(self)
        # 设置label的尺寸
        self.label_Draw.setMaximumSize(600,800)
        self.label_Draw.setGeometry(5, 76, 600, 800)
        #创建标签画板DEMO(本类要重载继承QLabel,在窗体右侧,演示绘画动画)
        self.label_Demo =  MyLabelDemo(self)
        self.label_Demo.setMaximumSize(800,800)
        self.label_Demo.setGeometry(620, 76, 800, 800)

        # 把pix_img传递给label
        #self.label_Draw.setPixmap(self.pix)
        # 设置pix_img填充满Label
       # self.label_Draw.label_DrawsetScaledContents(True)
        self.label_Draw.setScaledContents(True)
        self.label_Demo.setScaledContents(True)
        #self.label_Draw.setPixmap(QPixmap("1.jpg"))   #此语句无效,标签同画板绑定后,不会加载外部图像了

        #初始化工具栏
        self.initToolBar()
        
        #定义一菜单对象
        menubar = self.menuBar()
        fileMenu = menubar.addMenu('文件')
        menu_New = QAction('保存画板', self)
        menu_New.setStatusTip('在状态栏上显示内容:将当前画板中的图像保存到文件')
        fileMenu.addAction(menu_New)
        menu_Load = QMenu('导入', self)
        subMenu_LoadImg= QAction('导入图像', self)
        subMenu_LoadImg.setStatusTip('在状态栏上显示内容:导入一外部图形文件到画板')
        menu_Load.addAction(subMenu_LoadImg)
        fileMenu.addMenu(menu_Load)

        mnu_Exit = QAction(QIcon("t08.png"),'退出程序',self)
        mnu_Exit.setShortcut("ctrl+Q")  
        mnu_Exit.setStatusTip('在状态栏上显示内容:退出程序')
        mnu_Exit.triggered.connect(qApp.quit)
        fileMenu.addAction(mnu_Exit)
        sta = self.statusBar()       

        # 本例创建了一个行为菜单。这个行为/动作能切换状态栏显示或者隐藏。
        menu_View = menubar.addMenu('选项')
        viewStatAct = QAction('显示/隐藏状态栏', self, checkable=True)
        viewStatAct.setStatusTip('在状态栏上显示内容:视图菜单->显示/隐藏状态栏')        # 用checkable选项创建一个能选中的菜单。
        viewStatAct.setChecked(True)        # 默认设置为选中状态
    
        menu_View.addAction(viewStatAct)
    ##############################################################
        self.threadMaxCount=2     #本程序最大可开多线程的数量   
        self.demoClickNum=0   #DEMO标签控件被单击的次数,超出threadMaxCount归0循环(0值即线程全停)
        #定义槽函数,标签DEMO被单击的次数决定启动线程的数量
        #定义线程数组
        self.thread={}
        self.threadOpen=[]   #0索引起用,0对应首个线程
        for i in range(self.threadMaxCount):
            self.threadOpen.append(False)      #定义n个线程打开的状况,供计时器函数中取线程值时使用
            self.thread[i] = ThreadClass(parent=None,index=i)
            self.threadOpen[i]=False   #设置线程暂不打开,单击标签画板后打开
            #self.thread[i].start()
            self.setThreadObj(i,self.label_Demo)  #向线程中传入标签控件实例对象
            self.thread[i].signal_ID.connect(self.my_function)      #将线程1中的自定义信号signal_ID绑定槽函数self.my_function
        self.label_Demo.signal_clicked.connect(self.labDemoClick)         #将自定义的DEMO标签类信号

    #初始化工具栏
    def initToolBar(self):
        self.toolBar_main = QToolBar("绘图工具栏")
        self.addToolBar(self.toolBar_main )
        #self.addToolBar(Qt.ToolBarArea.TopToolBarArea, self.toolBar_main)
        self.toolBar_main.setObjectName(u"toolBar_main")
        self.toolBar_main.setFocusPolicy(Qt.FocusPolicy.ClickFocus)
        self.toolBar_main.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonTextUnderIcon)

        self.setIconSize(QSize(24, 24))
        self.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonTextUnderIcon)

        self.act_DrawLine = QAction(QIcon("./res/t01.png"), "画线", self)
        self.act_DrawLine.setObjectName(u"act_DrawLine")
        self.act_DrawLine.triggered.connect(self.draw_Line)
        self.toolBar_main.addAction(self.act_DrawLine)

        self.act_DrawRect = QAction(QIcon("./res/t02.png"), "画矩形", self)
        self.act_DrawRect.setObjectName(u"act_DrawRect")
        self.act_DrawRect.triggered.connect(self.draw_Rect)
        self.toolBar_main.addAction(self.act_DrawRect)

        self.act_DrawFillRect = QAction(QIcon("./res/t03.png"), "画填充矩形", self)
        self.act_DrawFillRect.setObjectName(u"act_DrawFillRect")
        self.act_DrawFillRect.triggered.connect(self.draw_FillRect)
        self.toolBar_main.addAction(self.act_DrawFillRect)

        self.act_DrawCircle = QAction(QIcon("./res/t04.png"), "画圆", self)
        self.act_DrawCircle.setObjectName(u"act_DrawCircle")
        self.act_DrawCircle.triggered.connect(self.draw_Circle)
        self.toolBar_main.addAction(self.act_DrawCircle)

        self.act_DrawEllptic = QAction(QIcon("./res/t05.png"), "画椭圆", self)
        self.act_DrawEllptic.setObjectName(u"act_DrawEllptic")
        self.act_DrawEllptic.triggered.connect(self.draw_Ellptic)
        self.toolBar_main.addAction(self.act_DrawEllptic)

        self.act_DrawFree = QAction(QIcon("./res/t06.png"), "涂手画", self)
        self.act_DrawFree.setObjectName(u"act_DrawFree")
        self.act_DrawFree.triggered.connect(self.Draw_Free)
        self.toolBar_main.addAction(self.act_DrawFree)

        self.act_DrawText = QAction(QIcon("./res/t07.png"), "画文本", self)
        self.act_DrawText.setObjectName(u"act_DrawText")
        self.act_DrawText.triggered.connect(self.draw_Text)
        self.toolBar_main.addAction(self.act_DrawText)
       
        self.act_DrawQuit = QAction(QIcon("./res/t08.png"), "退出绘画", self)
        self.act_DrawQuit.setObjectName(u"self.act_DrawExit")
        self.act_DrawQuit.triggered.connect(self.draw_Quit)
        self.toolBar_main.addAction(self.act_DrawQuit)
        

    #DEMO绘图标签被点击时       
    def labDemoClick(self):
        """if(self.demoClickNum>=self.threadMaxCount):
            self.demoClickNum=0
            for n in range(self.threadMaxCount):
                self.threadOpen[n]=False
                self.thread[n].stop()   #关闭全部线程,原线程发送的信号,对应槽函数未必已经处理完毕,可能还在接收信号
                time.sleep(1)
        for i in range(self.threadMaxCount):
            if(i <= (self.demoClickNum)):
                if(self.threadOpen[i]==False):  #对应线程还没打开,打开此序号线程
                    self.threadOpen[i]=True
                    print(f'单击标签画板:打开线程{i}')
                    self.thread[i].start()
        self.demoClickNum = self.demoClickNum + 1  #DEMO标签控件单击次数+1,好同线程打开数量对应"""
         #上面的行功能没法实现,故又回到只运行一个线程来看绘图演示,多个线程不能实现同时绘图?
        s
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mr_LuoWei2009

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值