PYQT5 series - reference from long live Frank

Source: address of Jianshu Long live Frank Address of Jianshu

PYQT5 (I) MAIN.PY standard start

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(2) solve the problem of sub thread flashback

In general, it is because your window is not well saved
 for instance:
I wrote a method in a window class whose class is test

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

If you write like this, generally speaking, the windows are all fleeting. You can try to change them to

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

Pyqt5 (III) set the window background color and borderless property, and set the top

#It's OK to add it during window initialization
#self.window yes 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)#No border, top
        self.window.setAttribute(Qt.Qt.WA_TranslucentBackground)#Transparent background color
        

Pyqt5 (IV) pychar configuration

See the source for details: https://www.jianshu.com/p/b5322f8cdcd1

Please refer to my previous blog: https://www.cnblogs.com/wohuiyijiu/p/12454130.html

(I didn't find it...)

Pyqt5 (VI) list widget list view add button and binding event

def GenerateBtn(self,pid):

    viewBtn = QtWidgets.QPushButton('See')

    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):

    # List control QTableWidget Generate list

    self.result_list.clear()#result_list Namely 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(7) QComboBox drop-down menu

The control name of the drop-down menu is QComboBox()
First introduce PyQt5.QtWidgets

Then we can introduce QcomboBox through QtWidgets

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

if __name__ == '__main__':

app = QApplication(sys.argv)

QDialog = QDialog()

S = dialog (qdialog) ා the dialog class is written by itself, initialization class

QDialog.show()

sys.exit(app.exec_())

--------------------------------------------------
Self.country#box = qtwidgets.qcombobox (dialog) 񖓿dialog is passed in from initialization and put here

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

self.country_box.setObjectName("country_box")

Self. Country? Box. AddItem ("")? Add a drop-down menu space first
--------------------------------------------------
Self.combo ﹐ box.setitemtext (0, ﹐ translate ("dialog", "test combo value")) ﹐ this function can only set content, not add new
--------------------------------------------------
self.country_box.setItemText(1, _translate("Dialog","test 2"))
--------------------------------------------------
If you want to add something, you can directly use addItem("fill in the text here")
--------------------------------------------------
Self. Country? Box. Currenttext()? Get the current selection after change
--------------------------------------------------
Attach common functions
 Overloading (dynamically modifying content)

insertItem()

setItemText()
If the current item of the combo box changes (status changes)

currentIndexChanged()

activated()

highlighted()

Remove content

removeItem()

clear()

Get current content

currentText()

Binding events

self.combobox.currentIndexChanged.connect(self.action)

Example of using pyqt5 (VIII) QCheckBox check box

First, create a layout, which is generated by the editor of 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")


Then initialize and add various values. Because there are many checkbox es, an array loop is used here to assign values
---------------------------------------------
       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 are used to save every checkbox, so don't forget to initialize variables first

If the click event is bound in the loop body and event confusion occurs, you can create a checkbox and encapsulate another layer of methods to solve the problem.
---------------------------------------------
    def create_checkboc(self,name,id):
        checkbox = QtWidgets.QCheckBox(name+'-'+id,self.gridLayoutWidget)
        checkbox.stateChanged.connect(lambda : self.show(name,id))
        return checkbox
---------------------------------------------
To turn off the checkbox, you can do the following
 close() closes the check box (not completely discarded)

deleteLater() delete check box)

Attach some common functions of checkbox

isChecked() to determine whether the function is selected

setChecked() sets whether to select. True is selected.

Pyqt5 (IX) pyinstaller failed to execute script main, missing queue package

After pyqt5 finishes writing the win32 Application, it is packaged into a single file by pyinstaller, and the error prompt box pops up: failed to execute script main

pyinstaller package parameter in pycharm:

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

Parameters: -w -F $FileName$

Working directory: $FileDir$

Analysis:

Through google, we found that pyinstaller has -- hidden import option

    --hidden-import MODULENAME, --hiddenimport MODULENAME

              Name an import not visible in the code of the

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

Solve:

Add -- hidden import = queue when packing

That is, the Parameters configuration is modified to:

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

eg:

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



Question 2:

ImportError: No module named 'queue'  

Failed to execute script final_exam2  

Then I import the queue module manually without any error.

Add -- hidden import = queue when packing



After trying to repackage and using the -- hidden import queue, the program works.

PYQT5(10) solves the problem of downward compatibility of win10 with xp

Updated February 17, 2020
 About developing compatible Windows XP system, and using pyqt5 software packed by pyinstaller.
If you have successfully compiled in win10 system and run on xp system, please let me teach you something, or you can talk to me about what you are studying. The online information is basically deceitful or copied.
At present, the specific operation steps of the best scheme are as follows:

Run an xp in the virtual machine (if there is an xp system, it is better)
I use virtualbox

2. Download Python 3.4 (xp system supports Python 3.4 at most)
Link is not up, direct Baidu search python has a lot.

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

