Pyqt5界面经验指南与踩坑记录

PYQt5编写界面遇到问题以及分析以及解决办法

科技制作比赛研究了一下界面制作问题,最终效果如下,在此进行记录
在这里插入图片描述
目录
1.美观问题
2.如何加透明框
3.图片素材添加办法
4.如何播放视频(有参考)
5.编译后的代码如何调用,主函数与启动加载时图片标志
6.主窗口操作与如何加弹窗(如操作错误警报)
7.如何绘制实时变化的波动曲线(有参考)
8.按钮外接自定义函数
9.时间与线程
10.硬件互联

  1. 注意QtDesigner的配置,能够将界面编写的更为美观。生成的代码需要增加初始化类与主函数编写才能使用。
    配置External Tools共三种,pyUIC用于编译.ui文件,pyrcc用于将导入显示在背景或graphviews上的图片文件编译为_rc文件
    配置办法在博客中有很多,应用如图所示
    在这里插入图片描述
    pyqt designer教程网上也有很多,推荐B站上的视频教程,核心要义为以下几点
    1)左侧为原件,可拖拽至主体上,常用pushbutton为按钮,label作为文本标签,graphicsview放置图片(label也可,具体见下文)
    2)layout可用于排版
    3)尽量对各元件名称有所更改标注,否则后期太多了可能找不到
    4)其中右侧的黄色列表中为原件样式,可通过更改变得美观,在此列举一个可在鼠标移动在按钮上方时更改按钮颜色的stylesheet写法
		QPushButton{
		border:1px solid #F3F3F5;
        border-radius:10px;
        border-color:rgba(0, 160, 240,155);
        color:rgba(220, 220, 220,155);
        font-size:12px;
        height:20px;
        padding-left:10px;
        padding-right:10px;
        text-align:left;
    }
    QPushButton:hover{
        color:black;
        border:1px solid #F3F3F5;
        border-radius:10px;
        background-color:rgba(255,255,255,180);
    }
  1. QtDesigner的主窗口类中self是个object类,同时引入了QMainWindow类,这种情况下如果想去掉界面边框并改变主窗口透明度需以下代码:
        MainWindow.setWindowOpacity(0.9)
        MainWindow.setWindowFlag(QtCore.Qt.FramelessWindowHint)
  1. 图片素材网站,推荐千库网(比较常见)但是需要付费,其它建议在知乎上搜索有哪些图片素材网站,链接不贴惹。
    图片的添加有主要两种办法,一是直接在designer上进行操作,点击右下角铅笔进行素材添加,通过样式表的更改加图片,代码如下,注意border图片是将图片变为整个框大小,而背景图片不会改变图片大小,不够大它会平铺
    border-image: url(:/liubian/pic/装饰01.png);
    background-color: rgba(0, 0, 0, 0);
    
    其编译后代码效果如下:
self.graphicsView_6 = QtWidgets.QGraphicsView(self.centralwidget)
        self.graphicsView_6.setGeometry(QtCore.QRect(790, 520, 181, 161))
        self.graphicsView_6.setStyleSheet("border-image: url(:/qiu/pic/装饰球.png);\n"
"background-color: rgba(0, 0, 0,0);")
        self.graphicsView_6.setObjectName("graphicsView_6")

注意本方法需要通过安装的第三个工具将图片格式也转换一下,并在代码结尾注意是否能够成功的import此图片
在这里插入图片描述
另,label的写法完全不同,其代码见视频播放

  1. 视频播放的办法有很多,最简单的就是调用Opencv逐帧读入,在此使用label作为图片放置对象,代码如下,注意颜色空间的转换问题:
    def Display(self):
        while self.videoflag==1:
            if self.cap.isOpened():
                print(10)
                success, frame = self.cap.read()
                self.main_ui.picture=frame
                # RGB转BGR
                print(11)
                if success:
                    frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
                    img = QImage(frame.data, frame.shape[1], frame.shape[0], QImage.Format_RGB888)
                    self.main_ui.label_15.setPixmap(QPixmap.fromImage(img))
                    self.main_ui.label_15.setScaledContents(True)
                    #time.sleep(0.1)
                    cv2.waitKey(10)
                else:
                    print("read failed, no frame data")
                    success, frame = self.playCapture.read()
                    #if not success and self.video_type is parentWindow.VIDEO_TYPE_OFFLINE:
                     #   print("play finished")  # 判断本地文件播放完毕
                        #                            self.reset()
                            #self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaStop))
                      #  return
            else:
                print("open file or capturing device error, init again")
                self.reset()
            print(16)

如果需要对实时视频流进行测试,本地直接调用电脑摄像机,网络流可以连凤凰卫视等直播,地址为"rtmp://live.hkstv.hk.lxdns.com/live/hks1";"rtmp://58.200.131.2:1935/livetv/hunantv"等,都不行就查一下哇

  1. 编译后的代码调用这里用的父子类二次操作,父类如下:
class parentWindow(QMainWindow,QWidget):

    video_url = ""

    def __init__(self,video_url="", video_type=VIDEO_TYPE_OFFLINE, auto_play=False):
        QMainWindow.__init__(self)
        self.main_ui = Ui_MainWindow()
        self.main_ui.setupUi(self)

那个Ui_MainWindow就是编译生成的那个类,另写主函数如下:

