PyQt5 learning notes - QWidget learning

Posted by vidhu on Sat, 29 Jan 2022 14:44:59 +0100

QWidget details

1, Description

  1. Base class for all visual controls

  2. Is the simplest blank control

  3. Control is the smallest element of the user interface
    Accept various events, mouse, keyboard
    Draw on the desktop and show it to users

  4. Each control is rectangular, and they are sorted in Z-axis order

  5. Control is cut by its parent control and the previous control

  6. A control without a parent control is called a window

2, Inherit

Obviously, it inherits from QObject and has all its functions

Use the following code to view

print(QWidget.__bases__)

3, Functional function

3.1 creation of control

import sys
from PyQt5.Qt import *



if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = QWidget()

    # print(QWidget.__bases__)   #Print its parent class, or install ctrl key and click to view it
    # print(QWidget.mro())   # Look up at all chain like


    window.resize(500,500)

    red = QWidget(window)  # Create a blank control again as a child control
    red.resize(100,100)

    red.setStyleSheet("background-color:red")  #Set the control to red
    red.move(450,0)

    window.show()

    sys.exit(app.exec_())


3.2 size and position

(1) Theoretical support: coordinate system of control

(2)API

API for getting elements:

Note: xy here refers to the relative position of the top-level control equivalent to the desktop, while weight and height are the content size excluding the window frame.

About setting related API s:

Note: resize changes the size of the user area. The setGeometry() function must wait until the display is successful.

Test code 1

import sys
from PyQt5.Qt import *



if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = QWidget()

    # print(QWidget.__bases__)   #Print its parent class, or install ctrl key and click to view it
    # print(QWidget.mro())   # Look up at all chain like

    window.show()

    # The user area is set (excluding the frame part). The first two coordinates are the coordinates of the user area, and the last two coordinates are the dimensions of the user area
    # However, this line of code must be set after the show() function, and then wrap it when the display is successful
    window.setGeometry(0,0,150,150)

    # The application executes and enters the message loop
    sys.exit(app.exec_())


Test code 2

import sys
from PyQt5.Qt import *



if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = QWidget()

    # print(QWidget.__bases__)   #Print its parent class, or install ctrl key and click to view it
    # print(QWidget.mro())   # Look up at all chain like

    window.move(200,100)
    window.resize(500,500)

    label = QLabel(window)
    label.setText("Social Shun")
    label.move(100,100)
    label.setStyleSheet("background-color:cyan;")


    def Cao1():
        new_content = label.text() + "Social Shun"
        label.setText(new_content)
        label.adjustSize()  # Adaptive resizing

    btn = QPushButton(window)
    btn.setText("add to the content")
    btn.move(100,300)

    btn.clicked.connect(Cao1)

    window.show()

    # The user area is set (excluding the frame part). The first two coordinates are the coordinates of the user area, and the last two coordinates are the dimensions of the user area
    # However, this line of code must be set after the show() function, and then wrap it when the display is successful
    # window.setGeometry(0,0,150,150)

    # The application executes and enters the message loop
    sys.exit(app.exec_())


(3) Application scenario
(4) Case

import sys
from PyQt5.Qt import *


if __name__ == '__main__':

    app = QApplication(sys.argv)

    window = QWidget()

    # You can display it first, and then set the control size
    window.show()

    # Set the size of the user area
    window.resize(500, 500)
    # Move the entire frame based on the point in the upper left corner
    window.move(300, 300)

    widget_count = 100   # Sets the total number of child controls
    # How many columns are set in a row
    column_count = 5
    # Calculate the width of a control
    widget_width = window.width() / column_count
    # Calculate the total number of lines
    row_count = (widget_count - 1) // column_count + 1
    # Calculate the height of a single control
    widget_height = window.height() / row_count

    for i in range(0,widget_count):
        # Add child controls after the entire frame is displayed
        w = QWidget(window)
        w.resize(widget_width, 100)

        # The x coordinate of each control is the column number * the width of each control (column number: the number takes the remainder of the number of columns)

        # Line No.: the number is used to get the remainder of the number in a row and column
        # Column number: number to divide the number of rows and columns

        widget_x = i % column_count * widget_width
        widget_y = i // column_count * widget_height
        w.move(widget_x,widget_y)


        w.setStyleSheet("background-color:red; border:1px solid yellow;")
        w.show()





    sys.exit(app.exec_())


