VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > Python基础教程 >
  • PYQT5 系列(一)——参考自《弗兰克万岁》


复制代码
1 import sys
2 from PyQt5.QtWidgets import QApplication
3 
4 from lib.main_window import main_window
5 
6 if __name__=='__main__':
7     app = QApplication(sys.argv)
8     m=main_window()
9     sys.exit(app.exec_())
复制代码

PYQT5(二)解决子线程闪退的问题

复制代码
一般情况下是因为你的window没有保存好导致的
举个例子:
我在一个class 为 test的窗口类中写了一个方法

def createNewWindow(self):
    newWindow=QDialog()
    testWindow=MyPersonalPrograme(newWindow)

如果你这么写的话一般来讲,窗口都是一闪而逝的,可以试试改为

def createNewWindow(self):
    self.newWindow=QDialog()
    testWindow=MyPersonalPrograme(self.newWindow)
复制代码

PYQT5(三)设置窗口背景颜色和无边框属性,和置顶

复制代码
#在窗口初始化的时候加入就可以了
#self.window是QMainWindow()
  
from PyQt5.QtWidgets import  QApplication,QMainWindow
from PyQt5 import QtGui, QtCore

        palette1 = QtGui.QPalette()
        palette1.setColor(palette1.Background,QtGui.QColor(255,255,255))
        self.window.setPalette(palette1)

     window.setWindowFlags(Qt.Qt.FramelessWindowHint|Qt.Qt.WindowStaysOnTopHint)#无边框,置顶
        self.window.setAttribute(Qt.Qt.WA_TranslucentBackground)#透明背景色
        
复制代码

PYQT5(四)PYCHARM配置

此篇可以详见源:https://www.jianshu.com/p/b5322f8cdcd1

亦可参考我之前的博客:https://www.cnblogs.com/wohuiyijiu/p/12454130.html

(五没找着...)

PYQT5(六)ListWidget列表视图添加按钮以及绑定事件

复制代码
def GenerateBtn(self,pid):

    viewBtn = QtWidgets.QPushButton('查看')

    viewBtn.setStyleSheet(''' text-align : center;

    background-color : DarkSeaGreen;

    height : 30px;

    border-style: outset;

    color:white;

     font : 13px; ''')

    viewBtn.clicked.connect(lambda:self.jump(pid))

    return viewBtn
复制代码
复制代码
def jump(self,pid):

    if id:

        self.son.pid=pid

        if not self.window.isVisible():

        self.son.window.hide()

        self.window.show()

    else:

        self.window.hide()

        self.son.window.show()

        self.sql.log(4,self.guige, pid)

        self.son.accept()

def buttonForRow(self,res):

    # 列表控件QTableWidget生成列表

    self.result_list.clear()#result_list就是Qtablewidget

    for i in range(0,len(res)):

        item =self.result_list.horizontalHeaderItem(i)

        self.result_list.setHorizontalHeaderItem(i, item)

        self.result_list.setItem(i,0,QtWidgets.QTableWidgetItem(str(res[i][0])))

        self.result_list.setItem(i,1, QtWidgets.QTableWidgetItem(str(res[i][1])))

        btn=self.GenerateBtn(res[i][1])

        self.result_list.setCellWidget(i,2,btn)
复制代码

PYQT5(七)QComboBox下拉菜单

复制代码
下拉菜单的控件名称是QComboBox()
先引入PyQt5.QtWidgets

然后就可以通过QtWidgets 引入QcomboBox了

--------------------------------------------------
from PyQt5.QtWidgets import QApplication,QMainWindow,QDialog

if __name__ == '__main__':

app = QApplication(sys.argv)

QDialog = QDialog()

s=Dialog(QDialog)#Dialog类是自己写的,初始化类

QDialog.show()

sys.exit(app.exec_())

--------------------------------------------------
self.country_box = QtWidgets.QComboBox(Dialog)#Dialog从初始化的时候传参进来放在这里使用

self.country_box.setGeometry(QtCore.QRect(850,231,291,31))

self.country_box.setObjectName("country_box")