Then click Install pywin32 installation file

Install Pyinstaller3.2.1
-------------------------------------------
Install command: pip install pyinstaller==3.2.1
-------------------------------------------
Download pyqt5 Python 3.4 private edition from the following connection
 Attach the link and check the number of digits. I use 32 bits.
A version of 5.5.1 is pasted here, which can be used for test.
https://sourceforge.net/projects/pyqt/files/PyQt5/PyQt-5.5.1/

If the installation fails, you can also try
 Try pip install python-qt5

pyqt5 is not displayed in pip list after installation with exe file
 It is said on the Internet that the exe package of python 32-bit and pyqt5 is not matched.
Combined with my attempt, use the installation package with corresponding number of digits of Pyqt5-5.5.1. After installation, do not worry about the list, or directly pack it

Packaging test
 Paste the simple tutorial of pyinstaller
-------------------------------------------
 pyinstaller -p C:\Python34\Lib\site-packages\PyQt5 -F -w main.py**
-p search for additional library file addresses
 -F pay attention to case, the generated file is a single exe execution file
 -w no console window
-------------------------------------------

Common mistakes
-------------------------------------------
from PyQt5 import QtCore, QtGui, QtWidgets
ImportError: cannot import name 'QtCore'
-------------------------------------------
It's said that there are various bugs in other versions of pyinstaller. Those copied blogs on the Internet are not very good-looking. They say there are bugs, but they don't say what they are. They just can't find the bugs in your pyqt library.
It is estimated that there is a problem in the previous step. You can try it in cmd
-------------------------------------------
pip uninstall pyinstaller
pip install pyinstaller==3.2.1
-------------------------------------------
So it's better to download pyinstaller3.2.1
-------------------------------------------
no model name 'queue'
-------------------------------------------
pyinstaller -F --hidden-import=queue final_exam2.py
-------------------------------------------
Solution to the failure of pip install openpyxl
-------------------------------------------
pip install openpyxl==2.5.14

Pyqt5 (XI) realize right-click menu

Form binding right click event
----------------------------------------------
        self.window.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.window.customContextMenuRequested.connect(self.rightMenuShow)
----------------------------------------------
  //Set right-click menu events and subsequent actions
----------------------------------------------
def rightMenuShow(self):
        try:
            self.contextMenu = QMenu()
            self.actionA = self.contextMenu.addAction(u'action a')
            self.contextMenu.popup(QCursor.pos())  # 2 Location of menu display
            self.actionA.triggered.connect(self.actionHandler)
            self.contextMenu.show()
        except Exception as e:
            print(e)
    def actionHandler(self):
        print('action')

PYQT5 (12) picture control, screenshot function

Mainly use Qlabel To achieve
----------------------------------------------
//Get width: Qlabel.width()

//Get height: 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")

----------------------------------------------
//Solution for too big picture:
----------------------------------------------
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 That's right.
----------------------------------------------
//Picture control (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 (XIII) cooperate with wechat screenshot and save the picture

# -*- 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 (XIV) is used in combination with PILLOW

It mainly solves the problem of calling pictures back and forth between two different libraries.
//Add 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))#Bottom canvas
        layer.paste(mark, (int((s[0]-mark.size[0])/2) , int((s[1]-mark.size[1])/2)))#Add watermark
        out = Image.composite(layer, im, layer)#Integrated
        data = out.tobytes("raw", "RGBA")#convert to byte format
        qim = QtGui.QImage(data, s[0], s[1], QtGui.QImage.Format_RGBA8888)#convert to qimage format
        qim.save('tttt.jpg')#Save locally
        return qim#Return at the same time
        # pix=QtGui.QPixmap.fromImage(qim)
    except Exception as e:
        print('error',e)
//Add transparency-------------------------------
#Yes bug
mark.putalpha(50)

https://www.cnblogs.com/RChen/archive/2007/03/31/pil_thumb.html

PYQT5(15) pushbutton binding event

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

Pyqt5 (XVI) picture container

def pic(self):
        # print(self.window.size)
        pix = QPixmap('icon/123.png')
        scale=1
        if pix.width()<self.width:#Contrast 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(17) open file directory

 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')
If you want to get an address or something, try these functions

 

 

 

getOpenFileNames gets the addresses of multiple files and returns an array

getOpenFileUrl returns PyQt5.QtCore.QUrl object. I don't know what to use

PYQT5 (eighteen) file drag and drop and get file information

#By rewriting QScrollArea File drag operation implemented by class
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 (XIX) how to hide the zoom in / out button in the title bar and fix the window size

self.window.setWindowFlags(QtCore.Qt.WindowTitleHint|QtCore.Qt.WindowCloseButtonHint)
---------------------
//Fixed window size
self.window.setFixedSize(100,200)

PYQT5(20) set small icon and title of window