Test effect:

3.3 maximum and minimum dimensions

3.3.1 API

3.3.2 application scenarios

3.3.3 cases

Test code:

import sys
from PyQt5.Qt import *


if __name__ == '__main__':
    app = QApplication(sys.argv)

    window  = QWidget()

    window.setWindowTitle("Maximum and minimum dimensions")

    window.setMaximumSize(500,500)
    window.setMinimumSize(100,100)

    window.show()

    sys.exit(app.exec_())



3.4 outer margin of content

3.4.1 API

3.4.2 application scenarios

Adjust the control content margin to make the display more beautiful

3.4.3 cases

import sys
from PyQt5.Qt import *


if __name__ == '__main__':
    app = QApplication(sys.argv)

    window  = QWidget()
    window.setWindowTitle("Setting of content margin")
    window.resize(500,500)


    label = QLabel(window)
    label.setText("Society is my brother, and I don't have many cruel words")
    label.resize(300,300)
    label.setStyleSheet("background-color:cyan;")

    # Upper left and lower right
    label.setContentsMargins(100, 200, 0, 0)
    print(label.getContentsMargins())


    print(label.contentsRect())



    window.show()

    sys.exit(app.exec_())


3.5 mouse related

3.5.1 API

(1) Set mouse shape

import sys
from PyQt5.Qt import *


if __name__ == '__main__':
    app = QApplication(sys.argv)

    window  = QWidget()
    window.setWindowTitle("Setting of content margin")
    window.resize(500,500)



    # window.setCursor(Qt.ForbiddenCursor)
    label = QLabel(window)
    label.setText("Hello Neo")
    label.resize(100,100)
    label.setStyleSheet("background-color:cyan;")

    
    label.setCursor(Qt.ForbiddenCursor)



    window.show()

    sys.exit(app.exec_())


(2) Reset shape
unsetCursor()

(3) Get mouse
cursor()->QCursor

(4) Mouse tracking

(5) QCursor object

  • pixmap()
  • pos()
  • setPos(x,y)

3.5.2 application scenarios

Follow up supplement

3.5.3 cases

Follow up supplement

3.6 events

3.6.1 API

(1) Show and close events

(2) Mobile event

moveEvent(QMoveEvent)

(3) Resize

resizeEvent(QResizeEvent)

(4) Mouse event

The test code is as follows:

import sys
from PyQt5.Qt import *

# An event generated by a user will eventually be passed to a specific method of a specific object, and the method will be overridden


class Window(QWidget):
    def __init__(self):
        # Initialize parent class
        super().__init__()
        self.setWindowTitle("Event message learning")
        self.resize(500,500)
        self.setup_ui()

    def setup_ui(self):
        pass

    # QShowEvent() is an event object
    def showEvent(self,QShowEvent):
        print("The window is displayed")

    def closeEvent(self,QCloseEvent):
        print("The window was closed")

    def moveEvent(self,QCloseEvent):
        print("The mouse moved")


    def resizeEvent(self,QResizeEvent):
        print("Window size change")

    def enterEvent(self,QEnterEvent):
        print("The mouse came in")
        self.setStyleSheet("background-color:red;")

    def leaveEvent(self,QLeaveEvent):
        print("The mouse left")
        self.setStyleSheet("background-color:green;")

    def mousePressEvent(self,QMouseEvent):
        print("Mouse pressed")

    def mouseReleaseEvent(self,QMouseEvent):
        print("The mouse is released")

    def mouseDoubleClickedEvent(self,QMouseEvent):
        print("Double click the mouse")

    def mouseMoveEvent(self,QMouseEvent):
        print("The mouse moved")



