PyQt6实战开发之旅-代码均可运行

image.png

学习感悟

由于官方文档是英文的,所以学习起来不是很直观。 网上的中文教程也都有点偏重就轻,去从头学习细枝末节不是很必要。假如每个控件组件讲十分钟,几百个控件可想而知。 最关键的是有python基础,能理解类与继承,函数调用这些东西。所有教程都过分强调信号与槽这个东西,很大可能他面向的学习对象是零基础的学生,但是你有基础的话一看就明白了,无非就是某些事件发出个信号然后调用函数的过程。 所以我的学习方法就是弄清楚,PyQt6中有哪些模块,每个模块中有哪些组件,每个组件是什么功能,体现在软件上是什么样,有一个直观的认识之后。 就怼着一个目标开始我们的编程。开始设计一款自己的软件,怼着那些厉害的软件模仿功能,我这里就直接模仿者vscode来做了,过程中整理记录好笔记,等软件做出来,自己肯定收获不小。 不然你从头到尾看完教程,才开始实战,这个时候前面学的又忘光了,很消耗人的。 所以说不要一开始就在认知不清楚的时候盲目看教程,很可能看个标签,按钮什么的各种都敲一敲。其实每个细节你都不用太细究,你只需要有个清晰的整体认知,需要使用的时候直接搜索查询拿来使用就好了。

简介

PyQt6组成模块及功能

QtCore
QtGui
QtWidgets
QtDBus
QtNetwork
QtHelp
QtXml
QtSvg
QtSql
QtTest

  • QtCore:这个模块提供了一些基本的功能,如时间处理、文件和目录处理、数据类型、流、属性系统、元对象系统等。
  • QtGui:这个模块是PyQt6中的图形用户界面(GUI)工具集,它提供了一些窗口系统、事件处理、2D图形和基本的图像类等功能。
  • QtWidgets:这个模块是建立在QtGui之上的一套新的控件,它提供了一套丰富的控件集合,例如按钮、文本框、列表框、复选框等。
  • QtDBus:这个模块实现了DBus的底层访问,使得应用程序可以通过DBus进行通信。
  • QtNetwork:这个模块提供了实现网络编程的类和方法,如网络请求和响应、SSL安全连接等。
  • QtHelp:这个模块用于创建帮助文件,支持多种格式,如HTML、XML等。
  • QtXml:这个模块实现了解析和生成XML文档的功能。
  • QtSvg:这个模块提供了将SVG文件转换为QPainter绘图的命令。
  • QtSql:这个模块实现了SQL数据库的访问功能,可以执行SQL语句以及获取查询结果。
  • QtTest:这个模块包含了一些测试工具,用于单元测试和集成测试。

模块所处位置

from PyQt6.QtWidgets import QApplication, QMainWindow, QMenu
from PyQt6.QtGui import QAction,QIcon

版本信息

# QT_VERSION_STR 可以显示 Qt 的版本信息,PYQT_VERSION_STR 可以显示 PyQt 的版本信息
from PyQt6.QtCore import QT_VERSION_STR
from PyQt6.QtCore import PYQT_VERSION_STR

print(QT_VERSION_STR)
print(PYQT_VERSION_STR)

程序实战

第一个程序

import sys
from PyQt6.QtWidgets import QApplication, QMainWindow, QLabel
from PyQt6.QtGui import QIcon

def main():
    app = QApplication(sys.argv)
    window = QMainWindow()
    window.setGeometry(100, 100, 300, 200) 
    window.setWindowTitle("派森斗罗")
    window.setWindowIcon(QIcon('logo.png'))

    QLabel("Hello, World!", window)

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

if __name__ == "__main__":
    main()

居中显示窗口

  • self.frameGeometry() 返回一个 QRect 对象,该对象表示小组件相对于其父级的几何图形,包括任何窗口框架。
  • QGuiApplication.primaryScreen().availableGeometry().center() 返回一个 QPoint 对象,该对象表示主屏幕的可用几何图形的中心点。
  • 此线移动矩形 ( qr ) 的左上角,使其中心位于指定的中心点 ( cp )。
  • rectangle.self.move(qr.topLeft()) :此行将小组件移动到矩形 ( qr ) 的左上角。 qr.topLeft() 返回表示矩形左上角的 A QPoint 。
import sys
from PyQt6.QtWidgets import QApplication, QWidget
from PyQt6.QtGui import QScreen, QGuiApplication
from PyQt6.QtGui import QIcon

class MyApplication(QWidget):
    def __init__(self):
        super().__init__()

        self.initUI()

    def initUI(self):
        self.setGeometry(0, 0, 300, 200)  # Set window size
        self.setWindowTitle('派森斗罗')
        self.setWindowIcon(QIcon('logo.png'))

        self.center()  # Center the window on the screen
    def center(self):
        qr=self.frameGeometry()
        cp=QGuiApplication.primaryScreen().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = MyApplication()
    ex.show()
    sys.exit(app.exec())

PyQt6-初探QMainWindow-各模块的学习方法

QMainWindow是Qt框架中的一个类,用于创建主窗口应用程序。它提供了一个具有一般应用程序框架的主窗口,包括菜单栏、工具栏、状态栏和中央工作区域。 以下是QMainWindow的一些主要特性:

  1. 菜单栏(Menu Bar):QMainWindow允许你添加菜单栏,通过菜单栏你可以创建各种菜单,包括文件、编辑、视图等。
  2. 工具栏(Tool Bar): 你可以在主窗口上添加工具栏,工具栏通常包含一些常用的工具按钮,例如打开、保存、剪切、复制等。
  3. 状态栏(Status Bar):QMainWindow还提供了一个状态栏,用于显示应用程序的状态信息或者当前操作的相关信息。
  4. 中央工作区域(Central Widget): 主要的应用程序界面通常放置在中央工作区域,这是一个可以包含其他Qt小部件的区域,例如文本编辑器、图形视图等。
  5. Dock小部件(Dock Widgets):QMainWindow支持将一些小部件作为停靠窗口,可以通过拖拽将它们放置在主窗口的边缘。
  6. 窗口管理功能: 包括最大化、最小化、关闭等窗口管理功能。

下面是一个简单的例子,演示如何创建一个基本的QMainWindow

from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel

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

        # 设置主窗口标题
        self.setWindowTitle('My Main Window')

        # 添加标签到中央工作区域
        central_widget = QLabel("Hello, QMainWindow!")
        self.setCentralWidget(central_widget)

        # 添加菜单栏
        menubar = self.menuBar()
        file_menu = menubar.addMenu('File')
        file_menu.addAction('Open')
        file_menu.addAction('Save')

        # 添加工具栏
        toolbar = self.addToolBar('Tools')
        toolbar.addAction('Cut')
        toolbar.addAction('Copy')
        toolbar.addAction('Paste')

        # 添加状态栏
        statusbar = self.statusBar()
        statusbar.showMessage('Ready')

if __name__ == '__main__':
    app = QApplication([])
    window = MyMainWindow()
    window.show()
    app.exec_()

这个例子创建了一个简单的主窗口,包括一个标签作为中央工作区域,一个简单的菜单栏,一个工具栏和一个状态栏。这只是一个入门示例,你可以根据你的应用程序需求自定义和扩展QMainWindow

多页面切换实例

在PyQt6中,可以使用QTabWidgetQWidget来实现多页面切换。 当然你也可以自定义组件来实现这样的功能。在这里我们使用QTabWidgetQWidget 以下是一个简单的示例:

import sys
from PyQt6.QtCore import Qt
from PyQt6.QtWidgets import QApplication, QMainWindow, QTabWidget, QVBoxLayout, QPushButton, QWidget
from PyQt6.QtGui import QIcon

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

        self.setWindowTitle("派森斗罗")
        self.setWindowIcon(QIcon('logo.png'))
        self.setGeometry(100, 100, 800, 600)

        self.tab_widget = QTabWidget()
        self.setCentralWidget(self.tab_widget)

        self.page1 = QWidget()
        self.page2 = QWidget()

        self.tab_widget.addTab(self.page1, "页面1")
        self.tab_widget.addTab(self.page2, "页面2")

        layout = QVBoxLayout()
        button1 = QPushButton("切换到页面2")
        button1.clicked.connect(lambda: self.switch_page(2))
        layout.addWidget(button1)

        button2 = QPushButton("切换到页面1")
        button2.clicked.connect(lambda: self.switch_page(1))
        layout.addWidget(button2)

        self.page1.setLayout(layout)
        self.page2.setLayout(layout)

    def switch_page(self, index):
        self.tab_widget.setCurrentIndex(index - 1)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    mainWin = MainWindow()
    mainWin.show()
    sys.exit(app.exec())

在这个示例中,我们创建了一个QMainWindow,并设置了一个QTabWidget作为其中心部件。然后,我们创建了两个QWidgetpage1page2),并将它们添加到QTabWidget中。我们还添加了两个按钮,分别用于在两个页面之间切换。当点击这些按钮时,会调用switch_page方法来切换当前选中的页面。

import sys
from PyQt6.QtCore import Qt
from PyQt6.QtWidgets import QApplication, QMainWindow, QTabWidget, QVBoxLayout, QPushButton, QWidget,QStackedWidget,QLabel
from PyQt6.QtGui import QIcon

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

        self.setWindowTitle("派森斗罗")
        self.setWindowIcon(QIcon('logo.png'))
        self.setGeometry(100, 100, 800, 600)

        self.initStackWeight()
        self.initTabWeight()

    def initStackWeight(self):
        self.stacked_widget = QStackedWidget()
        page1 = QWidget()
        page2 = QWidget()
        label1 = QLabel('这是页面 1')
        label2 = QLabel('这是页面 2')
        page1.layout = QVBoxLayout(page1)
        page2.layout = QVBoxLayout(page2)
        page1.layout.addWidget(label1)
        page2.layout.addWidget(label2)
        self.stacked_widget.addWidget(page1)
        self.stacked_widget.addWidget(page2)
        button1 = QPushButton('显示页面 1')
        button1.clicked.connect(lambda: self.stacked_widget.setCurrentIndex(0))
        button2 = QPushButton('显示页面 2')
        button2.clicked.connect(lambda: self.stacked_widget.setCurrentIndex(1))

        # 显示按钮和堆栈式布局
        mainWindow=QWidget()
        layout = QVBoxLayout()
        layout.addWidget(button1)
        layout.addWidget(button2)
        layout.addWidget(self.stacked_widget)
        mainWindow.setLayout(layout)
        self.setCentralWidget(mainWindow)

    def initTabWeight(self):
        self.tab_widget = QTabWidget()
        print(self.stacked_widget.widget(1).layout.addWidget(self.tab_widget))
        self.page1 = QWidget()
        self.page2 = QWidget()
        self.tab_widget.addTab(self.page1, "页面1")
        self.tab_widget.addTab(self.page2, "页面2")

        layout1 = QVBoxLayout()
        button1 = QPushButton("切换到标签页2")
        button1.clicked.connect(lambda: self.switch_page(2))
        layout1.addWidget(button1)
        self.page1.setLayout(layout1)

        layout2 = QVBoxLayout()
        button2 = QPushButton("切换到标签页1")
        button2.clicked.connect(lambda: self.switch_page(1))
        layout2.addWidget(button2)
        self.page2.setLayout(layout2)

    def switch_page(self, index):
        self.tab_widget.setCurrentIndex(index - 1)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    mainWin = MainWindow()
    mainWin.show()
    sys.exit(app.exec())