from PyQt5 import QtCore, QtGui#Correlation Library
.
.
.#Some code in the middle is omitted here
        _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)#Hide close button

PYQT5(21) setting window position

self.window.move(500,500)

PYQT5(22) Qlabel border and background color

        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(23) FOCUS event

        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(24) text box responds to carriage return event

self.sendLineEdit.returnPressed.connect(self.SendData)
This is LineEdit pressing Enter to trigger the SendData function

Pyqt5 (XXV) QLabel adaptive

Let QLabel adapt to the size of text, directly using the following code:
LabelName->adjustSize();

Let QLabel automatically judge and display in new line:
Labelname - > setgeometry (qrect (328, 240, 329, 27 * 4)); / / quadruple line spacing
LabelName->setWordWrap(true);
LabelName->setAlignment(Qt::AlignTop);

PYQT5 (XXVI) open external link

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

PYQT5(27) output log to file

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

Pyqt5 (XXVIII) text box automatically changes size with text

You need to override the control. I use QTextedit,The others should be similar.

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


def textAreaChanged(self):
        #Judge text box length change
        # 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)

PYQT5(29) multi screen adaptation

        
self.move(int(QApplication.desktop().screenGeometry(0).width())-180, 90, )
#  screenGeometry(0)It's the main screen
#  1 If it's split screen 1, and so on

PYQT5(30) remove the window title bar, remove the taskbar display, and set the top of the window

this->setWindowFlags
(Qt::FramelessWindowHint | Qt::Tool | Qt::WindowStaysOnTopHint); 
// Remove title block,Remove the taskbar display and set the window at the top

//Translated into pyqt---------------------
window.setWindowFlags
(Qt.Qt.FramelessWindowHint|Qt.Qt.WindowStaysOnTopHint|Qt.Qt.Tool)

PYQT5(31) save window position for next use

from PyQt5.Qt import QMainWindow,QDialog
import json
window=QMainWindow()
def save_location(self):
        with open('window_location.txt','w') as f:
            data={'x':self.window.x(),'y':self.window.y()}
            f.write(json.dumps(data))
    def load_laction(self):
        with open('window_location.txt', 'r') as f:
            txt=f.read()
            print(txt)
            j=json.loads(txt)
            return j

PYQT5(32) QMainWindow rewriting CloseEvent

    def closeEvent(self, e):
        e.ignore()
        self.hide()
        self.save_location()

PYQT5(33) input dialog box

    QID = QInputDialog()
    QID.setGeometry(int((screen.width() - size.width()) / 2),
                    int((screen.height() - size.height())) / 2, 200, 200)
    text, ok = QID.getText(self.window, 'input', 'Title')

PYQT5(34) date control

    self.dateEdit.setDate(QDate.currentDate())
    self.dateEdit.setCalendarPopup(True)

Thirty five doesn't matter. The author's latest situation

 

PYQT5(36) get screen resolution size

 

        
        from PyQt5.QtWidgets import QApplication, QWidget
        self.desktop = QApplication.desktop()
        self.screenRect = self.desktop.screenGeometry()
        self.height = self.screenRect.height()
        self.width = self.screenRect.width()

PYQT5(37) table control adjust column width

Column width auto assignment
--------------------------------------
self.tableWidget.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
--------------------------------------
self.tableWidget.verticalHeader().setSectionResizeMode(QHeaderView.Stretch)
--------------------------------------
This is row wide
 In this mode, we can't adjust the column width manually.

Manual adjustment
--------------------------------------
self.tableWidget.horizontalHeader().setSectionResizeMode(QHeaderView.Interactive)

Fixed value
--------------------------------------
self.tableWidget.horizontalHeader().setSectionResizeMode(QHeaderView.Fixed)

The user cannot resize the section. This section can only be resized programmatically using resizeSection(). The default section size is defaultSectionSize.

Assign column width with content
--------------------------------------
self.tableWidget.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)

self.tableWidget.horizontalHeader().setSectionResizeMode(0, QHeaderView.ResizeToContents)

We combine it with automatic column width distribution to see the effect immediately.

Combination of the above two methods
--------------------------------------
self.tableWidget.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)

self.tableWidget.horizontalHeader().setSectionResizeMode(0, QHeaderView.Interactive)


Column width is automatically allocated, but we can manually adjust the width of the first column, while the overall column width of the table is still automatically allocated. We have no way to adjust the width of the second and third columns, which are automatically allocated.

Custom column width

--------------------------------------
1. self.tableWidget.setColumnWidth(0, 40)
2. self.tableWidget.setColumnWidth(1, 200)
3. self.tableWidget.setColumnWidth(2, 200)

PYQT(38) PDF reader

https://blog.csdn.net/weixin_43773093/article/details/88783757

Copy it casually to avoid losing it.
UI design
 First, use Qt Designer to design the graphic interface:

Create a new MainWindow main interface, then set a toolbar, add three actions to the toolbar, and set corresponding icons for each action.