if __name__ == '__main__':

    app = QApplication(sys.argv)

    window = Window()

    window.show()


    sys.exit(app.exec_())


(5) Keyboard events

(6) Focus event

(7) Drag event

(8) Draw event
Displays the control, called when the control is updated

paintEvent(QPaintEvent)

(9) Change event
Called when the form changes and the font changes

changeEvent(QEvent)

(10) Right click menu
Called when accessing the right-click menu

contextMenuEvent(QContextMenuEvent)

(11) Input method
Input method call

inputMethodEvent(QInputMethodEvent)

3.6.2 application scenarios

When a control is triggered with a specific behavior, it will call a specific method to pass the event to the developer for easy processing. By rewriting these event methods, you can listen for relevant information.

3.6.3 cases

(1) Create a window that contains a label

import sys
from PyQt5.Qt import *


# Rewrite the event mechanism function of QLabel
class MyLabel(QLabel):
    def enterEvent(self,QMouseEvent):
        print("The mouse came in")
        self.setText("Welcome")

    def leaveEvent(self,QMouseEvent):
        print("The mouse left")
        self.setText("Thank you for your patronage")


if __name__ == '__main__':
    app = QApplication(sys.argv)

    window = QWidget()
    window.setWindowTitle("Case 1 of mouse operation")
    window.resize(500,500)

    label = MyLabel(window)
    label.resize(200,200)
    label.move(100,100)
    label.setStyleSheet("background-color: cyan;")

    window.show()
    sys.exit(app.exec_())


(2) Create a window to listen for user keys
Requirements: monitor the user's input of Tab key, monitor the user's input of Ctrl + S combination key, and monitor the user's input of Ctrl + Shift + A

import sys
from PyQt5.Qt import *


# Rewrite the event mechanism function of QLabel
class MyLabel(QLabel):
    def enterEvent(self,QMouseEvent):
        print("The mouse came in")
        self.setText("Welcome")

    def leaveEvent(self,QMouseEvent):
        print("The mouse left")
        self.setText("Thank you for your patronage")

    def keyPressEvent(self, evt):
        print("xx")

        # Determine whether this key is a normal key, Tab key, A BC and other input keys are normal keys, but ctrl is a modifier key
        # if evt.key() == Qt.Key_Tab:
        #     print("the user clicks the Tab key")
        # Modifier key Ctrl and normal key s
        if evt.modifiers() == Qt.ControlModifier | Qt.ShiftModifier and evt.key() == Qt.Key_S:
            print("ctrl + shfit + s It was clicked")


if __name__ == '__main__':
    app = QApplication(sys.argv)

    window = QWidget()
    window.setWindowTitle("Case 1 of mouse operation")
    window.resize(500,500)

    label = MyLabel(window)
    label.resize(200,200)
    label.move(100,100)
    label.setStyleSheet("background-color: cyan;")


    # For key events, it must be clear which control received the key
    label.grabKeyboard()  # Capture keyboard

    window.show()
    sys.exit(app.exec_())


(3) When the window is completed, the user area supports dragging
Click the user area and drag to move the window.

import sys
from PyQt5.Qt import *