顶部菜单栏实例

from PyQt6.QtWidgets import QApplication, QMainWindow, QMenu, QMenuBar
from PyQt6.QtGui import QIcon,QAction
from PyQt6.QtCore import Qt

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        menubar = self.menuBar()
        # 创建文件菜单,里面有二级菜单:打开,保存,设置
        fileMenu = menubar.addMenu('文件')
        openFile = QAction(QIcon('./assets/imgs/icons/open-file.png'),'打开文件', self)
        openFile.setShortcut('Ctrl+O')
        openFile.triggered.connect(self.openFile)
        fileMenu.addAction(openFile)
        openFolder = QAction(QIcon('./assets/imgs/icons/open-folder.png'),'打开文件夹', self)
        openFolder.triggered.connect(self.openFolder)
        fileMenu.addAction(openFolder)
        fileMenu.addSeparator()
        saveFile = QAction(QIcon('./assets/imgs/icons/save.png'),'保存', self)
        saveFile.setShortcut('Ctrl+S')
        saveFile.triggered.connect(self.saveFile)
        fileMenu.addAction(saveFile)
        setting = QAction(QIcon('./assets/imgs/icons/setting.png'),'设置', self)
        setting.triggered.connect(self.setting)
        fileMenu.addAction(setting)
        # 创建帮助菜单
        helpMenu = menubar.addMenu('帮助')
        about = QAction(QIcon('./assets/imgs/icons/about.png'),'关于', self)
        about.triggered.connect(self.about)
        helpMenu.addAction(about)
        helpMenu.addSeparator()
        donation = QAction(QIcon('./assets/imgs/icons/donation.png'),'捐赠', self)
        donation.triggered.connect(self.donation)
        helpMenu.addAction(donation)

        self.setWindowTitle("派森斗罗")
        self.setWindowIcon(QIcon('logo.png'))
        self.setGeometry(300, 300, 400, 200)
        self.show()

    def openFile(self):
        print('打开文件')
    def openFolder(self):
        print('打开文件夹')
    def setting(self):
        print('设置')
    def saveFile(self):
        print('保存文件')
    def about(self):
        print('这是一个顶部菜单栏示例程序')
    def donation(self):
        print('捐赠选项')

if __name__ == '__main__':
    app = QApplication([])
    window = MainWindow()
    app.exec()

多种栏示例

import sys
from PyQt6.QtWidgets import QApplication, QMainWindow,QPushButton,QLabel, QToolBar, QStatusBar, QTabWidget, QVBoxLayout, QWidget
from PyQt6.QtGui import QAction,QIcon

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

        self.initUI()

    def initUI(self):
        # 创建一个退出动作
        exitAction = QAction('退出', self)
        exitAction.setShortcut('Ctrl+Q')
        exitAction.triggered.connect(self.close)

        # 创建一个新建动作
        newAction = QAction('新建', self)

        # 创建一个打开动作
        openAction = QAction('打开', self)

        # 创建菜单栏
        menubar = self.menuBar()
        fileMenu = menubar.addMenu('文件')
        fileMenu.addAction(newAction)
        fileMenu.addAction(openAction)
        fileMenu.addSeparator()
        fileMenu.addAction(exitAction)

        # 创建工具栏
        toolbar = QToolBar()
        toolbar.addAction(newAction)
        toolbar.addAction(openAction)
        toolbar.addAction(exitAction)
        self.addToolBar(toolbar)

        # 创建状态栏
        statusbar = QStatusBar()
        self.setStatusBar(statusbar)
        statusbar.showMessage('这是状态栏',1000)

        btn=QPushButton('显示消息',self)
        btn.move(100,0)
        # 查看定义类
        btn.clicked.connect(lambda x:statusbar.showMessage('您好~',1000))

        # 创建标签栏
        tab_widget = QTabWidget()
        tab1 = QWidget()
        tab2 = QWidget()
        tab_widget.addTab(tab1, '标签1')
        tab_widget.addTab(tab2, '标签2')
        layout = QVBoxLayout()
        tab1.setLayout(layout)
        layout.addWidget(QWidget())  # 向标签1添加内容
        self.setCentralWidget(tab_widget)

        # 创建侧栏
        sidebar = QToolBar('侧栏')
        sidebar.addWidget(QLabel('这是侧边栏'))  # 向侧栏添加内容
        self.addToolBar(sidebar)

        # 创建工具箱栏
        toolbox = QToolBar('工具箱')
        toolbox.addWidget(QLabel('这是工具箱'))  # 向工具箱添加内容
        self.addToolBar(toolbox)

        # 设置主窗口属性
        self.setGeometry(100, 100, 600, 400)
        self.setWindowTitle('派森斗罗')
        self.setWindowIcon(QIcon('logo.png'))
        self.show()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = MyApplication()
    sys.exit(app.exec())

左侧菜单控制右侧多页面切换

import sys
from PyQt6.QtWidgets import QApplication, QMainWindow, QHBoxLayout, QListWidget, QWidget, QStackedWidget,QLabel,QListWidgetItem
from PyQt6.QtGui import QIcon,QAction
from PyQt6.QtCore import Qt

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

        self.initUI()

    def initUI(self):
        self.setGeometry(100, 100, 800, 600)
        self.setWindowTitle('多页面切换示例')

        # 创建一个主窗口部件
        central_widget = QWidget()
        self.setCentralWidget(central_widget)

        # 创建左侧导航栏
        nav_list = QListWidget()

        nav_list.addItem(QListWidgetItem(QIcon('./assets/imgs/icons/game.svg'),'游戏'))
        nav_list.addItem(QListWidgetItem(QIcon('./assets/imgs/icons/login.png'),'登录'))
        nav_list.addItem(QListWidgetItem(QIcon('./assets/imgs/icons/setting.png'),'设置'))
        nav_list.setFixedWidth(100)
        # nav_list.setViewMode(QListWidget.IconMode)
        nav_list.currentItemChanged.connect(self.switchPage)

        # 创建右侧多页面容器
        page_container = QStackedWidget()
        page1 = QWidget()
        QLabel('这是页面 1',page1)
        page1.setWindowTitle('页面 1')
        page2 = QWidget()
        page2.setWindowTitle('页面 2')
        QLabel('这是页面 2',page2)
        page_container.addWidget(page1)
        page_container.addWidget(page2)
        # page_container.setFixedWidth(500)

        # 创建布局管理器
        layout = QHBoxLayout()
        layout.addWidget(nav_list)
        layout.addWidget(page_container)

        central_widget.setLayout(layout)

    def switchPage(self, current, previous):
        if current:
            selected_index = self.centralWidget().layout().itemAt(0).widget().currentRow()
            self.centralWidget().layout().itemAt(1).widget().setCurrentIndex(selected_index)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = MyApplication()
    ex.show()
    sys.exit(app.exec())

pyqt6中如何实现多页面切换?

在 PyQt6 中实现多页面切换通常有多种方法,其中两种主要方法是使用 QStackedWidgetQTabWidget。以下是如何使用这两种方法实现多页面切换的总结:

  1. 使用 QStackedWidget

    • 创建一个 QStackedWidget 对象来托管多个页面。
    • 为每个页面创建一个独立的 QWidget 子类,包括该页面的内容和控件。
    • 使用 addWidget 方法将这些页面部件添加到 QStackedWidget 中,每个页面都有一个索引。
    • 使用 setCurrentIndex 方法切换页面,通过指定页面的索引。
    • 适用于需要程序控制多页面切换的情况。

示例代码:

stacked_widget = QStackedWidget()
page1 = QWidget()
page2 = QWidget()
stacked_widget.addWidget(page1)
stacked_widget.addWidget(page2)
stacked_widget.setCurrentIndex(0)  # 切换到第一个页面

  1. 使用 QTabWidget

    • 创建一个 QTabWidget 对象,它提供了选项卡式的多页面切换。
    • 为每个标签页创建一个独立的 QWidget 子类,包括页面的内容和控件。
    • 使用 addTab 方法将这些页面部件添加到 QTabWidget,同时指定标签页的标题。
    • 用户可以通过点击标签页来切换页面。
    • 适用于以选项卡形式显示多个页面的情况。

示例代码:

tab_widget = QTabWidget()
tab1 = QWidget()
tab2 = QWidget()
tab_widget.addTab(tab1, "页面 1")
tab_widget.addTab(tab2, "页面 2")

根据您的项目需求和个人喜好,您可以选择使用其中一种或两种方法来实现多页面切换。无论您选择哪种方法,都可以根据需要自定义和扩展页面的内容。

QTabweight与Qstackweight的区别

在 PyQt 中,QTabWidgetQStackedWidget 是用于处理多页面(或多视图)的两个不同的部件。它们有一些区别,主要在于它们的设计和用途。

QTabWidget:

  1. 标签页式布局: QTabWidget 提供了一个标签页式的用户界面,允许用户通过选项卡(标签页)来切换不同的页面。
  2. 导航和可见性: 用户可以通过点击选项卡切换页面。每个选项卡上通常有一个相关的标题,并且用户可以通过点击标题来选择相应的页面。
  3. 集成标签栏: QTabWidget 自动提供了一个标签栏,用于容纳选项卡。标签栏通常位于部件的顶部。
  4. 适用于多个页面场景: 当您有一组相关的页面,希望以标签页的形式进行切换时,QTabWidget 是一个很好的选择。
from PyQt6.QtWidgets import QApplication, QWidget, QTabWidget, QVBoxLayout, QLabel

app = QApplication([])

# 创建 QTabWidget
tab_widget = QTabWidget()

# 添加标签页
tab_page1 = QWidget()
label1 = QLabel('这是标签页 1')
tab_page1.layout = QVBoxLayout(tab_page1)
tab_page1.layout.addWidget(label1)
tab_page1.setLayout(tab_page1.layout)
tab_widget.addTab(tab_page1, '标签页 1')

