Pyside6百练成真(12)

QTableWidget

from PySide6.QtCore import Qt
from PySide6.QtWidgets import (QWidget, QApplication, QTabWidget, QTableWidgetItem, QVBoxLayout, QTableWidget)
from faker import Faker
class MyWindow(QWidget):
    def __init__(self):
        super().__init__()
        self.fake = Faker(locale='zh_CN')
        self.resize(800,600)

        self.data = [[self.fake.name(),self.fake.address(),self.fake.ascii_email()] for _ in range(80)]
        self.table = QTableWidget()
        self.table.setRowCount(80)
        self.table.setColumnCount(3)

        for rowIndex,row in enumerate(self.data):
            for columnIndex,item in enumerate(row):
                self.table.setItem(rowIndex,columnIndex,QTableWidgetItem(item))

        self.table.setItem(0,0,QTableWidgetItem(self.fake.name()))

        self.mainLayout = QVBoxLayout()
        self.mainLayout.addWidget(self.table)
        self.setLayout(self.mainLayout)


if __name__ == '__main__':
    app = QApplication([])
    try:
        window = MyWindow()
        window.show()
    except FileNotFoundError as e:
        print(e)
    except RuntimeError as e:
        print(f"Error loading UI: {e}")

    app.exec()
# 设置表头
        self.table.setHorizontalHeaderLabels(['姓名','地址','邮箱'])
        # 设置伸缩样式
        self.table.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeMode.Stretch)

```![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/19a294a2c66e4592b318ce0feca73685.png)
![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/d5c4340b357e4547b9080fbb7a73234a.png)
修改元素:
```python
self.table.item(0,0).setText('666') # 修改

排序

self.table.setSortingEnabled(True)

常用的信号:
在这里插入图片描述
在这里插入图片描述

self.table.cellClicked.connect(lambda row,col:print(f'当前点击了{row}行,第{col}列'))

# 可以添加以恶搞button
self.btn = QPushButton('输出')
self.btn.clicked.connect(self.outputSelect)

def outputSelect(self):
	# print(self.table.selectedItems())
	for i in self.table.selectedItems():
		print(i.text())

在表格中进行搜索:


        # 搜索栏
        self.searchLayout = QHBoxLayout()
        self.lineSearch = QLineEdit()
        self.btnSearch = QPushButton('搜索')
        self.searchLayout.addWidget(self.lineSearch)
        self.searchLayout.addWidget(self.btnSearch)


from PySide6.QtCore import Qt
from PySide6.QtWidgets import (QWidget, QApplication, QTabWidget, QTableWidgetItem, QVBoxLayout, QTableWidget,
                               QHeaderView, QHBoxLayout, QLineEdit, QPushButton)
from faker import Faker
class MyWindow(QWidget):
    def __init__(self):
        super().__init__()
        self.fake = Faker(locale='zh_CN')
        self.resize(800,600)

        # 搜索栏
        self.searchLayout = QHBoxLayout()
        self.lineSearch = QLineEdit()
        self.btnSearch = QPushButton('搜索')
        self.btnSearch.clicked.connect(self.search)

        self.searchLayout.addWidget(self.lineSearch)
        self.searchLayout.addWidget(self.btnSearch)

        self.data = [[self.fake.name(),self.fake.address(),self.fake.ascii_email()] for _ in range(80)]
        self.table = QTableWidget()
        self.table.setRowCount(80)
        self.table.setColumnCount(3)
        # 设置表头
        self.table.setHorizontalHeaderLabels(['姓名','地址','邮箱'])
        # 设置伸缩样式
        self.table.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeMode.Stretch)
        self.table.setSortingEnabled(True)
        self.table.cellClicked.connect(lambda row,col:print(f'当前点击了{row}行,第{col}列'))



        for rowIndex,row in enumerate(self.data):
            for columnIndex,item in enumerate(row):
                self.table.setItem(rowIndex,columnIndex,QTableWidgetItem(item))
        self.table.item(0,0).setText('666') # 修改



        self.table.setItem(0,0,QTableWidgetItem(self.fake.name()))

        self.mainLayout = QVBoxLayout()
        self.mainLayout.addLayout(self.searchLayout)
        self.mainLayout.addWidget(self.table)
        self.setLayout(self.mainLayout)

    def search(self):
        searchContent = self.lineSearch.text()
        for rowIndex, row in enumerate(self.data):
            for columnIndex,item in enumerate(row):
                if searchContent in item:
                    self.table.item(rowIndex,columnIndex).setForeground(Qt.GlobalColor.white)
        result = self.table.findItems(searchContent,Qt.MatchFlag.MatchContains)
        for item in result:
            print(item)
            item.setBackground(Qt.GlobalColor.red)
        #跳转
        self.table.scrollToItem(result[0],QTableWidget.ScrollHint.PositionAtTop)


        # for rowIndex,row in enumerate(self.data):
        #     for columnIndex,item in enumerate(row):
        #         if searchContent in item:
        #             self.table.item(rowIndex,columnIndex).setForeground(Qt.GlobalColor.red)
        #         else:
        #             self.table.item(rowIndex,columnIndex).setBackground(Qt.GlobalColor.yellow)