self.country_box.addItem("")#先添加一个下拉菜单空位
--------------------------------------------------
self.combo_box.setItemText(0, _translate("Dialog","test combo value"))#该函数只能设置内容,不能新增
--------------------------------------------------
self.country_box.setItemText(1, _translate("Dialog","test 2"))
--------------------------------------------------
如果要新增的话可以直接使用addItem("这里填入文本内容")
--------------------------------------------------
self.country_box.currentText()#发生变动后获取当前选择的内容
--------------------------------------------------
附上常用函数
重载(动态修改内容)

insertItem()

setItemText()
如果组合框的当前项目发生更改(状态改变)

currentIndexChanged()

activated()

highlighted()

移除内容

removeItem()

clear()

获取当前内容

currentText()

绑定事件

self.combobox.currentIndexChanged.connect(self.action)
复制代码

PYQT5(八)QCheckBox复选框使用范例

复制代码
首先创建一个布局,这一段是pyqt5自带的编辑器生成的

---------------------------------------------
self.gridLayoutWidget = QtWidgets.QWidget(QDialog)
        self.gridLayoutWidget.setGeometry(QtCore.QRect(830,140,321,141))
        self.gridLayoutWidget.setObjectName("gridLayoutWidget")
        self.model_gridLayout = QtWidgets.QGridLayout(self.gridLayoutWidget)
        self.model_gridLayout.setContentsMargins(0,0,0,0)
        self.model_gridLayout.setObjectName("model_gridLayout")


然后再初始化,添加各种数值,因为checkbox比较多,这里用的一个数组循环赋值
---------------------------------------------
       for i in data:
            if i[0]:
                if index<4:
                    checkbox = QtWidgets.QCheckBox(i[0]+'-'+i[1],self.gridLayoutWidget)
                    self.model_girdlayout.addWiget(checkbox,x,index,1,1)
                    index+=1
                else:
                    index=0
                    x+=1
                self.model_widgets.append(checkbox)

model_widgets是用来保存每一个checkbox的,所以不要忘了先初始化变量

如果出现在循环体中绑定点击事件,发生事件混乱现象,可以将创建checkbox再封装一层方法,便可以解决问题。
---------------------------------------------
    def create_checkboc(self,name,id):
        checkbox = QtWidgets.QCheckBox(name+'-'+id,self.gridLayoutWidget)
        checkbox.stateChanged.connect(lambda : self.show(name,id))
        return checkbox
---------------------------------------------
关闭checkbox可以按照如下方法
close() 关闭复选框(并未彻底丢弃)

deleteLater()删除复选框)

附上checkbox的一些常用函数

isChecked()判断函数是否被选中

setChecked()设置是否选择,True为选中。
复制代码

PYQT5(九)pyinstaller打包运行报错failed to execute script main,缺少queue包

复制代码
pyqt5写完win32 应用程序后,经过pyinstaller打包成单个文件,运行弹出错误提示框:failed to execute script main

pycharm中pyinstaller打包参数:

Program:C:\Python\Python35\Scripts\pyinstaller.exe

Parameters: -w -F $FileName$

Working directory: $FileDir$

分析:

经google,发现pyinstaller 有--hidden-import 选项

    --hidden-import MODULENAME, --hiddenimport MODULENAME

              Name an import not visible in the code of the

                script(s). This option can be used multiple times.

解决:

打包时加上 --hidden-import=queue

即Parameters配置修改为:

Parameters:--hidden-import=queue -w -F $FileName$

eg:

pyinstaller --hidden-import=queue -w -F -i test.ico main.py



问题2:

ImportError: No module named ‘queue‘  

Failed to execute script final_exam2  

然后自己手工导入queue模块,并没有报错。

打包时加上 --hidden-import=queue



在尝试重新打包并且使用--hidden-import queue 后,程序能够正常运行。
复制代码

PYQT5(十)解决win10向下兼容xp的问题

复制代码
更新于2020年2月17日
关于开发兼容windowsxp系统,并使用pyinstaller 打包的pyqt5软件。
如果有成功在win10系统编译,同时在xp系统上跑的大神,麻烦艾特我教我一下,或者有正在研究的可以找我讨论一下,网上的资料基本上是坑人的,或者抄来抄去的。
目前来看,最好的方案具体操作步骤如下:

在虚拟机中跑一个xp(如果有xp系统的机子当然更好啦)
我用是virtualbox

2.下载python3.4版本(xp系统最高支持到python3.4)
链接就不上了,直接百度搜索python就有一大堆。

安装pywin32
https://sourceforge.net/projects/pywin32/files/pywin32/Build%20220/pywin32-220.win32-py3.4.exe/download

然后点击安装pywin32的安装文件

安装Pyinstaller3.2.1
-------------------------------------------
安装命令:pip install pyinstaller==3.2.1
-------------------------------------------
到下面的连接中下载pyqt5 python3.4 专用版
附上链接,注意检查位数,我用的是32位的。
这里贴上一个5.5.1的版本,亲测可用。
https://sourceforge.net/projects/pyqt/files/PyQt5/PyQt-5.5.1/

by the way 如果安装失败的话,也可以试试
试试 pip install python-qt5

使用exe文件安装后,pip list 中不显示pyqt5
网上说是python 32位和pyqt5的exe包对不上。
结合本人尝试,使用Pyqt5-5.5.1的版本的对应位数的安装包,安装后别管list,直接打包也可以

打包测试
贴上pyinstaller的简单使用教程
-------------------------------------------
 pyinstaller -p C:\Python34\Lib\site-packages\PyQt5 -F -w main.py**
-p  搜索额外的库文件地址
-F 注意大小写,生成的文件是单个exe执行文件
-w 无console窗口
-------------------------------------------

常见错误
-------------------------------------------
from PyQt5 import QtCore, QtGui, QtWidgets
ImportError: cannot import name 'QtCore'
-------------------------------------------
据说别的版本的pyinstaller各种bug,网络上的那些抄来抄去的博客没什么好看的,说有bug但是不说是什么bug,无非就是找不到你的pyqt库的bug。
估计是上一步有问题,可以在cmd里试试
-------------------------------------------
pip uninstall pyinstaller
pip install pyinstaller==3.2.1
-------------------------------------------
所以最好还是下载pyinstaller3.2.1
-------------------------------------------
no model name 'queue'
-------------------------------------------
pyinstaller -F --hidden-import=queue final_exam2.py
-------------------------------------------
pip install openpyxl 失败的解决方法
-------------------------------------------
pip install openpyxl==2.5.14
复制代码

PYQT5(十一)实现右键菜单

复制代码
窗体绑定右键事件
----------------------------------------------
        self.window.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.window.customContextMenuRequested.connect(self.rightMenuShow)
----------------------------------------------
  设置右键菜单事件,和后续的动作
----------------------------------------------
def rightMenuShow(self):
        try:
            self.contextMenu = QMenu()
            self.actionA = self.contextMenu.addAction(u'动作a')
            self.contextMenu.popup(QCursor.pos())  # 2菜单显示的位置
            self.actionA.triggered.connect(self.actionHandler)
            self.contextMenu.show()
        except Exception as e:
            print(e)
    def actionHandler(self):
        print('action')
复制代码

PYQT5 (十二)图片控件,截图功能

复制代码
主要是使用Qlabel来实现
----------------------------------------------
获取宽度:Qlabel.width()

获取高度:Qlabel.height()
----------------------------------------------
def cut(self):

    screen = QApplication.primaryScreen()

# pix = screen.grabWindow(self.window.winId())

    pix = screen.grabWindow(self.img_label.winId())

pix.save("test.jpg")

----------------------------------------------
图片太大的解决方法:
----------------------------------------------
self.scrollArea = QtWidgets.QScrollArea(self.centralwidget)

self.scrollArea.setGeometry(QtCore.QRect(20,60,841,591))

self.scrollArea.setWidgetResizable(True)

self.scrollArea.setObjectName("scrollArea")

self.MyScroll = QtWidgets.QWidget()

self.MyScroll.setGeometry(QtCore.QRect(0,0,839,589))