tab_page2 = QWidget()
label2 = QLabel('这是标签页 2')
tab_page2.layout = QVBoxLayout(tab_page2)
tab_page2.layout.addWidget(label2)
tab_page2.setLayout(tab_page2.layout)
tab_widget.addTab(tab_page2, '标签页 2')

tab_widget.show()
app.exec()

QStackedWidget:

  1. 堆栈式布局: QStackedWidget 提供了一个堆栈式的用户界面,允许用户通过推入和弹出页面来切换。
  2. 程序控制切换: 切换页面通常是由程序控制的,而不是用户通过点击标签页来触发的。
  3. 没有集成标签栏: QStackedWidget 不提供内置的标签栏。相反,您需要使用其他部件(例如按钮、菜单)来触发页面切换。
  4. 适用于单个页面显示: 当您有多个页面,但同一时间只显示其中一个页面时,QStackedWidget 是一个很好的选择。
from PyQt6.QtWidgets import QApplication, QWidget, QVBoxLayout, QLabel, QPushButton, QStackedWidget

app = QApplication([])

# 创建 QStackedWidget
stacked_widget = QStackedWidget()

# 添加页面
page1 = QWidget()
label1 = QLabel('这是页面 1')
page1.layout = QVBoxLayout(page1)
page1.layout.addWidget(label1)
page1.setLayout(page1.layout)
stacked_widget.addWidget(page1)

page2 = QWidget()
label2 = QLabel('这是页面 2')
page2.layout = QVBoxLayout(page2)
page2.layout.addWidget(label2)
page2.setLayout(page2.layout)
stacked_widget.addWidget(page2)

# 创建按钮用于切换页面
button1 = QPushButton('显示页面 1')
button1.clicked.connect(lambda: stacked_widget.setCurrentIndex(0))

button2 = QPushButton('显示页面 2')
button2.clicked.connect(lambda: stacked_widget.setCurrentIndex(1))

# 显示按钮和堆栈式布局
layout = QVBoxLayout()
layout.addWidget(button1)
layout.addWidget(button2)
layout.addWidget(stacked_widget)

# 设置堆栈式布局为窗口布局
window = QWidget()
window.setLayout(layout)
window.show()

app.exec()

总体而言,QTabWidget 适用于标签页式导航,而 QStackedWidget 适用于以堆栈形式切换页面的场景。您可以根据具体需求选择使用哪一个。

Qframe与Qweight的区别

在 PyQt 中,QFrameQWidget 是两个不同的类,它们用于创建界面上的可视化组件,但有一些区别。

  1. **QFrame**** 类:**

    • QFrameQWidget 的子类,因此 QFrame 可以包含在其他 QWidget 内或作为 QMainWindow 的中心部件。
    • QFrame 是一个简单的容器,通常用于包含其他小部件或进行布局管理。
    • QFrame 通常用于创建矩形框架,比如创建边框、背景或者一些特殊的辅助图形元素。
from PyQt6.QtWidgets import QFrame
frame = QFrame()

  1. **QWidget**** 类:**

    • QWidget 是一个通用的用户界面对象,也是 QFrame 的基类。
    • QWidget 通常用于创建应用程序的主窗口或作为主窗口中的中心部件。
    • QFrame 相比,QWidget 是更通用的界面元素,可以包含其他小部件,并提供更多的功能。
from PyQt6.QtWidgets import QWidget
widget = QWidget()

总的来说,QFrame 更专注于创建框架和辅助图形,而 QWidget 是一个更通用的界面元素,可以包含其他小部件并提供更广泛的功能。在实际使用中,你可以根据需求选择使用 QWidgetQFrame

先显示登陆页面,登陆成功后显示主页面

import sys
from PyQt6.QtWidgets import QApplication, QWidget, QVBoxLayout, QLineEdit, QPushButton, QLabel
from PyQt6 import QtCore
from PyQt6.QtGui import QIcon

class LoginWindow(QWidget):
    loginSuccessSignal = QtCore.pyqtSignal()  # 登录成功的信号

    def __init__(self):
        super().__init__()

        self.initUI()

    def initUI(self):
        layout = QVBoxLayout(self)

        self.username_input = QLineEdit(self)
        self.password_input = QLineEdit(self)
        self.password_input.setEchoMode(QLineEdit.EchoMode.Password)

        login_button = QPushButton('Login', self)
        login_button.clicked.connect(self.login)

        layout.addWidget(QLabel('Username:'))
        layout.addWidget(self.username_input)
        layout.addWidget(QLabel('Password:'))
        layout.addWidget(self.password_input)
        layout.addWidget(login_button)

        self.setGeometry(300, 300, 400, 200)
        self.setWindowTitle('Login Window')

    def login(self):
        # 在实际应用中,这里应该有登录验证的逻辑
        # 这里简化为判断用户名和密码是否为正确
        if self.username_input.text() == '1' and self.password_input.text() == '1':
            self.loginSuccessSignal.emit()  # 发送登录成功信号
            self.close()

class YourMainWindow(QWidget):
    def __init__(self):
        super().__init__()

        self.initUI()

    def initUI(self):
        self.login_window = LoginWindow()
        self.login_window.loginSuccessSignal.connect(self.showMainWindow)

    def showMainWindow(self):
        self.setGeometry(300, 300, 400, 200)
        self.setWindowTitle('派森斗罗')
        self.setWindowIcon(QIcon('logo.png'))
        self.show()

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

    main_window = YourMainWindow()
    main_window.login_window.show()

    sys.exit(app.exec())

窗口渐显与渐隐

import sys
from PyQt6.QtWidgets import QApplication, QWidget, QVBoxLayout, QPushButton
from PyQt6.QtCore import QPropertyAnimation

class FadeWindow(QWidget):
    def __init__(self):
        super().__init__()

        self.initUI()

    def initUI(self):
        self.setGeometry(300, 300, 400, 200)
        self.setWindowTitle('派森斗罗')

        layout = QVBoxLayout(self)

        fade_out_button = QPushButton('Fade Out', self)
        fade_out_button.clicked.connect(self.fadeOut)

        fade_in_button = QPushButton('Fade In', self)
        fade_in_button.clicked.connect(self.fadeIn)

        layout.addWidget(fade_out_button)
        layout.addWidget(fade_in_button)

        # Set initial opacity to 0
        self.setWindowOpacity(0.0)
        self.fadeIn()

    def fadeIn(self):
        self.animation = QPropertyAnimation(self, b"windowOpacity")
        self.animation.setStartValue(0.0)
        self.animation.setEndValue(1.0)
        self.animation.setDuration(1000)
        self.animation.start()

    def fadeOut(self):
        self.animation = QPropertyAnimation(self, b"windowOpacity")
        self.animation.setStartValue(1.0)
        self.animation.setEndValue(0.0)
        self.animation.setDuration(1000)
        self.animation.finished.connect(self.close)
        self.animation.start()

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

    fade_window = FadeWindow()
    fade_window.show()

    sys.exit(app.exec())

窗口居中变大出现

我最开始想的是从小变到大,绘制之后再不断调用居中函数,最后发现窗口在左上角和中间不断闪动,于是我认真思考了一下想到了其实可以计算出初始状态和末状态的位置大小信息。 如何查看QPropertyAnimation类的方法以及信号。 可以优化一下出场,免去最开始的闪烁一下。

import sys
from PyQt6.QtWidgets import QApplication, QWidget, QVBoxLayout, QPushButton
from PyQt6.QtCore import QPropertyAnimation, QEasingCurve,QRect
from PyQt6.QtGui import QGuiApplication

class ScaleWindow(QWidget):
    def __init__(self):
        super().__init__()

        self.initUI()

    def initUI(self):
        # self.setGeometry(300, 300, 200, 100)
        self.setWindowTitle('变大窗口')
        self.scaleIn()

    def scaleIn(self):
        self.animation = QPropertyAnimation(self, b"geometry")
        self.animation.setStartValue(QRect(100,100,0,0))
        self.animation.setEndValue(QRect(100,100,200,300))
        self.animation.setDuration(1000)
        self.animation.valueChanged.connect(self.center)
        self.animation.setEasingCurve(QEasingCurve.Type.OutQuad)  # Use QEasingCurve.Type.OutQuad
        self.animation.start()
    
    def center(self):
        self.hide()
        qr=self.frameGeometry()
        cp=QGuiApplication.primaryScreen().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())
        self.show()

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

    scale_window = ScaleWindow()
    scale_window.show()

    sys.exit(app.exec())

import sys
from PyQt6.QtWidgets import QApplication, QWidget, QVBoxLayout, QPushButton
from PyQt6.QtCore import QPropertyAnimation, QEasingCurve,QRect
from PyQt6.QtGui import QGuiApplication

class ScaleWindow(QWidget):
    def __init__(self):
        super().__init__()

        self.initUI()

    def initUI(self):
        self.setGeometry(0, 0, 800, 600)
        self.setWindowTitle('变大窗口')
        self.center()
        self.scaleIn()

    def scaleIn(self):
        cp=QGuiApplication.primaryScreen().availableGeometry().center()
        qr=self.frameGeometry()
        self.animation = QPropertyAnimation(self, b"geometry")
        self.animation.setStartValue(QRect(cp.x(),cp.y(),0,0))
        self.animation.setEndValue(qr)
        self.animation.setDuration(1000)
        # self.animation.setDuration(3000)
        self.animation.setEasingCurve(QEasingCurve.Type.Linear)
        # self.animation.setEasingCurve(QEasingCurve.Type.OutQuint)
        # self.animation.setEasingCurve(QEasingCurve.Type.OutBack)
        # self.animation.setEasingCurve(QEasingCurve.Type.OutElastic)
        self.animation.start()
    
    def center(self):
        qr=self.frameGeometry()
        cp=QGuiApplication.primaryScreen().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())

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

    scale_window = ScaleWindow()
    scale_window.show()

    sys.exit(app.exec())

import sys
from PyQt6.QtWidgets import QApplication, QWidget, QVBoxLayout, QPushButton
from PyQt6.QtCore import QPropertyAnimation, QEasingCurve,QRect
from PyQt6.QtGui import QGuiApplication