if __name__=='__main__':

    app=QApplication(sys.argv)
    #启动界面
    splash=QSplashScreen(QPixmap("pic/bk01.jpg"))
    splash.showMessage("加载... 0%", Qt.AlignHCenter | Qt.AlignBottom, Qt.black)
    splash.show()
    qApp.processEvents()
  

    window = parentWindow("http://一个网址")
    child=childWindow()
    video=videoWindow()
    #window.main_ui.pushButton_11.clicked.connect(video.show())

    # 显示
    window.show()
    splash.finish(window)
    sys.exit(app.exec_())

其中splash是启动界面,在界面加载难产的时候让他不那么尴尬,效果如下:

在这里插入图片描述
6. 上面的主函数中能看到初始化中存在一个孩子类,其为警告弹窗,面向在界面中操作不当时出现,需要先在designer中另绘制一个窗口,效果与编译后代码如下
在这里插入图片描述

class Ui_Dialog(object):
    def setupUi(self, Dialog):
        Dialog.setObjectName("Dialog")
        Dialog.resize(408, 336)
        Dialog.setWindowOpacity(1.0)
        Dialog.setStyleSheet("background-color:rgba(0,0,0,0)")
        self.graphicsView = QtWidgets.QGraphicsView(Dialog)
        self.graphicsView.setGeometry(QtCore.QRect(0, 20, 401, 331))
        self.graphicsView.setStyleSheet("border-image: url(:/warn/pic/warn01.png);\n"
"background-color:rgba(0,0,0,0)")
        self.graphicsView.setObjectName("graphicsView")
        self.graphicsView_2 = QtWidgets.QGraphicsView(Dialog)
        self.graphicsView_2.setGeometry(QtCore.QRect(330, 10, 51, 41))
        self.graphicsView_2.setStyleSheet("border-image: url(:/warn/pic/close.png);\n"
"background-color:rgba(0,0,0,0)")
        self.graphicsView_2.setObjectName("graphicsView_2")
        self.pushButton = QtWidgets.QPushButton(Dialog)
        self.pushButton.setGeometry(QtCore.QRect(340, 20, 31, 21))
        self.pushButton.setStyleSheet("background-color:rgba(0,0,0,0)")
        self.pushButton.setText("")
        self.pushButton.setObjectName("pushButton")

        self.retranslateUi(Dialog)
        self.pushButton.clicked.connect(Dialog.close)
        QtCore.QMetaObject.connectSlotsByName(Dialog)
        Dialog.setWindowOpacity(0.8)
        Dialog.setWindowFlag(QtCore.Qt.FramelessWindowHint)

    def retranslateUi(self, Dialog):
        _translate = QtCore.QCoreApplication.translate
        Dialog.setWindowTitle(_translate("Dialog", "Dialog"))

import warn_rc

尤其注意,类似于主界面的代码,我们也需要另写一个类来将其调用,代码如下:

class childWindow(QDialog):
    def __init__(self):
        QDialog.__init__(self)
        self.child=Ui_Dialog()
        self.child.setupUi(self)

  1. 为了活泼性加了可变的曲线来描述参数,代码如下,函数定义加在父类里,显示在初始化init中,通过线程与延时器重复调用
    def plotData(self):

        if self.dataflag==1:
            self.tmp_x,self.tmp_y,self.tmp_z=self.cmdd
            self.main_ui.lineEdit_3.setText(str(self.tmp_x))
            self.main_ui.lineEdit_2.setText(str(self.tmp_y))
            self.main_ui.lineEdit.setText(str(self.tmp_z))
        if len(self.data_x)<self.N:
            self.data_x.append(self.tmp_x)
        else:
            self.data_x[:-1]=self.data_x[1:]
            self.data_x[-1]=self.tmp_x
        self.curve_x.setData(self.data_x)

        if len(self.data_y)<self.N:
            self.data_y.append(self.tmp_y)
        else:
            self.data_y[:-1]=self.data_y[1:]
            self.data_y[-1]=self.tmp_y
        self.curve_y.setData(self.data_y)

        if len(self.data_z)<self.N:
            self.data_z.append(self.tmp_z)
        else:
            self.data_z[:-1]=self.data_z[1:]
            self.data_z[-1]=self.tmp_z
        self.curve_z.setData(self.data_z)

        self.idx+=1

  1. 按钮外接函数
    在此处有两种添加办法,,一种是添加到通过PYQT编写的界面类UI_MainWindow里,代码如下:
 self.pushButton_9.clicked.connect(self.doit)
        self.pushButton_4.clicked.connect(self.starguide_1)

之后同样在此类里定义函数

    def doit(self):  # OK
            if self.flagbutton[1] == 1:
                    #child=childWindow()
                    #self.flagbutton=[0,1,0,0]
                    ......

另一种是加在我们写出的大类parentwindow里,代码如下:

self.main_ui.pushButton_15.clicked.connect(self.dataconnect_2)
        self.main_ui.pushButton_11.clicked.connect(self.bofang)

此时函数定义也要写在parentwindow里

  1. 时间与线程
    计时器代码:
self.thread=WorkThread()
self.xyztimer=QTimer()#计时器
self.xyztimer.start(5)

因为此计时器申请两个及以上时出现了未知错误,本任务中借用了另一篇博客中的视频播放中的计时器。

线程代码使用thread库,如下:

    def bofang(self):
        self.cap=cv2.VideoCapture(self.video_url)
        self.videoflag=self.videoflag*(-1)
        thu=threading.Thread(target=self.Display)
        thu.start()

Display是我们要接出线程运行的函数

  1. 硬件互联
    socket库操作,具体因硬件而异
    (其实是因为这部分不是我写的朕不会)

over.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值