self.MyScroll.setObjectName("MyScroll")

self.MyScroll.setMinimumSize(7000,7000)

#scrollArea就对了
----------------------------------------------
图片控件(QImage)
----------------------------------------------
def pic(self):

# print(self.window.size)

    pix = QPixmap('icon/123.png')

scale=1

    print(pix.width())

if pix.width()

self.img_label.setGeometry(10,10,pix.width()*scale,pix.height()*scale)

else:

self.img_label.setScaledContents(True)

# self.img_label.setGeometry(10, 10, self.width*scale,  self.height*scale)

    self.img_label.setStyleSheet("border: 2px solid red")

self.img_label.setPixmap(pix)

# self.img_label.mouseDoubleClickEvent(self.zoom())
复制代码

PYQT5(十三)配合微信截图并保存图片

复制代码
# -*- coding:utf-8 -*-

import ctypes

import os

from PyQt5.QtWidgets import QApplication

def capture():

    clipboard=QApplication.clipboard()

    try:

        dll = ctypes.cdll.LoadLibrary('PrScrn.dll')

        dataImage = clipboard.pixmap()

        dataImage.save('Grab.png')

    except Exception:

        print("Dll load error!")

        return

    else:

        try:

            dll.PrScrn(0)

            dataImage = clipboard.pixmap()

            dataImage.save('Grab.png')

        except Exception:

            print("Sth wrong in capture!")

            return
复制代码

PYQT5 (十四)配合PILLOW使用

复制代码
主要解决两种不同的库之间图片来回调用问题。
添加logo-------------------------------
    im = Image.open(path)
    im = im.convert("RGBA")
    im=im.resize((600,500),Image.ANTIALIAS)
    try:
        mark = Image.open("image/logo.png")
        s=im.size
        layer = Image.new('RGBA', s, (0, 0, 0, 0))#底层画布
        layer.paste(mark, (int((s[0]-mark.size[0])/2) , int((s[1]-mark.size[1])/2)))#添加水印
        out = Image.composite(layer, im, layer)#整合在一起
        data = out.tobytes("raw", "RGBA")#转换成byte格式
        qim = QtGui.QImage(data, s[0], s[1], QtGui.QImage.Format_RGBA8888)#转换成qimage格式
        qim.save('tttt.jpg')#保存在本地
        return qim#同时返回
        # pix=QtGui.QPixmap.fromImage(qim)
    except Exception as e:
        print('error',e)
添加透明度-------------------------------
#有bug
mark.putalpha(50)

https://www.cnblogs.com/RChen/archive/2007/03/31/pil_thumb.html
复制代码

PYQT5(十五) pushbutton绑定事件

self.setting_btn.clicked.connect(lambda :init_setting(self))

PYQT5(十六)图片容器

复制代码
def pic(self):
        # print(self.window.size)
        pix = QPixmap('icon/123.png')
        scale=1
        if pix.width()<self.width:#对比宽度
self.img_label.setGeometry(10,10,pix.width()*scale,pix.height()*scale)
        else:
            self.img_label.setScaledContents(True)
            # self.img_label.setGeometry(10, 10, self.width*scale,  self.height*scale)
        self.img_label.setStyleSheet("border: 2px solid red")

        self.img_label.setPixmap(pix)

        # self.img_label.mouseDoubleClickEvent(self.zoom())
复制代码

PYQT5(十七)打开文件目录

复制代码
 def setPicPath(self):
        path=self.load_last_path()
        file=QDialog()
        fname,ftype=QFileDialog.getOpenFileName(file,'open',path)
        print(fname)

        if fname:
            res = self.save_last_path(fname)
            if res == 0:
                print('false occured in path saving processing')
复制代码
如果要获取地址或者别的可以试试下面这些函数

 

 

 

getOpenFileNames 获取多个文件的地址,返回的是一个数组

getOpenFileUrl 返回PyQt5.QtCore.QUrl 对象,不知道什么用途

PYQT5 (十八)文件拖放(drag and drop)并获取文件信息