if __name__ == '__main__':
    app = QApplication([])
    try:
        window = MyWindow()
        window.show()
    except FileNotFoundError as e:
        print(e)
    except RuntimeError as e:
        print(f"Error loading UI: {e}")

    app.exec()

合并单元格
一般用pandas
在这里插入图片描述
QTableWidget的上下文菜单
右键菜单

self.getSelected,triggered.connect(self.outputSelect)
self.table.setContextMenuPolicy(Qt.ContextPolicy.ActionsContextMenu)
self.table.addAction(self.getSelected)

如何加载上万条数据同时保证页面不卡?
分页

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

QTableView

在这里插入图片描述

from PySide6.QtCore import Qt
from PySide6.QtWidgets import (QWidget, QApplication, QTabWidget, QTableWidgetItem, QVBoxLayout, QTableWidget,
                               QHeaderView, QHBoxLayout, QLineEdit, QPushButton, QTableView)
from PySide6.QtGui import QStandardItemModel, QStandardItem
from faker import Faker
class MyWindow(QWidget):
    def __init__(self):
        super().__init__()
        self.fake = Faker(locale='zh_CN')
        self.resize(800,600)
        self.data = [[self.fake.name(),self.fake.phone_number(),self.fake.address()] for _ in range(100)]

        # 创建模型
        self.model = QStandardItemModel()
        for indexRow,row in enumerate(self.data):
            for indexColumn,column in enumerate(row):
                self.model.setItem(indexRow,indexColumn,QStandardItem(column))

        # 创建视图层
        self.table = QTableView()
        self.table.setModel(self.model)

        self.table2 = QTableView()
        self.table2.setModel(self.model)


        self.mainLayout = QVBoxLayout()
        self.mainLayout.addWidget(self.table)
        self.mainLayout.addWidget(self.table2)
        self.setLayout(self.mainLayout)



if __name__ == '__main__':
    app = QApplication([])
    try:
        window = MyWindow()
        window.show()
    except FileNotFoundError as e:
        print(e)
    except RuntimeError as e:
        print(f"Error loading UI: {e}")

    app.exec()

MVC 视图模式:
下面这段代码纯粹的封装继承多态:

# 实现一个简单的MVC框架
#Model层
class Model:
    def __init__(self):
        self.username = None
        self.password = None

    def setUsername(self, username):
        self.username = username

    def setPassword(self, password):
        self.password = password

# view层
class QTableView:
    def __init__(self):
        self.model = None

    def set_model(self, model):
        self.model = model

    def get_model(self):
        return self.model

    def print_model(self):
        print('当前的模型为: ',self.model)
        print(self.model.username,self.model.password)



# 实际应用中,使用下面的代码进行MVC框架的调用
model = Model()
model.setUsername('admin')
model.setPassword('123456')

view = QTableView()
view.set_model(model)
view.print_model()

print(vars(model).items())

QTableView本身的属性
在这里插入图片描述
表头自适应
在这里插入图片描述
排序:

self.table.setSortingEnabled(True)

合并:

self.table.setSpan(0,0,2,2)

表格过滤:
涉及到代理类:

from PySide6.QtCore import Qt, QSortFilterProxyModel
 # 创建一个代理模型
        self.agentModel = QSortFilterProxyModel(self)
        self.agentModel.setSourceModel(self.model)
        self.agentModel.setFilterKeyColumn(-1) # 给所有的列都进行搜索
def bind(self):
	self.searchLineEdit.textChanged.connect(lambda text: self.agentModel.setFilterRegularExpression(text))# 搜索默认第一个
# 可以传正则表达式:QRegularExpression(text)
	

在这里插入图片描述

QSqlQueryModel 只读模型

生成数据

import sqlite3
import pandas as pd
from faker import Faker
import os

os.chdir(os.path.dirname(__file__))
fake = Faker(locale='zh_CN')
data = pd.DataFrame([{'name':fake.name(), 'address':fake.address(),'email':fake.email()} for _ in range(1000)])
connect = sqlite3.connect('test.db')
data.to_sql('data', connect, if_exists='replace',index=False)

from PySide6.QtCore import Qt, QSortFilterProxyModel
from PySide6.QtSql import QSqlDatabase, QSqlQueryModel
from PySide6.QtWidgets import (QWidget, QApplication, QTabWidget, QTableWidgetItem, QVBoxLayout, QTableWidget,
                               QHeaderView, QHBoxLayout, QLineEdit, QPushButton, QTableView)