class ScaleWindow(QWidget):
    def __init__(self):
        super().__init__()

        self.initUI()

    def initUI(self):
        self.setWindowTitle('变大窗口')
        self.scaleIn()

    def scaleIn(self):
        cp=QGuiApplication.primaryScreen().availableGeometry().center()
        qr=self.center()
        self.animation = QPropertyAnimation(self, b"geometry")
        self.animation.setStartValue(QRect(cp.x(),cp.y(),0,0))
        self.animation.setEndValue(qr)
        self.animation.setDuration(1000)
        # self.animation.setDuration(3000)
        self.animation.setEasingCurve(QEasingCurve.Type.Linear)
        # self.animation.setEasingCurve(QEasingCurve.Type.OutQuint)
        # self.animation.setEasingCurve(QEasingCurve.Type.OutBack)
        # self.animation.setEasingCurve(QEasingCurve.Type.OutElastic)
        self.animation.start()
    
    def center(self):
        qr=QRect(0, 0, 800, 600)
        cp=QGuiApplication.primaryScreen().availableGeometry().center()
        qr.moveCenter(cp)
        return qr

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

    scale_window = ScaleWindow()
    scale_window.show()

    sys.exit(app.exec())

最小化窗口到托盘,右键菜单,窗口恢复

import sys
from PyQt6.QtWidgets import QApplication, QMainWindow, QSystemTrayIcon, QMenu
from PyQt6.QtGui import QIcon, QAction

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

        self.initUI()

    def initUI(self):
        self.setWindowTitle('PyQt6 托盘示例')
        self.setWindowIcon(QIcon('logo.png'))
        self.setGeometry(300, 300, 300, 200)

        # 创建系统托盘图标
        self.tray_icon = QSystemTrayIcon(self)
        self.tray_icon.setIcon(QIcon('logo.png'))
        # 创建托盘图标菜单
        tray_menu = QMenu(self)
        action1 = tray_menu.addAction('设置一')
        action2 = tray_menu.addAction('设置二')
        tray_menu.addSeparator()
        action3 = tray_menu.addAction('打开主面板(未实现)')
        tray_menu.addSeparator()
        restore_action = QAction(QIcon('./assets/imgs/icons/recover.svg'),'还原', self)
        restore_action.triggered.connect(self.showNormal)
        exit_action = QAction(QIcon('./assets/imgs/icons/quit.svg'),'退出', self)
        exit_action.triggered.connect(app.quit)

        tray_menu.addAction(restore_action)
        tray_menu.addAction(exit_action)

        self.tray_icon.setContextMenu(tray_menu)
        # 托盘图标点击事件
        self.tray_icon.activated.connect(self.tray_icon_activated)
        self.tray_icon.show()
        
        # self.tray_icon.showMessage("托盘图标示例", "程序已最小化到托盘")


    def tray_icon_activated(self, reason):
        if reason == QSystemTrayIcon.ActivationReason.Trigger:
            if self.isHidden():
                self.showNormal()
                self.raise_()


    def closeEvent(self, event):
        # 重写窗口关闭事件,实现最小化到托盘
        event.ignore()
        self.hide()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MyWindow()
    window.show()
    sys.exit(app.exec())

背景运动及模糊滤镜

Steam登陆界面复现-PyQt6-Python-运动背景图三种实现方式

最开始使用的是重写paintEvent方法,但是后来发现加上模糊的时候窗口内容也模糊了。使用QLabel堆叠实现背景就不会造成窗口内容也模糊了。

import sys
from PyQt6.QtCore import Qt, QTimer
from PyQt6.QtGui import QPainter, QPixmap
from PyQt6.QtWidgets import QApplication, QMainWindow, QWidget,QGraphicsBlurEffect,QLabel

class MovingBackgroundWidget(QWidget):
    def __init__(self):
        super().__init__()
        self.setGeometry(100, 100, 800, 600)
        self.initBg()
        self.initUI()

    def initUI(self):
        label = QLabel('啊哈哈哈哈哈', self)
        label.setGeometry(100, 100, 100, 30)

    def initBg(self):
        # 设置背景图片
        self.background_pixmap = QPixmap("bg.jpg")
        # 暂存当前现实背景图片
        self.background_pixmap_tmp=QPixmap("bg.jpg")
        self.tmp_x=0
        self.tmp_y=0
        # 设置定时器,每隔一段时间触发重绘事件
        self.bg_timer = QTimer(self)
        self.bg_timer.timeout.connect(self.update_background)
        self.bg_timer.start(50)  # 调整移动速度,单位为毫秒
        # 添加毛玻璃模糊滤镜
        blur_effect = QGraphicsBlurEffect()
        blur_effect.setBlurRadius(10)
        self.setGraphicsEffect(blur_effect)

    def paintEvent(self, event):
        painter = QPainter(self)
        painter.drawPixmap(0, 0, self.background_pixmap_tmp)

    def update_background(self):
        self.tmp_x+=2
        self.tmp_y+=1
        self.background_pixmap_tmp = self.background_pixmap.copy(self.tmp_x, self.tmp_y,self.background_pixmap.width()-self.tmp_x, self.background_pixmap.height()-self.tmp_y)
        # 强制重绘
        self.update()

if __name__ == "__main__":
    app = QApplication(sys.argv)
    widget = MovingBackgroundWidget()
    
    # 将 widget 设置为主窗口的中央部件
    main_window = QMainWindow()
    main_window.setCentralWidget(widget)

    main_window.setGeometry(100, 100, 800, 600)
    main_window.show()

    sys.exit(app.exec())

import sys
from PyQt6.QtCore import Qt, QTimer
from PyQt6.QtGui import QPainter, QPixmap,QFont
from PyQt6.QtWidgets import (QApplication, QMainWindow, QWidget,QLabel,
    QGraphicsBlurEffect
    ,QHBoxLayout,QVBoxLayout)
from PyQt6.QtWidgets import QApplication, QWidget, QLabel, QLineEdit, QPushButton, QVBoxLayout, QHBoxLayout, QGridLayout, QCheckBox, QGraphicsOpacityEffect
from PyQt6.QtCore import Qt, QRect, QPropertyAnimation, QParallelAnimationGroup,QSize
from PyQt6.QtGui import QPixmap, QMovie
class LoginWidget(QWidget):
    def __init__(self):
        super().__init__()
        self.setFixedSize(880,550)
        self.setWindowFlag(Qt.WindowType.FramelessWindowHint,True)
        # self.initStyle()
        self.initBg()
        self.initUI()

    def initUI(self):
        # 创建布局和部件
        main_layout = QVBoxLayout(self)
        close_layout = QHBoxLayout()
        top_layout = QHBoxLayout()
        center_layout = QVBoxLayout()
        bottom_layout=QHBoxLayout()

        logo_label = QLabel(self)
        logo_pixmap = QPixmap("logo.png").scaled(70,70)
        logo_label.setPixmap(logo_pixmap)
        logo_label.setAlignment(Qt.AlignmentFlag.AlignTop | Qt.AlignmentFlag.AlignLeft)

        software_label = QLabel("派森斗罗", self)
        software_label.setAlignment(Qt.AlignmentFlag.AlignHCenter | Qt.AlignmentFlag.AlignVCenter)
        software_label.setStyleSheet("font-size: 20px; font-weight: bold; color: white;")

        close_button = QPushButton("×", self)
        close_button.setFixedSize(50,50)
        close_button.setStyleSheet("QPushButton {background-color: rgba(0, 0, 0, 0); color: #616F77;font-size:25px;}\
                                   QPushButton:hover {background-color: #E22A27; color: white;}")
        close_button.clicked.connect(self.close)

        username_label = QLabel("账号:", self)
        password_label = QLabel("密码:", self)
        username_label.setStyleSheet("color:white;font-weight:bold;font-size:15px;")
        password_label.setStyleSheet("color:white;font-weight:bold;font-size:15px;")

        username_input = QLineEdit(self)
        password_input = QLineEdit(self)
        username_input.setFixedSize(180,30)
        password_input.setFixedSize(180,30)
        username_input.setStyleSheet("QLineEdit{border:0;background-color:rgba(0, 0, 0, 100);padding:5px;color:white;font-weight:bold;}\
                                     QLineEdit:hover{background-color:rgba(0, 0, 0, 50);}")

        password_input.setEchoMode(QLineEdit.EchoMode.Password)
        password_input.setStyleSheet("QLineEdit{border:0;background-color:rgba(0, 0, 0, 100);padding:5px;color:white;font-weight:bold;}\
                                     QLineEdit:hover{background-color:rgba(0, 0, 0, 50);}")

        remember_me_checkbox = QCheckBox("记住密码", self)
        remember_me_checkbox.setStyleSheet("color:white;")

        login_button = QPushButton("登录", self)
        login_button.setFixedSize(100,25)
        login_button.setStyleSheet("QPushButton{border:0;color:white;background-color:rgba(0, 0, 255, 150);font-weight:bold;}\
                                     QPushButton:hover{background-color:rgba(0, 0, 255, 80);}")
        login_button.clicked.connect(lambda x:print('登录'))

        register_label = QLabel("还没有账号?  ", self)
        register_label.setStyleSheet("color:white;")
        register_button = QPushButton("去注册", self)
        font=register_button.font()
        font.setUnderline(True)
        register_button.setFont(font)
        register_button.setStyleSheet("border:0;color:white;")

        register_button.clicked.connect(lambda x:print('注册'))

        # 添加部件到布局
        close_layout.addStretch(1)
        close_layout.addWidget(close_button)

        top_layout.addWidget(logo_label)
        top_layout.addWidget(software_label)
        top_layout.addStretch(1)

        center_layout.addWidget(username_label)
        center_layout.addWidget(username_input)
        center_layout.addWidget(password_label)
        center_layout.addWidget(password_input)
        center_layout.addWidget(remember_me_checkbox)
        center_layout.addWidget(login_button, alignment=Qt.AlignmentFlag.AlignCenter)
        center_layout.setAlignment(Qt.AlignmentFlag.AlignHCenter|Qt.AlignmentFlag.AlignVCenter)

        bottom_layout.addStretch(10)
        bottom_layout.addWidget(register_label)
        bottom_layout.addWidget(register_button)
        bottom_layout.addStretch(1)

        main_layout.addLayout(close_layout)
        main_layout.addLayout(top_layout)
        main_layout.addStretch(1)
        main_layout.addLayout(center_layout)
        main_layout.addStretch(5)
        main_layout.addLayout(bottom_layout)
        main_layout.addStretch(3)

    def mousePressEvent(self, event):
        # 鼠标按压
        if event.button() == Qt.MouseButton.LeftButton and self.geometry().contains(self.mapToGlobal(event.pos())):
            self.dis = self.mapToGlobal(event.pos()) - self.pos()
            self.dragging = True
            self.setCursor(Qt.CursorShape.ClosedHandCursor)

    def mouseMoveEvent(self, event):
        # 鼠标移动的时候判断是否是拖拽状态,如果是的话就移动窗口
        if self.dragging:
            self.move(self.mapToGlobal(event.pos()) - self.dis)

    def mouseReleaseEvent(self, event):
        # 鼠标释放的时候接触拖拽状态并且改变鼠标样式
        if event.button() == Qt.MouseButton.LeftButton and self.dragging:
            self.dragging = False
            self.setCursor(Qt.CursorShape.OpenHandCursor)
        
    def initStyle(self):
        self.font=QFont('./assets/fonts/1.ttf')
        self.font.setPointSize(32)
        self.font.setBold(True)
        self.font.setStyle(QFont.Style.StyleNormal)

    def initBg(self):
        self.bg_label=QLabel(self)
        # 设置背景图片
        self.background_pixmap = QPixmap("bg1.jpg").scaled(880+500,550+250)
        # 暂存当前现实背景图片
        self.background_pixmap_tmp=QPixmap("bg1.jpg")
        self.tmp_x=0
        self.tmp_y=0
        self.dx=2
        self.dy=1
        # 设置定时器,每隔一段时间触发重绘事件
        self.bg_timer = QTimer(self)
        self.bg_timer.timeout.connect(self.update_background)
        self.bg_timer.start(50)  # 调整移动速度,单位为毫秒
        # 添加毛玻璃模糊滤镜
        blur_effect = QGraphicsBlurEffect()
        blur_effect.setBlurRadius(20)
        self.bg_label.setGraphicsEffect(blur_effect)

    def update_background(self):
        self.bg_label.setGeometry(self.rect())
        self.bg_label.setPixmap(self.background_pixmap_tmp)
        if self.tmp_x<0 or self.tmp_x>self.background_pixmap.width()-880:
            self.dx,self.dy=-self.dx,-self.dy
        self.tmp_x+=self.dx
        self.tmp_y+=self.dy
        self.background_pixmap_tmp = self.background_pixmap.copy(self.tmp_x,self.background_pixmap.height()-550-self.tmp_y,880,550)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    widget = LoginWidget()
    widget.show()
    sys.exit(app.exec())