You can also directly compile the PyReader.ui file I made, or import the Ui PyReader.py file.

Dependent requirement
Python3
PyQt5
PyMuPDF

Main tasks
 We use PyMuPDF to parse PDF to get PDF text information.

install
 We only need to enter: pip install PyMuPDF in cmd to install PyMuPDF.

Import

Import PyMuPDF
import fitz
 In this section, we just need to understand the following basic operations:

The fitz.open() function is used to read the contents of PDF files, and the doc.loadPage() function is used to obtain the information of a specific page. In particular, we use loadPage(0) to get cover information.

Read PDF
doc = fitz.open(fname)
#Get page n
page = doc.loadPage(n)
The main content of this section is to render the cover to the main interface, and complete the task of adding and deleting the cover.

Display form
 We use the QtWidgets.QTableWidget table control to display the cover page.

First, let's set the table style and function:

Among them, we set the cell aspect ratio to 4:3, as well as some other static properties, bind self.table with the right-click menu, and support to click cells to call the self.generateMenu function.
----------------------------------------------------
def _setTableStyle(self):
    #Open horizontal and vertical rollers
    self.table.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
    self.table.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
    #Set table with 5 rows and 8 columns
    self.table.setColumnCount(8)
    self.table.setRowCount(5)
    #Set standard width
    self.width = self.screen.width() // 8
    #Set cell width
    for i in range(8):
        self.table.setColumnWidth(i, self.width)
    #Set cell height
    #Set aspect ratio to 4: 3
    for i in range(5):
        self.table.setRowHeight(i, self.width * 4 // 3)
    #Hide title block
    self.table.verticalHeader().setVisible(False)
    self.table.horizontalHeader().setVisible(False)
    #Disable editing
    self.table.setEditTriggers(QAbstractItemView.NoEditTriggers)
    #Do not show gridlines
    self.table.setShowGrid(False)
    #Bind cells to right-click menu
    #Click the cell to call the self.generateMenu function
    self.table.setContextMenuPolicy(Qt.CustomContextMenu)
    self.table.customContextMenuRequested.connect(self.generateMenu)
----------------------------------------------------
Plus cover
 Let's first look at how to generate image class files that TableWidget can display.

We get the page object through doc.loadPage(0) and pass it to the render_pdf_page() function. Set the zoom ratio to 1:1. First, build the QImage object, and then convert the QImage object to a displayable object through the convertFromImage function.
----------------------------------------------------
#Show PDF cover
 #page_data is the page object
def render_pdf_page(page_data, for_cover=False):
    #Image scaling
    zoom_matrix = fitz.Matrix(4, 4)
    if for_cover:
        zoom_matrix = fitz.Matrix(1, 1)
    
    #Get Pixmap object corresponding to cover page
    #alpha set the background to white
    pagePixmap = page_data.getPixmap(
        matrix = zoom_matrix, 
        alpha=False) 
    #Get image format
    imageFormat = QtGui.QImage.Format_RGB888 
    #Generate QImage object
    pageQImage = QtGui.QImage(
        pagePixmap.samples,
        pagePixmap.width, 
        pagePixmap.height, 
        pagePixmap.stride,
        imageFormat)

    #Generate pixmap object
    pixmap = QtGui.QPixmap()
    pixmap.convertFromImage(pageQImage)
    return pixmap
----------------------------------------------------
Next, we want to add a cover image to the cell:

We use the + sign in the toolbar to add a PDF cover.
----------------------------------------------------
self.addbar.triggered.connect(self.open), when you click the + sign, the self.open function is called.
----------------------------------------------------
We use the getOpenFileName() function to get the file address. The following three parameters of self are the window name, the default path of the file and the supported file type. This function returns the address of the file.

The filter_book() function is used to ensure that the cover of the same book is not displayed repeatedly.
----------------------------------------------------
def getfile(self):
    #Open a single file
    fname, _ = QFileDialog.getOpenFileName(self, 'Open files', './', '(*.pdf)')
    return fname

def open(self):
    #Open file
    fname = self.getfile()
    if self.filter_book(fname):
        self.setIcon(fname)
                
#Get the address of a non duplicate book
def filter_book(self, fname):
    if not fname:
        return False
    if fname not in self.booklist:
        self.booklist.append(fname)
        return True
    return False      
----------------------------------------------------               
Then, we will render the PDF cover to the main interface:

label.setScaledContents(True) enables images to be filled with labels. self.table.setCellWidget(self.x, self.y, label) is used to set the rows and columns of labels. Finally, make sure to wrap every eight elements, and then clear the number of columns.
----------------------------------------------------
def setIcon(self, fname):
    Open PDF
    doc = fitz.open(fname)
    #Load cover page
    page = doc.loadPage(0)
    #Generate cover image
    cover = render_pdf_page(page, True)
    label = QLabel(self)
    #Set image auto fill label
    label.setScaledContents(True)
    #Set cover picture
    label.setPixmap(QPixmap(cover))
    #Set cell element to label
    self.table.setCellWidget(self.x, self.y, label)
    #Delete the label object to prevent the interface from being refreshed in the future
    #Because the label's life cycle is not over
    del label
    #Set the current number of rows and columns
    self.crow, self.ccol = self.x, self.y
    #Wrap every 8 elements
    if (not self.y % 7) and (self.y):
        self.x += 1
        self.y = 0
    else:
        self.y += 1
----------------------------------------------------
Right click menu
 As we mentioned above, how to bind cells to the right-click menu.

In this tutorial, there are only two items in the right-click menu: start reading (not implemented yet) and delete books.
----------------------------------------------------
def generateMenu(self, pos):
    row_num = col_num = -1
    #Gets the number of rows and columns in the selected cell
    for i in self.table.selectionModel().selection().indexes():
        row_num = i.row()
        col_num = i.column()
    #If there are elements in the selected cell, the right-click menu is supported
    if (row_num < self.crow) or (row_num == self.crow and col_num <= self.ccol):
        menu = QMenu()
        #Add options
        item1 = menu.addAction('Start reading ')
        item2 = menu.addAction('delete book ')
        #Get options
        action = menu.exec_(self.table.mapToGlobal(pos))
        if action == item1:
            pass
        #Click option 2 and call self.delete book to delete the book
        elif action == item2:
            self.delete_book(row_num, col_num)
----------------------------------------------------
Next, let's look at how to delete a Book:

First, maintain a self.booklist, which stores the address of non duplicate PDF file. First, get the index of the book in the booklist, and delete the element in the booklist. Then clear the contents of all cells after (including) the selected cells. Finally, the book address after the index in the booklist will be displayed on the table again. To put it simply, delete the selected cell and move the cell forward one bit.

----------------------------------------------------
#Delete book
def delete_book(self, row, col):
    #Get the location of the book in the list
    index = row * 8 + col
    self.x = row
    self.y = col
    if index >= 0:
        self.booklist.pop(index)

    i, j = row, col
    while 1:
        #Remove elements from row i and column j cells
        self.table.removeCellWidget(i, j)
        #Delete all the way to the last cell with elements
        if i == self.crow and j == self.ccol:
            break
        if (not j % 7) and j:
            i += 1
            j = 0
        else:
            j += 1

    #If the booklist is empty, set the current cell to - 1
    if not self.booklist:
        self.crow = -1
        self.ccol = -1
    #After deleting the book, display the cover pictures in order again
    for fname in self.booklist[index:]:
        self.setIcon(fname)
----------------------------------------------------

PyQt5 (39) QTableWidget adaptive window size, field size and layout

https://blog.csdn.net/yl_best/article/details/84070231

PYQT5(40) download and install QT-DESIGNER

https://www.jianshu.com/p/4df033879a3f

 

 

(1) I can't find it

Pyqt5 (2) implementation of drag and drop file function of myscrollwidget

class MyScrollWidget(QWidget):
    def __init__(self):
        super(QWidget, self).__init__()
        # self.resize(800, 600)
        self.move(0, 0)
        # self.setMouseTracking(False)
        self.last_time_move = 0
        self.last_time_move_x = 0
    def eventFilter(self,source, event):
        try:
            if event.type() == QEvent.MouseMove:
                print(event.pos().y(),event.pos().x())
                if self.last_time_move == 0:
                    self.last_time_move = event.pos().y()
                    self.last_time_move_x=event.pos().x()
                distance = (self.last_time_move - event.pos().y())/100
                distance_x = (self.last_time_move - event.pos().x())/100
                self.scroll(distance_x,0)
                self.last_time_move = event.pos().y()
                self.last_time_move_x=event.pos().x()
            elif event.type() == QEvent.MouseButtonRelease:
                self.last_time_move = 0
                self.last_time_move_x = 0
            return QWidget.eventFilter(self, source, event)
        except Exception as e:
            print(e)
#by the way Failed to fix it. y Scroll on the axis, but it's OK to use the scroll wheel. Put it first to realize the function and then come back to optimize it

PYQT5(3) multi thread QProgressBar stuck

def init_progress(parent):
    m = wake_progress()
    parent.progress = m
    m.run()
    if not m.window.isVisible():
        m.window.show()

#Activation method

class wake_progress(QThread):
#Thread class
    def __init__(self):
        super().__init__()
        self.window = QMainWindow()
        self.p=''
    def run(self):
        self.p =file_upload_statu_bar(self.window)

class file_upload_statu_bar(progress_bar):
#Primitive class
    def __init__(self,Form):
        print('progress bar')
        self.window=Form
        super().__init__()
        self.setupUi(Form)
        self.window.show()
    def change(self,name):
        self.label.setText(name)

The thread of progress bar is stuck

Finally, by reference to the narrow Article
One paragraph:
For programs that take a long time to execute, PyQt needs to wait for the program to finish executing before proceeding to the next step, which is shown in the interface as "stuck"; if QApplication.processEvents() is run continuously while executing the time-consuming program, then the function of executing the time-consuming program while refreshing the page can be realized, which will give people a relatively smooth feeling So, the usage of QApplication.processEvents() is to add QApplication.processEvents(), processEvents() to the time-consuming operation of the main function, which is simply to refresh the page.

So we add it in the loop

from PyQt5.QtWidgets import QApplication
def slotAdd(self): 
  for n in range(10): 
  str_n = 'File index {0}'.format(n)
  self.listFile.addItem(str_n) 
  QApplication.processEvents()#This is the key
  time.sleep(1) 

We can solve the problem successfully

The QSystemTrayIcon implementation window of PYQT5 (4) is minimized to the tray

from PyQt5 import QtGui

from PyQt5.QtWidgets import QSystemTrayIcon


class MyTray(QSystemTrayIcon):
    def __init__(self):
        super().__init__()
        try:
            self.setIcon(QtGui.QIcon('icon/car.png'))
            self.activated.connect(self.iconClicked)
        except Exception as e:
            print(e)
    def bind(self,window):
        self.parent_window=window
    def test(self):
        try:
            self.parent_window.show()
        except Exception as e:
            print(e)

    def iconClicked(self,reason):
    #Mouse click icon The transmitted signal will have a shaped value. 1 is to right-click, 2 is to double-click, 3 is to left-click, 4 is to middle click"
        print('click')
        if reason == 2 :#2 Double click.
            self.test()

Add a section to add the function of secondary menu, not tested yet

    def showMenu(self):
        "Design the menu of tray, here I realize a secondary menu"
        self.menu = QMenu()
        self.menu1 = QMenu()
        self.showAction1 = QAction("Display message 1", self, triggered=self.showM)
        self.showAction2 = QAction("Show message 2", self,triggered=self.showM)
        self.quitAction = QAction("Sign out", self, triggered=self.quit)

        self.menu1.addAction(self.showAction1)
        self.menu1.addAction(self.showAction2)
        self.menu.addMenu(self.menu1, )

        self.menu.addAction(self.showAction1)
        self.menu.addAction(self.showAction2)
        self.menu.addAction(self.quitAction)
        self.menu1.setTitle("Two level menu")
        self.setContextMenu(self.menu)

PYQT5(5) QTableWidgets with jump button

from PyQt5 import QtWidgets, QtCore
from PyQt5.QtWidgets import QTableWidget, QTableWidgetItem


class btn_table(QTableWidget):
    def __init__(self,x,y,window,res):
        self.centralwidget = QtWidgets.QWidget(window)
        self.centralwidget.setObjectName("centralwidget")
        self.centralwidget.resize(500,500)
        super().__init__(self.centralwidget)
        self.setGeometry(QtCore.QRect(20, 10, 471, 401))
        self.setObjectName("client_table")
        self.setColumnCount(x)
        self.setRowCount(y)

        self.buttonForRow(res)

        self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
        self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
    def buttonForRow(self,res):#Add content and a button on the last line
        # requir:[[value1,value2,value3,...],[value1,value2,value3,value4,...]]
        self.clear()
        for i in range(0,len(res)):
            try:
                item = self.horizontalHeaderItem(i)
                self.setHorizontalHeaderItem(i, item)
            except Exception as e:
                print(e)
                t = QtWidgets.QTableWidgetItem()
                self.setHorizontalHeaderItem(i, t)
                item = self.horizontalHeaderItem(i)

            for a in range(0,len(res[i])):
                self.setItem(i,a,QtWidgets.QTableWidgetItem(str(res[i][a])))
                print(res[i][a])
                # self.setItem(i, 1, QtWidgets.QTableWidgetItem(str(res[i][1])))
            btn=self.GenerateBtn(res[i][1])
            self.setCellWidget(i,len(res[0]),btn)
    def GenerateBtn(self,clientid):
        viewBtn = QtWidgets.QPushButton('See')
        viewBtn.setStyleSheet(''' text-align : center;
                              background-color : DarkSeaGreen;
                              height : 30px;
                              border-style: outset;
                              color:white;
                              font : 13px; ''')
        viewBtn.clicked.connect(lambda:self.jump(clientid) )
        return viewBtn
    def jump(self,clientid):
        print(clientid)

The approximate effect is as follows

 

PYQT(6)python3.4+pymssql+pyinstaller error compiling exe

I use pyinstaller -F -w to generate a separate exe file, which always appears
 Missing file for 'mssql'

Baidu came to the solution:

http://www.tuicool.com/articles/7RbU3i

Later, the following code was added to the. py file

import pymssql
import _mssql
_mssql.__version__

When packing with pyinstaller, pay attention to these packages
requests
pymssql

PYQT5 (7) implements the form that can be dragged

class MyWindow(QMainWindow):
    def __init__(self):
        super().__init__()

    def mousePressEvent(self, event):
        if event.button() == Qt.Qt.LeftButton:
            self.m_flag = True
            self.m_Position = event.globalPos() - self.pos()  # Get the position of the mouse relative to the window
            event.accept()
            self.setCursor(QCursor(Qt.Qt.OpenHandCursor))  # Change mouse icon

    def mouseMoveEvent(self, QMouseEvent):
        if Qt.Qt.LeftButton and self.m_flag:
            self.move(QMouseEvent.globalPos() - self.m_Position)  # change the window position
            QMouseEvent.accept()

    def mouseReleaseEvent(self, QMouseEvent):
        self.m_flag = False
        self.setCursor(QCursor(Qt.Qt.ArrowCursor))

PYQT5 (8) Rewrite Qlabel

from PyQt5 import Qt, QtCore
from PyQt5.QtWidgets import QLabel, QFrame
class dialog_label(QLabel):
def init(self,centralwidget):
super().init(centralwidget)
# self.dialog_label.setGeometry(QtCore.QRect(30, 30, 251, 91))
self.setFrameShape(QFrame.Box)
self.setStyleSheet('border-width: 1px;border-style: solid;border-color: rgb(255, 170, 0);')
print('dialog_label')

0 People praise points
PYQT5 Advanced log

PYQT5(9)QLabel realizes right-click to pop up menu and bind event

class MyLabel(QLabel):
    def __init__(self,centralwidget):
#centralwidget Form parameters
        super().__init__(centralwidget)
        self.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.customContextMenuRequested.connect(self.rightMenuShow)#Open right click strategy
    def rightMenuShow(self, point):
#Add right-click menu
            self.popMenu = QMenu()
            tj=QAction(u'Add to', self)
            sc=QAction(u'delete', self)
            xg = QAction(u'modify', self)
            self.popMenu.addAction(tj)
            self.popMenu.addAction(sc)
            self.popMenu.addAction(xg)
#Binding events
            tj.triggered.connect(self.test)
            sc.triggered.connect(self.test)
            xg.triggered.connect(self.test)
            self.showContextMenu(QtGui.QCursor.pos())
    def test(self):
        print('test')
    def showContextMenu(self, pos):
#Adjusting position
        '''''
        //Function called on right click
        '''
        # Before the menu is displayed, move it to the position where the mouse clicks

        self.popMenu.move( pos)
        self.popMenu.show()

PYQT5(10)Qlabel to capture keyboard key events

    def keyPressEvent(self, event):
        if (event.key() == Qt.Qt.Key_P):#P
            if QApplication.keyboardModifiers() == Qt.Qt.ShiftModifier:#shirft
                print("shift + p")
                self.talk_edit.show()
                self.talk_edit.setFocus()
            else:
                print("p")
                print('okokok')

https://blog.csdn.net/m0_37828248/article/details/79766580?utm_source=blogxgwz8

PYQT5(11) adaptive text height width Qtextedit

     self.width = 24
        self.height = 42
        self.edit.resize(self.width, self.height)
        self.document = self.edit.document()
        self.document.contentsChanged.connect(self.textAreaChanged)
        self.edit.setLineWrapMode(QTextEdit.NoWrap)
    def textAreaChanged(self):
        self.document.adjustSize()
 
        newWidth = self.document.size().width() + 10
        newHeight = self.document.size().height() + 20
        if newWidth != self.edit.width():
            self.edit.setFixedWidth(newWidth)
        if newHeight != self.edit.height():
            self.edit.setFixedHeight(newHeight)

PYQT5(12) reusable frame for automatically saving window position

import json
import os
from PyQt5.QtWidgets import QMainWindow
class AutoSaveWindow(QMainWindow):
    def __init__(self,name=''):
        #Pay attention to bring the name parameter
        super().__init__()
        self.name=name
        if os.path.exists('window_location_%s.txt'%self.name):
            self.load_location()
        #Check position and move every time you start
        

    def closeEvent(self, *args, **kwargs):
        self.save_location()

    def save_location(self):
        with open('window_location_%s.txt'%self.name, 'w') as f:
            data = {'x': self.x(), 'y': self.y()}
            f.write(json.dumps(data))

    def load_location(self):
        with open('window_location_%s.txt'%self.name, 'r') as f:
            txt = f.read()
            print(txt)
            j = json.loads(txt)
            self.move(j['x'],j['y'])

PYQT5(13) one thing to do to repeatedly bind button events

btn.disconnect()

PYQT5(14)pyqt5 QTreeWidget use collection (such as right-click menu)

A good tutorial: https://zhuanlan.zhihu.com/p/36033317

 
image

[introduction]

Example of QTreeWidget in PyQT5

from PyQt5.QtWidgets import *
import sys

class TreeWidgetDemo(QMainWindow):
def **init**(self, parent=None):
super(TreeWidgetDemo, self).**init**(parent)
self.setWindowTitle('TreeWidget Example')
self.tree = QTreeWidget()
# Set number of columns
self.tree.setColumnCount(2)
# Set header title
self.tree.setHeaderLabels(['Key', 'Value'])
# Set adaptive width
self.header().setSectionResizeMode(QHeaderView.ResizeToContents)
root = QTreeWidgetItem(self.tree)
root.setText(0, 'root')
root.setText(1, '0')

    child1 = QTreeWidgetItem(root)
    child1.setText(0, 'child1')
    child1.setText(1, '1')

    child2 = QTreeWidgetItem(root)
    child2.setText(0, 'child2')
    child2.setText(1, '2')

    child3 = QTreeWidgetItem(root)
    child3.setText(0, 'child3')
    child3.setText(1, '3')

    child4 = QTreeWidgetItem(child3)
    child4.setText(0, 'child4')
    child4.setText(1, '4')

    child5 = QTreeWidgetItem(child3)
    child5.setText(0, 'child5')
    child5.setText(1, '5')

    self.tree.addTopLevelItem(root)
    self.tree.clicked.connect(self.onTreeClicked)

    self.setCentralWidget(self.tree)

def onTreeClicked(self, qmodelindex):
    item = self.tree.currentItem()
    print("key=%s ,value=%s" % (item.text(0), item.text(1)))

Start it up

if **name** == '**main**':
app = QApplication(sys.argv)
tree = TreeWidgetDemo()
tree.show()
sys.exit(app.exec_())

Analyze to determine whether it is a parent

def onTreeClicked(self, qmodelindex):
    item = self.tree.currentItem()
     if item.parent()==None:
        print("key=%s ,value=%s" % (item.text(0), item.text(1)))
        #None Indicates the highest level

Signal triggering conditions:

Activated (qmodeldindex) this signal is issued when the user activates the item specified in the index
 This signal is issued when clicking the left mouse button of clicked (qmodeldindex)
Collapsed (qmodeldindex) signals when an item specified by the index is collapsed.
Currentitemchanged (qtreewidgettitem *, qtreewidgettitem *) signals when the current item changes
 Double clicked (qmodeldindex) sends this signal when double clicking the mouse button
 Entered (qmodeldindex) sends this signal when the mouse cursor enters the item specified in index
 Expanded (qmodeldeldindex) signals when an item specified by the index is expanded
 iconSizeChanged(QSize) sets the size of this icon when the view is visible, and sends this signal
 Item activated (qtreewidget item *, int) signals when a user activates an item by clicking, double clicking, or pressing a special key (for example, Enter)
Itemchanged (qtreewidgettitem *, int) signals when the content of a column in a specified item changes
 Item clicked (qtreewidget item *, int) signals when the user clicks inside the window.
Itemcollapsed (qtreewidgettitem *) signals when the specified item is collapsed
 Itemdoubleclick (qtreewidget item *, int) signals when the user double clicks in the window
 Itementered (qtreewidgettitem *, int) signals when the mouse cursor enters an item on a specified column
 When itemexpanded (qtreewidgettitem *) extends a specified item, signals
 Itempressed (qtreewidget item *, int) signals when the user presses the mouse button in the window.
itemSelectionChange() signals when the selection in the tree component changes
 Pressed (qmodeldindex) signals when the mouse button is pressed
 viewportEntered() signals when the mouse cursor enters the control

Get the content and

    def getLocation(self,item):

        if item.parent():
            temp = item.parent().text(0)
            parent=self.getLocation(item.parent())
            if parent :
                res=os.path.join(parent,temp)

                return res
            else:
                return temp
        else:
            return 0
#Give an example, text(0)Is the name of the folder, then all paths can be obtained after recursion

Right click menu

     def __init__(self):
        self.setContextMenuPolicy(Qt.CustomContextMenu)#Policy for opening the right-click menu
        self.customContextMenuRequested.connect(self.rightClickMenu)#Binding events

    def rightClickMenu(self,pos):
        try:
            self.contextMenu = QMenu()#create object
            self.actionA = self.contextMenu.addAction(u'action')#Add action
            self.actionA = self.contextMenu.addAction(u'action b')
            self.actionA.triggered.connect(self.actionHandler)
            self.contextMenu.exec_(self.mapToGlobal(pos))#Display menu with pointer position
            self.contextMenu.show()#display
        except Exception as e:
            print(e)
    def actionHandler(self):
        print(self.currentItem().text(0))

Delete all item s under the child node

                item=self.currentItem()
                for i in range(0,item.childCount()):
                    print(item.child(item.childCount()-1).text(0))
                    item.removeChild(item.child(item.childCount()-1))
                

 

Tags: Python Qt pip JSON

Posted on Mon, 23 Mar 2020 03:16:09 -0400 by dud3r