from PySide6.QtGui import QStandardItemModel, QStandardItem
from faker import Faker
class MyWindow(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('QSqlQueryModel')
        self.resize(800,600)

        self.table = QTableView()

        # 和数据库建立练习
        self.db = QSqlDatabase.addDatabase('QSQLITE')
        self.db.setDatabaseName('./test.db')
        if not self.db.open():
            raise Exception('数据库打开失败')

        # 创建模型
        self.model = QSqlQueryModel(self)
        self.model.setQuery("select * from user")

        # 创建表格视图
        self.table = QTableView()
        self.table.setModel(self.model)

        self.mainLayout = QVBoxLayout()
        self.mainLayout.addWidget(self.table)
        self.setLayout(self.mainLayout)




if __name__ == '__main__':
    app = QApplication([])
    try:
        window = MyWindow()
        window.show()
    except FileNotFoundError as e:
        print(e)
    except RuntimeError as e:
        print(f"Error loading UI: {e}")

    app.exec()

QSqlTableModel 可以读写的模型
1.导入模型: QSqlTableModel

# 创建模型
self.model = QSqlTableModel()
self.model.setTable("user")#设置具体的表
self.model.select()

修改表头
在这里插入图片描述
在这里插入图片描述

QTabWidget 选项卡

from PySide6.QtWidgets import (QWidget, QApplication, QVBoxLayout, QTableWidget,
                               QLineEdit, QPushButton, QTableView, QLabel, QTabWidget)
from PySide6.QtGui import QStandardItemModel, QStandardItem
from faker import Faker
class MyWindow(QWidget):
    def __init__(self):
        super().__init__()

        self.tab1 = QWidget()
        self.tab1Layout = QVBoxLayout()
        self.tab1Layout.addWidget(QPushButton('按钮1'))
        self.tab1Layout.addWidget(QLabel('标签1'))
        self.tab1.setLayout(self.tab1Layout)

        self.tab2 = QWidget()
        self.tab2Layout = QVBoxLayout()
        self.tab2Layout.addWidget(QPushButton('按钮2'))
        self.tab2Layout.addWidget(QLabel('标签2'))
        self.tab2.setLayout(self.tab2Layout)

        self.tab3 = QWidget()
        self.tab3Layout = QVBoxLayout()
        self.tab3Layout.addWidget(QPushButton('按钮3'))
        self.tab3Layout.addWidget(QLabel('标签3'))
        self.tab3.setLayout(self.tab3Layout)

        self.tab = QTabWidget(self)
        self.tab.addTab(self.tab1,'选项卡1')
        self.tab.addTab(self.tab2,'选项卡2')
        self.tab.addTab(self.tab3,'选项卡3')
        self.tab.setTabsClosable(True)
        # self.tab.setTabShape(QTabWidget.TabShape.Triangular)
        self.tab.setMovable(True)

        self.tab.tabCloseRequested.connect(lambda index:self.tab.removeTab(index))


        self.mainLayout = QVBoxLayout()
        self.mainLayout.addWidget(self.tab)
        self.setLayout(self.mainLayout)


if __name__ == '__main__':
    app = QApplication([])
    try:
        window = MyWindow()
        window.show()
    except FileNotFoundError as e:
        print(e)
    except RuntimeError as e:
        print(f"Error loading UI: {e}")

    app.exec()

在这里插入图片描述

QTimer 计时器,一个不停唠叨的老妈

轮播图: 随着时间不停更换图片
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
QApplication.processEvents()
无论你正在做什么,当你执行到这一条命令的时候,它会把我们现在这个窗体的控制权还给我们的窗体,会卡住
在这里插入图片描述
但是不是真正的多线程是一个伪多线程,只是将控制权暂时交给我们的窗体,让用户能够进行一个操作。

QThread 子类化
子线程如何传递参数给主窗口,说明信号从子窗口发出
在这里插入图片描述

import time

from PySide6.QtCore import Signal, QThread
from PySide6.QtWidgets import (QWidget, QApplication, QLabel, QVBoxLayout)

class WorkThread(QThread):
    signal = Signal(str)

    def __init__(self):
        super().__init__()
        print('run')

    def run(self):
        for i in range(1,10):
            self.signal.emit(str(i))
            time.sleep(1)

class MyWindow(QWidget):
    def __init__(self):
        super().__init__()
        self.lb = QLabel('当前的值为:0')
        self.workThread = WorkThread()
        self.workThread.signal.connect(lambda x:self.lb.setText(f'当前的值为:'+x))
        self.workThread.started.connect(lambda :print('线程开始'))
        self.workThread.finished.connect(lambda :print('线程结束'))
        self.workThread.start()

        self.mainLayout = QVBoxLayout()
        self.mainLayout.addWidget(self.lb)
        self.setLayout(self.mainLayout)




if __name__ == '__main__':
    app = QApplication([])
    try:
        window = MyWindow()
        window.show()
    except FileNotFoundError as e:
        print(e)
    except RuntimeError as e:
        print(f"Error loading UI: {e}")

    app.exec()

在这里插入图片描述

实例化创建多线程
在这里插入图片描述

主线程传递给子线程
在这里插入图片描述

阻塞线程
wait()

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

### 打包PySide6应用程序为可执行文件 为了将使用PySide6编写的Python应用转换为独立的Windows可执行文件,推荐遵循特定指导原则来确保过程顺利进行。在准备阶段,建议在一个虚拟环境中操作而不是全局环境中安装`pyinstaller`工具[^3]。 一旦环境设置完成并激活之后,可以利用下面给出的具体命令来进行打包工作: 对于基础版本的应用程序,简单的命令可能是这样的: ```bash pyinstaller -F -w main.py --hidden-import PySide6.QtSvg ``` 这条指令中的各个部分具有不同的作用:`-F`选项指示PyInstaller创建单个文件输出;而`--hidden-import`参数用于指定那些可能不会被自动检测到但是仍然必要的模块,在这里特指`PySide6.QtSvg`[^1]。 然而,当遇到更复杂的情况或者特定依赖项缺失时——比如缺少某些目录结构如`ultralytics`文件夹——这表明可能存在未声明的数据资源或者是其他形式的隐含导入路径[^4]。此时应当仔细审查项目的构成以及任何外部库的要求,并相应调整构建配置或通过额外的命令行开关提供这些信息给PyInstaller。 另外值得注意的是,用户也可以查阅PyInstaller的帮助文档获取更多可用选项的信息,方法是简单地输入`pyinstaller -h`[^2]。 #### 示例代码片段展示如何处理基本情况下的PySide6至EXE转换流程 假设有一个名为`main.py`的主要入口脚本,则完整的打包命令看起来像这样: ```bash pyinstaller -F -w main.py --hidden-import PySide6.QtSvg ``` 此命令会尝试生成一个单独的、无控制台窗口显示的(.exe)文件,并且包含了所有必需的PySide6组件和支持其正常工作的隐藏导入。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值