from PyQt6.QtWidgets import QApplication, QWidget, QLabel, QLineEdit, QPushButton, QVBoxLayout, QHBoxLayout, QGridLayout, QCheckBox, QGraphicsOpacityEffect
from PyQt6.QtCore import Qt, QRect, QPropertyAnimation, QParallelAnimationGroup,QSize
from PyQt6.QtGui import QPixmap, QMovie
class LoginWindow(QWidget):
    def __init__(self):
        super().__init__()

        self.setWindowTitle("Login")        
        self.initBg()
        self.initUI()

    def mousePressEvent(self, event):
        # 鼠标按压,判断是否是鼠标左键并且点击点在窗口内
        if event.button() == Qt.MouseButton.LeftButton and self.geometry().contains(self.mapToGlobal(event.pos())):
            self.dis = self.mapToGlobal(event.pos()) - self.pos()
            print(self.mapToGlobal(event.pos()),event.pos(),self.pos(),self.dis)
            self.dragging = True
            self.setCursor(Qt.CursorShape.ClosedHandCursor)
    def mouseMoveEvent(self, event):
        # 鼠标移动的时候判断是否是拖拽状态,如果是的话就移动窗口
        if self.dragging:
            # self.move(event.pos()-self.dis)
            self.move(self.mapToGlobal(event.pos()) - self.dis)
    def mouseReleaseEvent(self, event):
        # 鼠标释放的时候接触拖拽状态并且改变鼠标样式
        if event.button() == Qt.MouseButton.LeftButton and self.dragging:
            self.dragging = False
            self.setCursor(Qt.CursorShape.OpenHandCursor)

    def initBg(self):
        # 设置背景图片
        self.setFixedSize(880, 550)
        background_label = QLabel(self)
        background_label.setGeometry(self.rect())
        movie = QMovie("./assets/imgs/bg/bg.gif")
        movie.setScaledSize(QSize(880,550))
        background_label.setMovie(movie)
        movie.start()

    def initUI(self):
        self.setWindowFlag(Qt.WindowType.FramelessWindowHint)
        # 创建布局和部件
        main_layout = QVBoxLayout(self)
        close_layout = QHBoxLayout()
        top_layout = QHBoxLayout()
        center_layout = QVBoxLayout()
        bottom_layout=QHBoxLayout()

        logo_label = QLabel(self)
        logo_pixmap = QPixmap("logo.png").scaled(70,70)
        logo_label.setPixmap(logo_pixmap)
        logo_label.setAlignment(Qt.AlignmentFlag.AlignTop | Qt.AlignmentFlag.AlignLeft)

        software_label = QLabel("派森斗罗", self)
        software_label.setAlignment(Qt.AlignmentFlag.AlignHCenter | Qt.AlignmentFlag.AlignVCenter)
        software_label.setStyleSheet("font-size: 20px; font-weight: bold; color: white;")

        close_button = QPushButton("×", self)
        close_button.setFixedSize(50,50)
        close_button.setStyleSheet("QPushButton {background-color: rgba(0, 0, 0, 0); color: #616F77;font-size:25px;}\
                                   QPushButton:hover {background-color: #E22A27; color: white;}")
        close_button.clicked.connect(self.close)

        username_label = QLabel("账号:", self)
        password_label = QLabel("密码:", self)
        username_label.setStyleSheet("color:white;font-weight:bold;font-size:15px;")
        password_label.setStyleSheet("color:white;font-weight:bold;font-size:15px;")

        username_input = QLineEdit(self)
        password_input = QLineEdit(self)
        username_input.setFixedSize(180,30)
        password_input.setFixedSize(180,30)
        username_input.setStyleSheet("QLineEdit{border:0;background-color:rgba(0, 0, 0, 100);padding:5px;color:white;font-weight:bold;}\
                                     QLineEdit:hover{background-color:rgba(0, 0, 0, 50);}")

        password_input.setEchoMode(QLineEdit.EchoMode.Password)
        password_input.setStyleSheet("QLineEdit{border:0;background-color:rgba(0, 0, 0, 100);padding:5px;color:white;font-weight:bold;}\
                                     QLineEdit:hover{background-color:rgba(0, 0, 0, 50);}")

        remember_me_checkbox = QCheckBox("记住密码", self)
        remember_me_checkbox.setStyleSheet("color:white;")

        login_button = QPushButton("登录", self)
        login_button.setFixedSize(100,25)
        login_button.setStyleSheet("QPushButton{border:0;color:white;background-color:rgba(0, 0, 255, 150);font-weight:bold;}\
                                     QPushButton:hover{background-color:rgba(0, 0, 255, 80);}")
        login_button.clicked.connect(lambda x:print('登录'))

        register_label = QLabel("还没有账号?  ", self)
        register_label.setStyleSheet("color:white;")
        register_button = QPushButton("去注册", self)
        font=register_button.font()
        font.setUnderline(True)
        register_button.setFont(font)
        register_button.setStyleSheet("border:0;color:white;")

        register_button.clicked.connect(lambda x:print('注册'))

        # 添加部件到布局
        close_layout.addStretch(1)
        close_layout.addWidget(close_button)

        top_layout.addWidget(logo_label)
        top_layout.addWidget(software_label)
        top_layout.addStretch(1)

        center_layout.addWidget(username_label)
        center_layout.addWidget(username_input)
        center_layout.addWidget(password_label)
        center_layout.addWidget(password_input)
        center_layout.addWidget(remember_me_checkbox)
        center_layout.addWidget(login_button, alignment=Qt.AlignmentFlag.AlignCenter)
        center_layout.setAlignment(Qt.AlignmentFlag.AlignHCenter|Qt.AlignmentFlag.AlignVCenter)

        bottom_layout.addStretch(10)
        bottom_layout.addWidget(register_label)
        bottom_layout.addWidget(register_button)
        bottom_layout.addStretch(1)

        main_layout.addLayout(close_layout)
        main_layout.addLayout(top_layout)
        main_layout.addStretch(1)
        main_layout.addLayout(center_layout)
        main_layout.addStretch(5)
        main_layout.addLayout(bottom_layout)
        main_layout.addStretch(3)

if __name__ == '__main__':
    app = QApplication([])
    login_window = LoginWindow()
    login_window.show()
    app.exec()

窗口自定义拖拽功能

def mousePressEvent(self, event):
        # 鼠标按压,判断是否是鼠标左键并且点击点在窗口内
        if event.button() == Qt.MouseButton.LeftButton and self.geometry().contains(self.mapToGlobal(event.pos())):
            self.dis = self.mapToGlobal(event.pos()) - self.pos()
            print(self.mapToGlobal(event.pos()),event.pos(),self.pos(),self.dis)
            self.dragging = True
            self.setCursor(Qt.CursorShape.ClosedHandCursor)
def mouseMoveEvent(self, event):
    # 鼠标移动的时候判断是否是拖拽状态,如果是的话就移动窗口
    if self.dragging:
        # self.move(event.pos()-self.dis)
        self.move(self.mapToGlobal(event.pos()) - self.dis)
def mouseReleaseEvent(self, event):
    # 鼠标释放的时候接触拖拽状态并且改变鼠标样式
    if event.button() == Qt.MouseButton.LeftButton and self.dragging:
        self.dragging = False
        self.setCursor(Qt.CursorShape.OpenHandCursor)

import sys
from PyQt6.QtWidgets import QApplication, QWidget
from PyQt6.QtGui import QScreen, QGuiApplication,QIcon
from PyQt6.QtCore import Qt, QRect, QPropertyAnimation, QParallelAnimationGroup,QSize
class MyApplication(QWidget):
    def __init__(self):
        super().__init__()

        self.initUI()
    def mousePressEvent(self, event):
        # 鼠标按压,判断是否是鼠标左键并且点击点在窗口内
        if event.button() == Qt.MouseButton.LeftButton and self.geometry().contains(self.mapToGlobal(event.pos())):
            self.dis = self.mapToGlobal(event.pos()) - self.pos()
            print(self.mapToGlobal(event.pos()),event.pos(),self.pos(),self.dis)
            self.dragging = True
            self.setCursor(Qt.CursorShape.ClosedHandCursor)
    def mouseMoveEvent(self, event):
        # 鼠标移动的时候判断是否是拖拽状态,如果是的话就移动窗口
        if self.dragging:
            # self.move(event.pos()-self.dis)
            self.move(self.mapToGlobal(event.pos()) - self.dis)
    def mouseReleaseEvent(self, event):
        # 鼠标释放的时候接触拖拽状态并且改变鼠标样式
        if event.button() == Qt.MouseButton.LeftButton and self.dragging:
            self.dragging = False
            self.setCursor(Qt.CursorShape.OpenHandCursor)

    def initUI(self):
        self.setGeometry(0, 0, 300, 200)  # Set window size
        self.setWindowTitle('派森斗罗')
        self.setWindowIcon(QIcon('logo.png'))

        self.center()  # Center the window on the screen
    def center(self):
        qr=self.frameGeometry()
        cp=QGuiApplication.primaryScreen().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = MyApplication()
    ex.show()
    sys.exit(app.exec())