复制代码
#通过重写QScrollArea 类实现的文件拖拽操作
class MyScrollWidget(QtWidgets.QScrollArea):
    def __init__(self,parent=None):
        super().__init__(parent)
        self.setAcceptDrops(True)
    def dragEnterEvent(self, event):
        if event.mimeData().hasUrls:
            event.accept()
        else:
            event.ignore()

    def dragMoveEvent(self, event):
        if event.mimeData().hasUrls:
            try:
                event.setDropAction(Qt.Qt.CopyAction)
            except Exception as e:
                print(e)
            event.accept()
        else:
            event.ignore()

    def dropEvent(self, event):
        try:
            if event.mimeData().hasUrls:
                event.setDropAction(Qt.Qt.CopyAction)
                event.accept()
                links = []
                for url in event.mimeData().urls():
                    links.append(str(url.toLocalFile()))
                print(links)
            else:
                event.ignore()
        except Exception as e:
            print(e)```
复制代码

PYQT5(十九)标题栏如何隐藏放大缩小按钮,固定窗口大小

self.window.setWindowFlags(QtCore.Qt.WindowTitleHint|QtCore.Qt.WindowCloseButtonHint)
---------------------
固定窗口大小
self.window.setFixedSize(100,200)

PYQT5(二十) 设置窗口小图标和标题

复制代码
from PyQt5 import QtCore, QtGui#相关库
.
.
.#这里省略中间的一些代码
        _translate = QtCore.QCoreApplication.translate
        self.window.setWindowIco(QIcon('./test.jgp'))
        self.window.setWindowTitle(_translate("window", "CLIENT INFO"))
        self.window.setWindowFlags(QtCore.Qt.WindowTitleHint|QtCore.Qt.WindowCloseButtonHint)#隐藏关闭按钮
复制代码

PYQT5(二十一)设置窗口位置

self.window.move(500,500)

PYQT5(二十二)Qlabel边框和背景颜色

        self.setFrameShape(QFrame.Box)
        self.setStyleSheet('border-width: 1px;border-style: solid;
border-color: rgb(255, 170, 0);background-color: rgb(100,149,237);')
        print('dialog_label')

PYQT5(二十三)FOCUS焦点事件

复制代码
        self.setFocusPolicy(QtCore.Qt.ClickFocus)

    def focusInEvent(self, QFocusEvent):
        print('focus in')
        pix = QPixmap('icon/action2.png')
        self.setPixmap(pix)
    def focusOutEvent(self, QFocusEvent):
        pix = QPixmap('icon/123.png')
        self.setPixmap(pix)

----------------------
https://www.jianshu.com/p/ef674f39499d
复制代码

PYQT5(二十四)文本框回应回车事件

self.sendLineEdit.returnPressed.connect(self.SendData)
这个是LineEdit按下Enter按键触发SendData函数

PYQT5(二十五) QLabel自适应

复制代码
让QLabel自适应text的大小,直接用下面的代码:
LabelName->adjustSize();

让QLabel能够自动判断并换行显示:
LabelName->setGeometry(QRect(328, 240, 329, 27*4)); //四倍行距
LabelName->setWordWrap(true);
LabelName->setAlignment(Qt::AlignTop);
复制代码

PYQT5(二十六)打开外部链接

def outer(self):
    QtGui.QDesktopServices.openUrl(QtCore.QUrl('http://www.hao123.com'))

PYQT5(二十七)输出log到文件中

with open('log','a+') as l:
        print("date.txt exits%s \n"%now, file=l)

PYQT5(二十八)文本框自动跟随文本多少改变大小

复制代码
需要重写控件,我用的是QTextedit,其他的应该也是差不多的。

self.document().contentsChanged.connect(self.textAreaChanged)


def textAreaChanged(self):
        #判断文本框长度变化
        # self.document().adjustSize()
        newHeight = self.document().size().height() + 30
        print(newHeight)

        if newHeight>300:
            self.setGeometry(QtCore.QRect(self.X, self.Y, 141, 300))
        else:
            self.setGeometry(QtCore.QRect(self.X, self.Y, 141, newHeight))
        self.setLineWrapMode(1)