class Window(QWidget):
    def __init__(self):
        super().__init__()
        self.flag = False
        self.setWindowTitle("Window moving learning")
        self.resize(500, 500)
        self.setup_ui()

    def setup_ui(self):
        pass

    def mousePressEvent(self, evt):
        self.flag = True


        # Determine two points (the point where the mouse is pressed for the first time, and the original point where the window is currently located)
        # This coordinate is relative to the desktop
        self.mouse_x = evt.globalX()
        self.mouse_y = evt.globalY()
        print(self.mouse_x, self.mouse_y)

        # The original point in the upper left corner of the record window is set as its member variable
        self.origin_x = self.x()
        self.origin_y = self.y()

    def mouseMoveEvent(self, evt):
        if self.flag == True:
            print("Mouse movement")
            # Each time the mouse moves, the latest coordinate position is obtained
            print(evt.globalX(), evt.globalY())

            # Calculate movement vector
            change_x = evt.globalX - self.mouse_x
            change_y = evt.globalY - self.mouse_y

            print(change_x, change_y)

            dest_x = self.origin_x + change_x
            dest_y = self.origin_y + change_y



        self.move(dest_x,dest_y)

    def mouseReleaseEvent(self, evt):
        print("Mouse release")


if __name__ == '__main__':
    app = QApplication(sys.argv)

    window = Window()

    window.show()
    sys.exit(app.exec_())

3.7 parent child relationship

3.7.1 API

API test code:

import sys
from PyQt5.Qt import *

if __name__ == '__main__':

    app = QApplication(sys.argv)

    window  = QWidget()

    label1 = QLabel(window)
    label1.setText("Label 1")

    label2 = QLabel(window)
    label2.setText("Label 2")
    label2.move(50,50)


    label3 = QLabel(window)
    label3.setText("Label 3")
    label3.move(100,100)

    print(window.childAt(55,55))  # Check whether there is a control QLabel in the specified coordinates

    print(label2.parentWidget())  # View his parent control QWidget

    print(window.childrenRect())

    window.show()
    sys.exit(app.exec_())

3.7.2 application scenarios

3.7.3 cases

Test code 1:

import sys
from PyQt5.Qt import *


# Requirement: click the label, and the label turns red


class Label(QLabel):
    def mousePressEvent(self,QMouseEvent):
        self.setStyleSheet("background-color: red;")


if __name__ == '__main__':
    app = QApplication(sys.argv)

    window  = QWidget()

    window.setWindowTitle("Cases of parent-child relationship")
    window.resize(500,500)

    for i in range(1,11):
        label = Label(window)
        label.setText("label"+ str(i))
        label.move(40 * i,40 * i)


    window.show()
    sys.exit(app.exec_())


Test code 2:

import sys
from PyQt5.Qt import *


# Requirement: click the label, and the label turns red

class Window(QWidget):



    # You need to click the label to make the label red, so we need the relative coordinates of the label
    def mousePressEvent(self,evt):
        # print("mouse clicked")
        # QMouseEvent viewing this class, you can see the relative coordinates pos x y
        local_x = evt.x()
        local_y = evt.y()
        sub_widget = self.childAt(local_x,local_y)

        if sub_widget is not None:
            sub_widget.setStyleSheet("background-color:red;")
        print(sub_widget)
        print(local_x,local_y)

if __name__ == '__main__':
    app = QApplication(sys.argv)

    window  = Window()

    window.setWindowTitle("Cases of parent-child relationship")
    window.resize(500,500)

    for i in range(1,11):
        label = QLabel(window)
        label.setText("label"+ str(i))
        label.move(40 * i,40 * i)


    window.show()
    sys.exit(app.exec_())


3.8 hierarchical control

3.8.1 API

3.8.2 application scenarios

The z-axis order of the control needs to be adjusted

3.8.3 cases

Test the above API

Test code:

import sys
from PyQt5.Qt import *

class Label(QLabel):
    def mousePressEvent(self,evt):
        self.raise_()  # Click the label control to rise up


if __name__ == '__main__':


    app = QApplication(sys.argv)

    window = QWidget()
    window.setWindowTitle("Hierarchical relationship")
    window.resize(500,500)

    label1 = Label(window)
    label1.setText("Label 1")
    label1.resize(200,200)
    label1.setStyleSheet("background-color:red;")

    label2 = Label(window)
    label2.setText("Label 2")
    label2.resize(200,200)
    label2.setStyleSheet("background-color:green;")
    label2.move(100,100)

    # label2.lower()

    # label1.raise_()

    label2.stackUnder(label1)  # Label 2 is under label 1


    window.show()
    sys.exit(app.exec_())