窗口双击更换背景

import sys
import typing
from PyQt6.QtWidgets import QApplication, QMainWindow,QSystemTrayIcon,QMenu,QFrame,QHBoxLayout,QVBoxLayout,QLineEdit, QPushButton, QLabel,QListWidget, QMenuBar, QWidget, QStackedWidget,QLabel,QListWidgetItem
from PyQt6.QtGui import (QIcon,QAction,QScreen, QGuiApplication,QColor,QResizeEvent,QDragMoveEvent,QMoveEvent,
QPixmap, QMovie)
from PyQt6.QtCore import (Qt,pyqtSignal,QRect,QPropertyAnimation,
QParallelAnimationGroup, QSequentialAnimationGroup, QPauseAnimation, QEasingCurve,QSize)
from PyQt6.QtWidgets import (QApplication, QWidget, QLabel, QLineEdit, QPushButton,QCheckBox,
QVBoxLayout, QHBoxLayout, QGridLayout,
QGraphicsOpacityEffect)

class LoginWindow(QWidget):
    loginSuccessSignal = pyqtSignal()  # 登录成功的信号

    def __init__(self):
        super().__init__()
        self.configSize=(880,550)
        self.configBg=['bg.gif','bg1.gif','bg2.gif','bg3.gif','bg4.gif','bg5.gif',]

        self.initBg()
        self.initUI()
        self.center()
        self.fadeIn()

    def changeBg(self):
        movie_path='./assets/imgs/bg/'+self.configBg[
        (self.configBg.index(
            self.background_label.movie().fileName().split('/')[-1]
        )+1)
        %len(self.configBg)
        ]
        print(movie_path)
        movie=QMovie(movie_path)
        self.background_label.setMovie(movie)
        movie.setScaledSize(QSize(*self.configSize))
        movie.start()

    def mouseDoubleClickEvent(self,event):
        self.changeBg()
    def initBg(self):
        # 设置窗口无框架,设置大小
        self.setWindowFlag(Qt.WindowType.FramelessWindowHint)
        self.setFixedSize(*self.configSize)
        # 设置背景
        self.background_label = QLabel(self)
        self.background_label.setGeometry(self.rect())
        movie = QMovie('./assets/imgs/bg/'+self.configBg[0])
        # movie = QMovie("bg.gif")
        movie.setScaledSize(QSize(*self.configSize))
        self.background_label.setMovie(movie)
        movie.start()

    def mousePressEvent(self, event):
        # 鼠标按压,判断是否是鼠标左键并且点击点在窗口内
        if event.button() == Qt.MouseButton.LeftButton and self.geometry().contains(self.mapToGlobal(event.pos())):
            self.dis = self.mapToGlobal(event.pos()) - self.pos()
            self.dragging = True
            self.setCursor(Qt.CursorShape.ClosedHandCursor)
    def mouseMoveEvent(self, event):
        # 鼠标移动的时候判断是否是拖拽状态,如果是的话就移动窗口
        if self.dragging:
            self.move(self.mapToGlobal(event.pos()) - self.dis)
    def mouseReleaseEvent(self, event):
        # 鼠标释放的时候接触拖拽状态并且改变鼠标样式
        if event.button() == Qt.MouseButton.LeftButton and self.dragging:
            self.dragging = False
            self.setCursor(Qt.CursorShape.OpenHandCursor)

    def initUI(self):
        # 创建布局和部件
        main_layout = QVBoxLayout(self)
        close_layout = QHBoxLayout()
        top_layout = QHBoxLayout()
        center_layout = QVBoxLayout()
        bottom_layout=QHBoxLayout()

        logo_label = QLabel(self)
        logo_pixmap = QPixmap("logo.png").scaled(70,70)
        logo_label.setPixmap(logo_pixmap)
        logo_label.setAlignment(Qt.AlignmentFlag.AlignTop | Qt.AlignmentFlag.AlignLeft)

        software_label = QLabel("派森斗罗", self)
        software_label.setAlignment(Qt.AlignmentFlag.AlignHCenter | Qt.AlignmentFlag.AlignVCenter)
        software_label.setStyleSheet("font-size: 20px; font-weight: bold; color: white;")

        close_button = QPushButton("×", self)
        close_button.setFixedSize(50,50)
        close_button.setStyleSheet("QPushButton {background-color: rgba(0, 0, 0, 0); color: #616F77;font-size:25px;}\
                                   QPushButton:hover {background-color: #E22A27; color: white;}")
        close_button.clicked.connect(self.close)

        username_label = QLabel("账号:", self)
        password_label = QLabel("密码:", self)
        username_label.setStyleSheet("color:white;font-weight:bold;font-size:15px;")
        password_label.setStyleSheet("color:white;font-weight:bold;font-size:15px;")

        username_input = QLineEdit(self)
        password_input = QLineEdit(self)
        username_input.setFixedSize(180,30)
        password_input.setFixedSize(180,30)
        username_input.setStyleSheet("QLineEdit{border:0;background-color:rgba(80,100,100,150);padding:5px;color:white;font-weight:bold;}\
                                     QLineEdit:hover{background-color:rgba(0, 0, 0, 100);}")

        password_input.setEchoMode(QLineEdit.EchoMode.Password)
        password_input.setStyleSheet("QLineEdit{border:0;background-color:rgba(80,100,100,150);padding:5px;color:white;font-weight:bold;}\
                                     QLineEdit:hover{background-color:rgba(0, 0, 0, 100);}")

        remember_me_checkbox = QCheckBox("记住密码", self)
        remember_me_checkbox.setStyleSheet("color:white;")

        login_button = QPushButton("登录", self)
        login_button.setFixedSize(100,25)
        login_button.setStyleSheet("QPushButton{border:0;color:white;background-color:rgba(0, 0, 255, 150);font-weight:bold;}\
                                     QPushButton:hover{background-color:rgba(0, 0, 255, 80);}")
        login_button.clicked.connect(self.login)
        # login_button.clicked.connect(lambda x:print('登录'))

        register_label = QLabel("还没有账号?  ", self)
        register_label.setStyleSheet("color:white;")
        register_button = QPushButton("去注册", self)
        font=register_button.font()
        font.setUnderline(True)
        register_button.setFont(font)
        register_button.setStyleSheet("border:0;color:white;")

        register_button.clicked.connect(lambda x:print('注册'))

        # 添加部件到布局
        close_layout.addStretch(1)
        close_layout.addWidget(close_button)

        top_layout.addWidget(logo_label)
        top_layout.addWidget(software_label)
        top_layout.addStretch(1)

        center_layout.addWidget(username_label)
        center_layout.addWidget(username_input)
        center_layout.addWidget(password_label)
        center_layout.addWidget(password_input)
        center_layout.addWidget(remember_me_checkbox)
        center_layout.addWidget(login_button, alignment=Qt.AlignmentFlag.AlignCenter)
        center_layout.setAlignment(Qt.AlignmentFlag.AlignHCenter|Qt.AlignmentFlag.AlignVCenter)

        bottom_layout.addStretch(10)
        bottom_layout.addWidget(register_label)
        bottom_layout.addWidget(register_button)
        bottom_layout.addStretch(1)

        main_layout.addLayout(close_layout)
        main_layout.addLayout(top_layout)
        main_layout.addStretch(1)
        main_layout.addLayout(center_layout)
        main_layout.addStretch(5)
        main_layout.addLayout(bottom_layout)
        main_layout.addStretch(3)

        self.setWindowOpacity(0.0)

    def fadeIn(self):
        self.animation = QPropertyAnimation(self, b"windowOpacity")
        self.animation.setStartValue(0.0)
        self.animation.setEndValue(1.0)
        self.animation.setDuration(1000)
        self.animation.start()

    def fadeOut(self):
        self.animation = QPropertyAnimation(self, b"windowOpacity")
        self.animation.setStartValue(1.0)
        self.animation.setEndValue(0.0)
        self.animation.setDuration(1000)
        self.animation.finished.connect(self.quit)
        self.animation.start()
    
    def quit(self):
        self.loginSuccessSignal.emit()  # 发送登录成功信号
        self.close()
    
    def center(self):
        qr=self.frameGeometry()
        cp=QGuiApplication.primaryScreen().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())

    def login(self):
        self.fadeOut()
        # if self.username_input.text() == '1' and self.password_input.text() == '1':
        #     self.fadeOut()

多软件图标排布

from PyQt6 import QtGui
from PyQt6.QtWidgets import QApplication, QWidget, QVBoxLayout, QScrollArea, QLabel, QGridLayout, QPushButton
from PyQt6.QtGui import QPixmap
import sys
import typing
from PyQt6.QtWidgets import QApplication, QMainWindow,QSystemTrayIcon,QMenu,QFrame,QHBoxLayout,QVBoxLayout,QLineEdit, QPushButton, QLabel,QListWidget, QMenuBar, QWidget, QStackedWidget,QLabel,QListWidgetItem
from PyQt6.QtGui import (QIcon,QAction,QScreen, QGuiApplication,QColor,QResizeEvent,QDragMoveEvent,QMoveEvent,
                         QPixmap, QMovie)
from PyQt6.QtCore import (Qt,pyqtSignal,QRect,QPropertyAnimation,
                          QParallelAnimationGroup, QSequentialAnimationGroup, QPauseAnimation, QEasingCurve,QSize)
from PyQt6.QtWidgets import (QApplication, QWidget, QLabel, QLineEdit, QPushButton,QCheckBox,
                             QVBoxLayout, QHBoxLayout, QGridLayout,
                             QGraphicsOpacityEffect)