3.9 top level window related

3.9.1 API

(1) Icon settings

Test code:

import sys
from PyQt5.Qt import *

if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = QWidget()
    window.setWindowTitle("Window related operations")

    window.resize(500,500)

    icon = QIcon("img.png")  # Add picture path relative path
    window.setWindowIcon(icon)

    print(window.windowIcon())  # Print icon properties

    print(window.windowTitle()) # Print Title Properties

    window.setWindowOpacity(0.5)


    window.show()

    sys.exit(app.exec_())

(2) Opacity settings

setWindowOpacity(transparency)
windowOpacity()
import sys
from PyQt5.Qt import *

if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = QWidget()
    window.setWindowTitle("Window related operations")

    window.resize(500,500)

    icon = QIcon("img.png")  # Add picture path relative path
    window.setWindowIcon(icon)

    print(window.windowIcon())  # Print icon properties

    print(window.windowTitle()) # Print Title Properties

    window.setWindowOpacity(0.5)


    window.show()

    sys.exit(app.exec_())

(3) Window status

Test code:

import sys
from PyQt5.Qt import *

if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = QWidget()
    window.setWindowTitle("Window related operations")

    window.resize(500,500)

    icon = QIcon("img.png")  # Add picture path relative path
    window.setWindowIcon(icon)

    print(window.windowIcon())  # Print icon properties

    print(window.windowTitle()) # Print Title Properties

    window.setWindowOpacity(0.5)

    window.setWindowState(Qt.WindowMaximized)

    window.show()

    sys.exit(app.exec_())

(4) Maximize and minimize windows

3.9.2 application scenarios

See case

3.9.3 cases

import sys
from PyQt5.Qt import *


# Encapsulate
class Window(QWidget):
    def __init__(self,*args,**kwargs):
        super().__init__(*args,**kwargs)
        self.setWindowFlag(Qt.FramelessWindowHint)
        self.setWindowOpacity(0.9)

        self.setWindowTitle("Top level window operation-case")
        self.resize(500, 500)

        self.top_margin = 10 #Set as public data

        self.setup_ui()



    def setup_ui(self):
        # Public data


        # Create three buttons to listen for different click events
        self.close_btn = QPushButton(self)
        self.close_btn.setText("close")

        self.max_btn = QPushButton(self)
        self.max_btn.setText("Maximize")


        self.mini_btn = QPushButton(self)
        self.mini_btn.setText("minimize")


        def max_normal():
            if self.isMaximized():
                self.showNormal()
                self.max_btn.setText("Maximize")

            else:
                self.showMaximized()
                self.max_btn.setText("recovery")

        # Window closing slot function signaling mechanism
        def close():
            self.close()

        # Signal and slot connection
        self.close_btn.pressed.connect(close)
        self.max_btn.pressed.connect(max_normal)
        self.mini_btn.pressed.connect(self.showMinimized)


    def resizeEvent(self, QResizeEvent):
        print("The window size has changed")

        close_btn_x = self.width() - self.close_btn.width()
        close_btn_y = self.top_margin
        self.close_btn.move(close_btn_x, close_btn_y)

        max_btn_x = close_btn_x - self.max_btn.width()
        max_btn_y = self.top_margin
        self.max_btn.move(max_btn_x, max_btn_y)

        mini_btn_x = max_btn_x - self.mini_btn.width()
        mini_btn_y = self.top_margin
        self.mini_btn.move(mini_btn_x, mini_btn_y)



if __name__ == '__main__':
    app = QApplication(sys.argv)

    # When creating a window, pass in the parameter flags to remove the original title bar
    # window = QWidget(flags = Qt.FramelessWindowHint)

    window  = Window()  # Encapsulates this class and automatically executes initialization methods

    window.show()

    sys.exit(app.exec_())