class SoftwareWindow(QWidget):
    def __init__(self):
        super().__init__()

        self.initUI()
        self.initSoftList()

    def initUI(self):
        self.setWindowTitle('多软件窗口')
        self.setGeometry(100, 100, 700, 100)
        self.show()

    def initSoftList(self):
        # 模拟软件数据
        self.software_data = [
            {"name": "软件1", "icon_path": "assets/imgs/icons/sun.png"},
            {"name": "软件1", "icon_path": "assets/imgs/icons/sun.png"},
            {"name": "软件1", "icon_path": "assets/imgs/icons/sun.png"},
            {"name": "软件1", "icon_path": "assets/imgs/icons/sun.png"},
            {"name": "软件1", "icon_path": "assets/imgs/icons/sun.png"},
            {"name": "软件1", "icon_path": "assets/imgs/icons/sun.png"},
            {"name": "软件1", "icon_path": "assets/imgs/icons/sun.png"},
            {"name": "软件1", "icon_path": "assets/imgs/icons/sun.png"},
            {"name": "软件1", "icon_path": "assets/imgs/icons/sun.png"},
            {"name": "软件1", "icon_path": "assets/imgs/icons/sun.png"},
            {"name": "软件1", "icon_path": "assets/imgs/icons/sun.png"},
            {"name": "软件1", "icon_path": "assets/imgs/icons/sun.png"},
        ]
        self.setSoftBoxs(con=self)

    def setSoftBoxs(self,con,box_width=120,box_height=160):
        # 创建包含软件图标和名称的布局
        layout = QGridLayout()
        print(con.width())
        row, col = 0, 0  # 行和列的起始位置
        # 能够容纳的行
        row_allow=self.width()//120
        for software in self.software_data:
            icon_path = software["icon_path"]
            name = software["name"]
            des='这是软件一ahhah哈哈哈哈哈'
            box=self.getSoftBox(name,icon_path,des,box_width=box_width,box_height=box_height)
            layout.addWidget(box, row, col)
            col += 1
            if col == row_allow:
                col = 0
                row += 1
        con.setLayout(layout)

    def getSoftBox(self,name,logo_path,des,box_width,box_height):
        box=QWidget()
        box.setFixedSize(box_width,box_height)
        box.setToolTip(des)
        # box.setStyleSheet("QWidget{background-color:pink}")
        box.setStyleSheet("QWidget{border:1px solid black;background-color:#FDF6E3;}")
        layout=QVBoxLayout()
        logo_label=QLabel()
        logo_label.setPixmap(QPixmap(logo_path).scaledToWidth(50))
        logo_label.setFixedSize(50,50)
        name_label=QLabel(name)
        des_label=QLabel(des)
        btn=QPushButton('打开')
        layout.addWidget(logo_label)
        layout.addWidget(name_label)
        layout.addWidget(des_label)
        layout.addWidget(btn)
        layout.setAlignment(logo_label,Qt.AlignmentFlag.AlignHCenter | Qt.AlignmentFlag.AlignVCenter)

        box.setLayout(layout)
        return box


if __name__ == '__main__':
    app = QApplication([])
    ex = SoftwareWindow()
    app.exec()

点击按钮打开新页面

import sys
from PyQt6.QtWidgets import QApplication, QMainWindow, QPushButton, QDialog, QVBoxLayout, QLabel

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

        # 创建主窗口
        self.setWindowTitle("派森斗罗")
        self.setGeometry(100, 100, 400, 200)

        # 创建按钮并连接点击信号与槽
        self.button = QPushButton("打开新窗口", self)
        self.button.clicked.connect(self.open_dialog)

    def open_dialog(self):
        # 创建对话框
        self.dialog = MyDialog()
        self.dialog.show()
        self.dialog.exec()

class MyDialog(QDialog):
    def __init__(self):
        super().__init__()

        # 创建对话框中的控件
        layout = QVBoxLayout(self)
        label = QLabel("这是新窗口!", self)
        layout.addWidget(label)

        self.setWindowTitle("派森斗罗")
        self.setGeometry(200, 200, 300, 150)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec())

窗口中画一个框

import sys
from PyQt6.QtWidgets import QApplication, QMainWindow, QWidget
from PyQt6.QtGui import QPainter, QBrush, QPen
from PyQt6.QtCore import Qt, QRect, QPoint

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

        self.initUI()

    def initUI(self):
        self.setGeometry(100, 100, 800, 600)
        self.setWindowTitle('Draw Rectangle')

        self.canvas = DrawingCanvas(self)
        self.setCentralWidget(self.canvas)

        self.show()

class DrawingCanvas(QWidget):
    def __init__(self, parent):
        super().__init__(parent)
        self.setGeometry(0, 0, parent.width(), parent.height())

        self.origin = QPoint(0, 0)  # 初始化为 (0, 0)
        self.end = QPoint(0, 0)     # 初始化为 (0, 0)

    def paintEvent(self, event):
        painter = QPainter(self)
        # 设置绘制选项,启用抗锯齿。
        painter.setRenderHint(QPainter.RenderHint.Antialiasing)

        rect = QRect(self.origin, self.end)
        painter.drawRect(rect)

    def mousePressEvent(self, event):
        if event.button() == Qt.MouseButton.LeftButton:
            self.origin = event.pos()
            self.end = event.pos()

    def mouseMoveEvent(self, event):
        if event.buttons() & Qt.MouseButton.LeftButton:
            self.end = event.pos()
            self.update()

    def mouseReleaseEvent(self, event):
        if event.button() == Qt.MouseButton.LeftButton:
            self.end = event.pos()
            self.update()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = DrawingApp()
    sys.exit(app.exec())

介绍一下QGraphicsScene和QGraphicsView

QGraphicsSceneQGraphicsView 是 PyQt 中用于创建图形用户界面的两个关键类,它们一起协同工作,提供了一种灵活的图形表示方法。以下是它们的主要介绍:

QGraphicsScene

QGraphicsScene 是一个二维图形场景,它允许你在其中添加、移动和交互多个 2D 图形项(QGraphicsItem)。图形项可以是简单的图形元素,如矩形、椭圆和文本,也可以是自定义的图形元素。QGraphicsScene 提供了以下主要功能:

  1. 管理图形项: QGraphicsScene 维护了一个图形项的列表,你可以在其中添加、移除和操纵图形项。
  2. 场景坐标系: 每个图形项都有自己的局部坐标系,而 QGraphicsScene 提供了一个全局坐标系,使你能够在场景中的不同图形项之间执行坐标转换。
  3. 事件处理: QGraphicsScene 可以接收鼠标、键盘和其他事件,你可以通过重写相应的事件处理方法来响应这些事件。
  4. 图形项选择: 你可以选择一个或多个图形项,执行相应的操作,比如拖动、删除等。

QGraphicsView

QGraphicsView 是用于在窗口中显示 QGraphicsScene 的视图类。它提供了以下主要功能:

  1. 显示场景: QGraphicsView 提供一个用于显示 QGraphicsScene 内容的视图窗口。你可以在一个窗口中显示多个 QGraphicsView,每个视图显示同一个或不同的场景。
  2. 视图变换: 通过视图变换,你可以对场景进行平移、缩放、旋转等操作。这使得你可以轻松地实现图形的缩放和平移效果。
  3. 视图更新: 当场景中的图形项发生变化时,QGraphicsView 负责更新视图,以便反映这些变化。
  4. 事件转发: QGraphicsView 接收鼠标、键盘等事件,并将它们传递给场景中的图形项进行处理。
  5. 交互支持: QGraphicsView 提供了一些方便的方法来支持用户的交互,比如启用鼠标拖拽、缩放等。

通过将 QGraphicsSceneQGraphicsView 结合使用,你可以创建出富有交互性的图形界面,用于显示和操作图形元素。这对于图形编辑器、CAD 应用、数据可视化等领域非常有用。

图片浏览,可以放大缩小拖拽

import sys
from PyQt6.QtWidgets import QApplication, QGraphicsView, QGraphicsScene, QGraphicsPixmapItem, QMainWindow
from PyQt6.QtCore import Qt, QPointF
from PyQt6.QtGui import QPixmap, QWheelEvent, QPainter

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

        self.initUI()

    def initUI(self):
        self.setGeometry(100, 100, 800, 600)
        self.setWindowTitle('Image Viewer')

        self.scene = QGraphicsScene(self)
        self.view = GraphicsView(self.scene, self)
        self.setCentralWidget(self.view)

        # Load an example image
        image_path = 'letter.png'  # Replace with the actual path to your image
        pixmap = QPixmap(image_path)
        item = QGraphicsPixmapItem(pixmap)
        self.scene.addItem(item)

        self.show()

class GraphicsView(QGraphicsView):
    def __init__(self, scene, parent):
        super().__init__(scene, parent)
        self.setRenderHint(QPainter.RenderHint.Antialiasing, True)
        self.setStyleSheet('GraphicsView{background-color:#FDF6E3;}')

        self.setDragMode(QGraphicsView.DragMode.ScrollHandDrag)  # Enable hand-drag mode

    def wheelEvent(self, event: QWheelEvent):
        modifiers = event.modifiers()
        if modifiers == Qt.KeyboardModifier.ControlModifier:
            # Zoom only if Ctrl key is pressed
            factor = 1.2  # Zoom factor
            if event.angleDelta().y() < 0:
                factor = 1.0 / factor  # Zoom out for a negative wheel event

            self.scale(factor, factor)

def main():
    app = QApplication(sys.argv)
    viewer = ImageViewer()
    sys.exit(app.exec())

if __name__ == '__main__':
    main()

图片浏览,ctrl+滚轮放大缩小,左键按压拖拽,右键按压画框,框显示坐标信息

import sys
from PyQt6.QtWidgets import QApplication, QGraphicsView, QGraphicsScene, QGraphicsPixmapItem, QGraphicsRectItem, QMainWindow, QGraphicsTextItem
from PyQt6.QtCore import Qt, QRectF
from PyQt6.QtGui import QPixmap, QPainter, QFont

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

        self.initUI()

    def initUI(self):
        self.setGeometry(100, 100, 800, 600)
        self.setWindowTitle('Image Viewer')

        self.scene = QGraphicsScene(self)
        self.view = GraphicsView(self.scene, self)
        self.setCentralWidget(self.view)

        # Load an example image
        image_path = 'letter.png'  # Replace with the actual path to your image
        pixmap = QPixmap(image_path)
        item = QGraphicsPixmapItem(pixmap)
        self.scene.addItem(item)

        self.show()

class GraphicsView(QGraphicsView):
    def __init__(self, scene, parent):
        super().__init__(scene, parent)
        
        self.setStyleSheet('GraphicsView{background-color:#FDF6E3;}')
        self.setRenderHint(QPainter.RenderHint.Antialiasing, True)
        self.setDragMode(QGraphicsView.DragMode.ScrollHandDrag)  # 启用拖拽模式

        self.drawing_rect = None
        self.origin = None
        self.is_drawing = False
        self.coordinate_text_items = {}  # 存储坐标信息的字典,以矩形为键

    def wheelEvent(self, event):
        modifiers = event.modifiers()
        if modifiers == Qt.KeyboardModifier.ControlModifier:
            # 只有在按下 Ctrl 键时才缩放
            factor = 1.2  # 缩放因子
            if event.angleDelta().y() < 0:
                factor = 1.0 / factor  # 对于负的滚轮事件进行缩小

            self.scale(factor, factor)

    def mouseDoubleClickEvent(self, event):
        super().mouseDoubleClickEvent(event)

        if event.button() == Qt.MouseButton.LeftButton:
            # 获取鼠标双击的位置
            double_click_position = event.pos()

            # 获取双击位置相对于原图的像素位置
            double_click_scene_position = self.mapToScene(double_click_position)

            # 获取点击位置相对于原图的像素位置
            item = self.scene().itemAt(double_click_scene_position, self.transform())
            if isinstance(item, QGraphicsRectItem):
                # 删除被点击的矩形的坐标信息
                rect_key = id(item)
                if rect_key in self.coordinate_text_items:
                    self.removeCoordinateTextItems(self.coordinate_text_items[rect_key])

                # 删除被点击的矩形
                self.scene().removeItem(item)

    def mouseMoveEvent(self, event):
        super().mouseMoveEvent(event)

        if event.buttons() & Qt.MouseButton.RightButton:
            if self.is_drawing and self.origin is not None:
                # 获取鼠标当前位置
                current_position = event.pos()

                # 获取当前位置相对于原图的像素位置
                current_scene_position = self.mapToScene(current_position)

                # 更新矩形的大小
                self.drawing_rect.setRect(QRectF(self.origin, current_scene_position))

        # 实时显示图像
        scene_rect = self.sceneRect()
        self.setSceneRect(scene_rect)

    def mouseReleaseEvent(self, event):
        super().mouseReleaseEvent(event)

        if event.button() == Qt.MouseButton.RightButton:
            if self.is_drawing and self.origin is not None:
                self.is_drawing = False

                # 获取鼠标释放的位置
                release_position = event.pos()

                # 获取释放位置相对于原图的像素位置
                release_scene_position = self.mapToScene(release_position)

                # 更新矩形的大小
                self.drawing_rect.setRect(QRectF(self.origin, release_scene_position))

                # 显示矩形的坐标信息
                self.showRectCoordinates(self.drawing_rect)

    def mousePressEvent(self, event):
        super().mousePressEvent(event)

        if event.button() == Qt.MouseButton.RightButton:
            if not self.is_drawing:
                # 获取鼠标点击的位置
                click_position = event.pos()

                # 获取点击位置相对于原图的像素位置
                scene_position = self.mapToScene(click_position)
                self.origin = scene_position
                self.is_drawing = True

                # 创建一个新的矩形
                self.drawing_rect = QGraphicsRectItem(QRectF(self.origin, self.origin))
                self.scene().addItem(self.drawing_rect)

    def showRectCoordinates(self, rect_item):
        # 获取矩形的左上角和右下角相对于图片的坐标
        rect_top_left = rect_item.rect().topLeft()
        rect_bottom_right = rect_item.rect().bottomRight()

        # 将坐标转换为整数
        rect_top_left = rect_top_left.toPoint()
        rect_bottom_right = rect_bottom_right.toPoint()

        # 在矩形的左上角显示坐标信息
        text_item_top_left = QGraphicsTextItem(f"({rect_top_left.x()}, {rect_top_left.y()})")
        text_item_top_left.setPos(rect_top_left.x(), rect_top_left.y() - 15)
        self.scene().addItem(text_item_top_left)

        # 在矩形的右下角显示坐标信息
        text_item_bottom_right = QGraphicsTextItem(f"({rect_bottom_right.x()}, {rect_bottom_right.y()})")
        text_item_bottom_right.setPos(rect_bottom_right.x() - 60, rect_bottom_right.y() + 5)
        self.scene().addItem(text_item_bottom_right)

        # 存储矩形和坐标信息的关联
        rect_key = id(rect_item)
        self.coordinate_text_items[rect_key] = [text_item_top_left, text_item_bottom_right]

    def removeCoordinateTextItems(self, items):
        # 删除与矩形关联的坐标信息
        for item in items:
            self.scene().removeItem(item)

def main():
    app = QApplication(sys.argv)
    viewer = ImageViewer()
    sys.exit(app.exec())

if __name__ == '__main__':
    main()



给出这样一个pyqt6程序,左边是刚才的窗口,窗口右边有按钮和输入框,分别可以输入:

背景图像选择框,字体选择框,字体大小,字体颜色设置,文字区域左顶点,

右顶点,字间隔,行间距,行间距随机扰动值,字体大小随机扰动值,字间距随机扰动值

    font=ImageFont.truetype("hand.ttf", size=100),

    line_spacing=150,

    fill=0,  # 字体“颜色”

    left_margin=100,

    top_margin=100,

    right_margin=100,

    bottom_margin=100,

    word_spacing=15,

    # line_spacing_sigma=6,  # 行间距随机扰动

    line_spacing_sigma=0,  # 行间距随机扰动

    # font_size_sigma=20,  # 字体大小随机扰动

    # font_size_sigma=2,  # 字体大小随机扰动

    font_size_sigma=0,  # 字体大小随机扰动

    word_spacing_sigma=0,  # 字间距随机扰动

    # word_spacing_sigma=3,  # 字间距随机扰动

    start_chars="“([<",  # 特定字符提前换行,防止出现在行尾

    end_chars=",。",  # 防止特定字符因排版算法的自动换行而出现在行首

    perturb_x_sigma=0,  # 笔画横向偏移随机扰动

    # perturb_x_sigma=4,  # 笔画横向偏移随机扰动

    perturb_y_sigma=0,  # 笔画纵向偏移随机扰动

    # perturb_y_sigma=4,  # 笔画纵向偏移随机扰动

    perturb_theta_sigma=0,  # 笔画旋转偏移随机扰动

---------------------------END---------------------------

题外话

在这里插入图片描述

感兴趣的小伙伴,赠送全套Python学习资料,包含面试题、简历资料等具体看下方。

👉CSDN大礼包🎁:全网最全《Python学习资料》免费赠送🆓!(安全链接,放心点击)

一、Python所有方向的学习路线

Python所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照下面的知识点去找对应的学习资源,保证自己学得较为全面。

img

二、Python兼职渠道推荐*

学的同时助你创收,每天花1-2小时兼职,轻松稿定生活费.
在这里插入图片描述

三、最新Python学习笔记

当我学到一定基础,有自己的理解能力的时候,会去阅读一些前辈整理的书籍或者手写的笔记资料,这些笔记详细记载了他们对一些技术点的理解,这些理解是比较独到,可以学到不一样的思路。

img

四、实战案例

纸上得来终觉浅,要学会跟着视频一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。

img

👉CSDN大礼包🎁:全网最全《Python学习资料》免费赠送🆓!(安全链接,放心点击)

若有侵权,请联系删除

  • 20
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: PyQt6是一个用于Python编程语言的GUI工具包,它允许开发人员在Windows、Mac和Linux等多个平台上创建功能强大的图形用户界面(GUI)应用程序。对于那些希望快速开发实战开发人员来说,PyQt6是一个非常有用的工具。 首先,你可以从官方网站上下载PyQt6的源码和文档。官方网站提供了最新的稳定版本和先前版本的下载选项。你可以根据自己的操作系统选择适当的版本进行下载。 在下载完成后,你可以按照文档中的说明进行安装。通常情况下,你只需要运行安装程序并按照步骤完成安装过程。一旦安装完成,你就可以开始在PyQt6中进行快速开发实战PyQt6提供了丰富的GUI组件和工具,使得开发过程更加简单和高效。它包括了各种各样的控件,如按钮、文本框、标签、列表框等等,你可以通过简单的代码来创建和布局这些控件。此外,PyQt6还提供了各种丰富的功能,如绘图、动画、数据存储等,使得你可以轻松地开发出具有复杂功能和交互性的应用程序。 另外,PyQt6还提供了丰富的文档和示例代码。这些文档和示例代码将指导你如何正确地使用PyQt6的各种功能和组件。你可以通过阅读文档和运行示例代码来学习和掌握PyQt6的开发技巧和最佳实践。 总之,PyQt6是一个功能强大的GUI工具包,可以帮助你快速开发实战。你可以从官方网站下载并安装PyQt6,并通过阅读文档和运行示例代码来学习和掌握它的使用方法。无论是初学者还是有经验的开发人员,PyQt6都是一个优秀的选择。 ### 回答2: 在进行PyQt6快速开发实战之前,首先需要下载并安装PyQt6库。PyQt6是一个功能强大的Python框架,它提供了丰富的GUI编程工具和功能,可以帮助开发者快速构建界面丰富、交互性强的应用程序。 要下载PyQt6库,可以通过以下步骤进行: 1. 打开Python的官方网站(https://www.python.org/),并下载和安装Python解释器。请确保安装的是Python 3.x版本,因为PyQt6只支持Python 3。 2. 打开命令行终端(Windows可以使用Cmd、PowerShell等;Mac和Linux可以使用终端),输入以下命令安装PyQt6: ``` pip install PyQt6 ``` 这会自动从Python包索引下载并安装PyQt6库。如果你使用的是conda环境,也可以使用类似的命令进行安装。 3. 安装完成后,你就可以在Python脚本中导入并使用PyQt6库了。只需在脚本中加入以下语句即可: ```python from PyQt6.QtWidgets import QApplication, QMainWindow, QLabel # 在这里写下你的代码 ``` 这样,你就可以根据自己的需要使用PyQt6工具和功能进行开发了。 需要注意的是,PyQt6的下载速度可能会受到网络环境的影响。如果下载速度较慢,可以尝试更换源镜像,或者使用代理服务器来加快下载速度。 总之,通过以上步骤,你可以快速下载并安装PyQt6库,为实战开发提供强大的GUI编程工具和功能。希望这个回答对你有所帮助! ### 回答3: PYQT6是一种用于创建图形用户界面(GUI)应用程序的Python库。它基于了Qt框架,并提供了丰富的功能和工具,可以快速开发和部署可视化的应用程序。 要下载PYQT6快速开发实战的内容,可以采取以下几个步骤: 1. 在互联网浏览器中搜索"PYQT6快速开发实战",可以找到相关的网站或在线资源。 2. 访问可信赖的网站,如官方文档、编程论坛或云存储平台。 3. 在网站中搜索PYQT6快速开发实战的下载链接或资源。 4. 点击下载链接,根据提示选择合适的版本和操作系统。 5. 下载完成后,可以解压缩文件并阅读其中的文档。通常会包含示例代码、教程和其他辅助材料。 6. 根据实际需要,可以在自己的开发环境中调用PYQT6库并开始实际的应用程序开发。 请注意,在下载PYQT6快速开发实战的过程中要保持警惕,避免从不可靠的来源下载,以防止安全风险和恶意软件的感染。 最后,推荐在学习和使用PYQT6过程中,多查阅相关的文档和教程,充分利用PYQT6提供的功能和工具,以便更好地进行快速开发实战

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值