3.10 interaction status

3.10.1 API

(1) Available

  • setEnabled(bool) sets whether the control is disabled
  • isEnabled() gets whether the control is available
import sys
from PyQt5.Qt import *



if __name__ == '__main__':
    app = QApplication(sys.argv)

    window = QWidget()
    window.setWindowTitle("Interaction state")
    window.resize(500,500)

    btn = QPushButton(window)
    btn.setText("Button")
    btn.pressed.connect(lambda : print("Button clicked"))

    print(btn.isEnabled())


    btn.setEnabled(False)

    print(btn.isEnabled())



    window.show()
    sys.exit(app.exec_())

(2) Show / hide

import sys
from PyQt5.Qt import *

class Window(QWidget):

    # When drawing a control
    def paintEvent(self,evt):
        print("The window is drawn")

        # To override the final drawing event, you still need to call the drawing method of the parent class
        return super().paintEvent(evt)

class Btn(QPushButton):

    # Draw a button
    def paintEvent(self,evt):
        print("The button is drawn")

        # Finally, the button needs to call the drawing method of the parent class
        return super().paintEvent(evt)

if __name__ == '__main__':
    app = QApplication(sys.argv)

    window = Window()
    window.setWindowTitle("Interaction state")
    window.resize(500,500)

    btn = Btn(window)
    btn.setText("Button")
    btn.pressed.connect(lambda : print("Button clicked"))

    window.setHidden(False)   # If set to False, the window will be drawn

    btn.setVisible(False)  # The button is set to be invisible, so the event of the button will not be triggered

    sys.exit(app.exec_())

(3) Comprehensive case:
Create a window that contains a text box, a button, and a label.

3.11 information prompt

3.11.1 API

3.11.2 application scenarios

Don't want to fill in

3.11.3 cases

Implement the above API

Test code:

from PyQt5.Qt import *
import sys



if __name__ == '__main__':
    app =QApplication(sys.argv)

    #  QWidget is just a blank control (window)
    # window = QWidget()

    # Replace with a combined control with a title bar window
    window = QMainWindow()

    # Lazy loading display needs to be loaded

    # Activation status bar
    window.statusBar()

    window.setWindowTitle("Information prompt case")
    window.resize(500,500)

    # When the mouse hovers over the window control, it will be prompted in the status bar
    window.setStatusTip("This is the window")

    # Print status prompt
    print(window.statusTip())

    label = QLabel(window)
    label.setText("Society I Shun brother")
    label.setStatusTip("This is a status prompt label")
    label.setToolTip("This is an informational label")

    print(label.toolTip())

    label.setToolTipDuration(2000)  # Let the message prompt label display for two seconds




    window.show()

    sys.exit(app.exec_())



3.12 focus control

3.12.1 API

Parent control angle:

Test code:

import sys
from PyQt5.Qt import *

class Window(QWidget):
     def mousePressEvent(self, evt):
         print(self.focusWidget())



if __name__ == '__main__':


    app = QApplication(sys.argv)


    window = Window()
    window.setWindowTitle("Focus control")
    window.resize(500,500)


    le1 = QLineEdit(window)
    le1.move(50,50)

    le2  = QLineEdit(window)
    le2.move(100,100)

    le3 = QLineEdit(window)
    le3.move(150,150)

    # le2.setFocus()  # Set the second text box to get focus
    # le2.setFocusPolicy(Qt.TabFocus)  # Set how to get focus: Tab can only
    # le2.setFocusPolicy(Qt.ClickFocus)  # Set the way to get focus: mouse click
    # le2.setFocusPolicy(Qt.StrongFocus)  # Focus can be obtained in both ways

    # print(window.focusWidget())

    window.show()
    sys.exit(app.exec_())

4, Signal

Topics: Qt PyQt5