pyqt5冻结+分页表
逻辑代码
# -*- coding: utf-8 -*-
import sys,time,copy
from PyQt5.QtWidgets import QWidget,QApplication, QDesktopWidget,QTableWidgetItem
from QhTableWidgetQGN import Ui_QhTableWidgetQGN
from PyQt5.QtCore import Qt
from PyQt5 import QtCore, QtGui, QtWidgets
from QhQTableWidgetEx import * #导入自定义的表格控件扩展类class QhTableWidgetQGNGUI(QWidget,Ui_QhTableWidgetQGN):"""GUI交互部分代码"""def __init__(self,qh_parent = None):# super().__init__(qh_parent)super(QhTableWidgetQGNGUI, self).__init__()self.setupUi(self)self.QhItemDataLis=[ # 表模型参数 [字段名,字段宽度 0代表默认120,是否可调节宽度0可 1否,数据结构]['#',36,1,['QCHECKBOX',str(''),0,'0,0','',None,None]],['操作',190,1,['QPUSHBUTTON',["执行","修改"],0,'0,0',['ZHIXING','XIUGAI'],None,None]],['操作1',190,0,['QPUSHBUTTON',"执行",0,'0,0','ZHIXING',None,None]],['默认数据',0,1,['NONE',str('阙辉'),0,'0,0','',None,None]],['整型数据',0,1,['INT',526,0,'0,0','',None,None]],['浮点数据',0,1,['FLOAT',526.13,0,'0,0','',None,None]],['字符串类型',0,1,['STR',str('阙辉526'),0,'0,0','',None,None]],['日期类型数据',0,1,['DATA',str("2024-12-12"),0,'0,0','',None,None]],['自定义字符串',0,1,['OWNQLINEEDIT',"378899",5,'0,0','',None,None]],['组合框控件',0,1,['QComboBox',str('阙辉526'),2,'0,0','',None,None]],['采用扩展标签控件QLabelEx',300,0,['QLabel',str('阙辉'),2,'0,0','',None,None]],['多行文本',0,0,['QTEXTEDIT',str('阙辉526\n QComboBox组合框控件, 参数3表示此组合框在字典dic_TableItemData KEY对应的列表(选择项)'),2,'0,0','',None,None]],['任务名称',120,0,['INT',str('QueHui'),0,'0,0','',None,None]],['任务ID',120,0,['INT',str(''),0,'0,0','',None,None]],['任务类型',100,1,['QCOMBOBOX',str(''),1,'0,0','',None,None]],['日期YYYY-MM-DD',138,1,['DATE',str(''),0,'0,0','',None,None]],['时',56,1,['INT',str(''),0,'0,0','',None,None]],['分',56,1,['INT',str(''),0,'0,0','',None,None]],['秒',56,1,['INT',str(''),0,'0,0','',None,None]],['程序名',200,0,['STR',str(''),0,'0,0','',None,None]],['任务状态',100,1,['STR',str(''),0,'0,0','',None,None]],['运行状态',100,1,['STR',str(''),0,'0,0','',None,None]],['累计次数',0,1,['INT',str(''),0,'0,0','',None,None]],]QhTableModel = copy.deepcopy(self.QhItemDataLis)self.QhlstHead = [Qhrow[0] for Qhrow in QhTableModel] # 表头字段:支持动态增加self.QhColwidthLs = [[Qhi,Qhrow[1]] for Qhi,Qhrow in enumerate(QhTableModel)] # 自定义列宽self.QhIsResizeLs = [[Qhi,Qhrow[2]] for Qhi,Qhrow in enumerate(QhTableModel)] # 自定义不可编辑列self.QhHeaderTableWidget = QhQTableWidgetEx(self.QhHeaderWidgetTB,QhrowNum=1,QhlstHead=self.QhlstHead,QhColwidthLs=self.QhColwidthLs,QhIsResizeLs=self.QhIsResizeLs,QhFreeCol=3)self.QhHeaderTableWidget.setRowHeight(0, 37)# 隐藏头表横竖滚动条 阙辉self.QhHeaderTableWidget.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)self.QhHeaderTableWidget.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)self.gridLayout_6.addWidget(self.QhHeaderTableWidget, 0, 0, 1, 1)self.QhMainTableWidget = QhQTableWidgetEx(self.QhMainWidgetTB,QhrowNum=30,QhlstHead=self.QhlstHead,QhColwidthLs=self.QhColwidthLs,QhIsResizeLs=self.QhIsResizeLs,QhFreeCol=3)# 隐藏主表表头信息 阙辉# self.QhMainTableWidget.horizontalHeader().hide()# self.QhMainTableWidget.QhfreezeTableWidget.horizontalHeader().hide()self.gridLayout_5.addWidget(self.QhMainTableWidget, 0, 0, 1, 1)# 横滚动条联动 阙辉self.QhMainTableWidget.horizontalScrollBar().valueChanged.connect(self.QhHeaderTableWidget.horizontalScrollBar().setValue)self.QhHeaderTableWidget.horizontalScrollBar().valueChanged.connect(self.QhMainTableWidget.horizontalScrollBar().setValue)# 列宽联动 阙辉self.QhHeaderTableWidget.horizontalHeader().sectionResized.connect(self.QhupdateMainSectionWidth)self.QhMainTableWidget.horizontalHeader().sectionResized.connect(self.QhupdateHeaderSectionWidth)# 上下列位置保持一一致,设置垂直滚动条一直存在 阙辉self.QhHeaderTableWidget.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)self.QhMainTableWidget.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)self.QhHeaderTableWidget.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)# self.QhButtonTBCX01.clicked.connect(self.Qhffff)def QhupdateMainSectionWidth(self, logicalIndex, oldSize, newSize):self.QhMainTableWidget.setColumnWidth(logicalIndex, newSize)def QhupdateHeaderSectionWidth(self, logicalIndex, oldSize, newSize):self.QhHeaderTableWidget.setColumnWidth(logicalIndex, newSize)
# def QhUpdateRightZW(self):# QhWidthR = self.verticalHeader().width()
# self.QhframeZhanWei01.setMinimumSize(QtCore.QSize(QhWidthR, 10))
# self.QhframeZhanWei01.setMaximumSize(QtCore.QSize(QhWidthR, 10))# def resizeEvent(self, event):
# # 冻结列 逻辑重写
# # 当表格大小发生变化时,更新冻结表格的位置和大小
# # 阙辉
# # self.QhframeZhanWei01.resize(int(20),10)
# super().resizeEvent(event)
# def Qhffff(self):
# print(self.QhMainTableWidget.verticalHeader().width())if __name__ == "__main__":qh_app = QApplication(sys.argv) # 创建应用实例 # 创建应用实例qh_MyWindows = QhTableWidgetQGNGUI() # 创建窗口实例qh_MyWindows.show() # 显示窗口qh_n = qh_app.exec() # 执行exec()方法,进入事件循环,如果遇到窗口退出命令,返回整数qh_nprint(qh_n) # 输出输出关闭事件返回的整数try: # 捕获程序退出事件sys.exit(qh_n) # 通知python系统,结束程序运行except SystemExit:print("请在此做一些其他工作。") # python解释器停止执行前的工作
ui代码
# -*- coding: utf-8 -*-# Form implementation generated from reading ui file 'QhTableWidgetQGN.ui'
#
# Created by: PyQt5 UI code generator 5.15.9
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.from PyQt5 import QtCore, QtGui, QtWidgetsclass Ui_QhTableWidgetQGN(object):def setupUi(self, QhTableWidgetQGN):QhTableWidgetQGN.setObjectName("QhTableWidgetQGN")QhTableWidgetQGN.resize(965, 652)QhTableWidgetQGN.setStyleSheet("QScrollBar:vertical {\n"
" border: none; /* 移除边框,如果需要的话 */\n"
" width: 15px; /* 设置滚动条的宽度 */\n"
" margin:0px 0 0px 0; /*为滚动条区域预留空间,这里22px是上下按钮的高度(假设) */\n"
"}\n"
"\n"
"\n"
"")self.gridLayout = QtWidgets.QGridLayout(QhTableWidgetQGN)self.gridLayout.setContentsMargins(0, 0, 0, 0)self.gridLayout.setSpacing(0)self.gridLayout.setObjectName("gridLayout")self.QhHeaderWidgetQ = QtWidgets.QWidget(QhTableWidgetQGN)self.QhHeaderWidgetQ.setMinimumSize(QtCore.QSize(0, 108))self.QhHeaderWidgetQ.setMaximumSize(QtCore.QSize(16777215, 108))self.QhHeaderWidgetQ.setStyleSheet("")self.QhHeaderWidgetQ.setObjectName("QhHeaderWidgetQ")self.gridLayout_2 = QtWidgets.QGridLayout(self.QhHeaderWidgetQ)self.gridLayout_2.setContentsMargins(0, 0, 0, 0)self.gridLayout_2.setSpacing(0)self.gridLayout_2.setObjectName("gridLayout_2")self.QhHeaderWidgetGN = QtWidgets.QWidget(self.QhHeaderWidgetQ)self.QhHeaderWidgetGN.setMinimumSize(QtCore.QSize(0, 40))self.QhHeaderWidgetGN.setMaximumSize(QtCore.QSize(16777215, 40))self.QhHeaderWidgetGN.setStyleSheet("")self.QhHeaderWidgetGN.setObjectName("QhHeaderWidgetGN")self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.QhHeaderWidgetGN)self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0)self.horizontalLayout_2.setSpacing(0)self.horizontalLayout_2.setObjectName("horizontalLayout_2")self.QhPageWidgetCZ01 = QtWidgets.QWidget(self.QhHeaderWidgetGN)self.QhPageWidgetCZ01.setMinimumSize(QtCore.QSize(0, 40))self.QhPageWidgetCZ01.setMaximumSize(QtCore.QSize(16777215, 40))self.QhPageWidgetCZ01.setObjectName("QhPageWidgetCZ01")self.gridLayout_3 = QtWidgets.QGridLayout(self.QhPageWidgetCZ01)self.gridLayout_3.setContentsMargins(-1, 5, -1, 5)self.gridLayout_3.setObjectName("gridLayout_3")self.widget_ZhanWei01 = QtWidgets.QWidget(self.QhPageWidgetCZ01)self.widget_ZhanWei01.setMinimumSize(QtCore.QSize(0, 30))self.widget_ZhanWei01.setMaximumSize(QtCore.QSize(16777215, 30))self.widget_ZhanWei01.setObjectName("widget_ZhanWei01")self.gridLayout_3.addWidget(self.widget_ZhanWei01, 0, 5, 1, 1)self.QhpushButtonUp01 = QtWidgets.QPushButton(self.QhPageWidgetCZ01)self.QhpushButtonUp01.setMinimumSize(QtCore.QSize(30, 30))self.QhpushButtonUp01.setMaximumSize(QtCore.QSize(30, 30))self.QhpushButtonUp01.setStyleSheet("QPushButton{border-image: url(:/QhImage/QhImage/QhDown01.png);border-radius: 5px; \n"
"}QPushButton:hover{border-image: url(:/QhImage/QhImage/QhDown05.png);border-radius: 5px;\n"
"}QPushButton:checked{color:#fff;border-color:#66b1ff;background-color: #66b1ff;\n"
"}QPushButton:pressed{color:#fff;border-color: #3a8ee6;background-color: #3a8ee6;\n"
"}\n"
"")self.QhpushButtonUp01.setText("")self.QhpushButtonUp01.setObjectName("QhpushButtonUp01")self.gridLayout_3.addWidget(self.QhpushButtonUp01, 0, 0, 1, 1)self.QhCobxPageYM01 = QtWidgets.QComboBox(self.QhPageWidgetCZ01)self.QhCobxPageYM01.setMinimumSize(QtCore.QSize(60, 30))self.QhCobxPageYM01.setMaximumSize(QtCore.QSize(16777215, 30))self.QhCobxPageYM01.setSizeAdjustPolicy(QtWidgets.QComboBox.AdjustToContents)self.QhCobxPageYM01.setObjectName("QhCobxPageYM01")self.gridLayout_3.addWidget(self.QhCobxPageYM01, 0, 1, 1, 1)self.QhLabelPageCount = QtWidgets.QLabel(self.QhPageWidgetCZ01)self.QhLabelPageCount.setMinimumSize(QtCore.QSize(0, 30))self.QhLabelPageCount.setMaximumSize(QtCore.QSize(16777215, 30))self.QhLabelPageCount.setStyleSheet("QLabel {\n"
" color: blue; /* 设置字体颜色为红色 */\n"
" font-weight: bold; /* 设置字体为加粗 */\n"
"}")self.QhLabelPageCount.setAlignment(QtCore.Qt.AlignCenter)self.QhLabelPageCount.setObjectName("QhLabelPageCount")self.gridLayout_3.addWidget(self.QhLabelPageCount, 0, 4, 1, 1)self.QhpushButtonDown01 = QtWidgets.QPushButton(self.QhPageWidgetCZ01)self.QhpushButtonDown01.setMinimumSize(QtCore.QSize(30, 30))self.QhpushButtonDown01.setMaximumSize(QtCore.QSize(30, 30))self.QhpushButtonDown01.setStyleSheet("QPushButton{border-image: url(:/QhImage/QhImage/QhUp01.png);border-radius: 5px; \n"
"}QPushButton:hover{border-image: url(:/QhImage/QhImage/QhUp05.png);border-radius: 5px;\n"
"}QPushButton:checked{color:#fff;border-color:#66b1ff;background-color: #66b1ff;\n"
"}QPushButton:pressed{color:#fff;border-color: #3a8ee6;background-color: #3a8ee6;\n"
"}\n"
"")self.QhpushButtonDown01.setText("")self.QhpushButtonDown01.setObjectName("QhpushButtonDown01")self.gridLayout_3.addWidget(self.QhpushButtonDown01, 0, 2, 1, 1)self.QhCobxPageC = QtWidgets.QComboBox(self.QhPageWidgetCZ01)self.QhCobxPageC.setMinimumSize(QtCore.QSize(99, 30))self.QhCobxPageC.setMaximumSize(QtCore.QSize(16777215, 30))self.QhCobxPageC.setLayoutDirection(QtCore.Qt.LeftToRight)self.QhCobxPageC.setCurrentText("")self.QhCobxPageC.setObjectName("QhCobxPageC")self.gridLayout_3.addWidget(self.QhCobxPageC, 0, 3, 1, 1)self.horizontalLayout_2.addWidget(self.QhPageWidgetCZ01)self.widget_ZhanWei02 = QtWidgets.QWidget(self.QhHeaderWidgetGN)self.widget_ZhanWei02.setMinimumSize(QtCore.QSize(0, 30))self.widget_ZhanWei02.setMaximumSize(QtCore.QSize(16777215, 30))self.widget_ZhanWei02.setObjectName("widget_ZhanWei02")self.horizontalLayout_2.addWidget(self.widget_ZhanWei02)self.QhButwidgetGN = QtWidgets.QWidget(self.QhHeaderWidgetGN)self.QhButwidgetGN.setMinimumSize(QtCore.QSize(268, 40))self.QhButwidgetGN.setMaximumSize(QtCore.QSize(268, 40))self.QhButwidgetGN.setObjectName("QhButwidgetGN")self.gridLayout_4 = QtWidgets.QGridLayout(self.QhButwidgetGN)self.gridLayout_4.setContentsMargins(-1, 5, -1, 5)self.gridLayout_4.setObjectName("gridLayout_4")self.QhButtonTBAdd01 = QtWidgets.QPushButton(self.QhButwidgetGN)self.QhButtonTBAdd01.setMinimumSize(QtCore.QSize(68, 30))self.QhButtonTBAdd01.setMaximumSize(QtCore.QSize(68, 30))self.QhButtonTBAdd01.setStyleSheet("QPushButton{color:#fff;background-color:#67c23a;border: 1px solid #67c23a;border-radius: 10px;\n"
"}QPushButton:hover{color:#fff;border-color:#85ce61;background-color:#85ce61;\n"
"}QPushButton:checked{color:#fff;border-color:#85ce61;background-color: #85ce61;\n"
"}QPushButton:pressed{color:#fff;border-color: #5daf34;background-color: #5daf34;\n"
"}\n"
"")self.QhButtonTBAdd01.setObjectName("QhButtonTBAdd01")self.gridLayout_4.addWidget(self.QhButtonTBAdd01, 0, 1, 1, 1)self.QhButtonTBCX01 = QtWidgets.QPushButton(self.QhButwidgetGN)self.QhButtonTBCX01.setMinimumSize(QtCore.QSize(68, 30))self.QhButtonTBCX01.setMaximumSize(QtCore.QSize(68, 30))self.QhButtonTBCX01.setStyleSheet("QPushButton{color:#fff;background-color:#409eff;border: 1px solid #409eff;border-radius: 10px;\n"
"}QPushButton:hover{color:#fff;border-color:#66b1ff;background-color:#66b1ff;\n"
"}QPushButton:checked{color:#fff;border-color:#66b1ff;background-color: #66b1ff;\n"
"}QPushButton:pressed{color:#fff;border-color: #3a8ee6;background-color: #3a8ee6;\n"
"}\n"
"")self.QhButtonTBCX01.setObjectName("QhButtonTBCX01")self.gridLayout_4.addWidget(self.QhButtonTBCX01, 0, 0, 1, 1)self.QhButtonTBDel01 = QtWidgets.QPushButton(self.QhButwidgetGN)self.QhButtonTBDel01.setMinimumSize(QtCore.QSize(68, 30))self.QhButtonTBDel01.setMaximumSize(QtCore.QSize(68, 30))self.QhButtonTBDel01.setStyleSheet("QPushButton{color:#fff;background-color:#f56c6c;border: 1px solid #f56c6c;border-radius: 10px;\n"
"}QPushButton:hover{color:#fff;border-color:#f78989;background-color:#f78989;\n"
"}QPushButton:checked{color:#fff;border-color:#f78989;background-color: #f78989;\n"
"}QPushButton:pressed{color:#fff;border-color: #dd6161;background-color: #dd6161;\n"
"}\n"
"")self.QhButtonTBDel01.setObjectName("QhButtonTBDel01")self.gridLayout_4.addWidget(self.QhButtonTBDel01, 0, 2, 1, 1)self.horizontalLayout_2.addWidget(self.QhButwidgetGN)self.gridLayout_2.addWidget(self.QhHeaderWidgetGN, 0, 0, 1, 1)self.QhHeaderWidgetTB = QtWidgets.QWidget(self.QhHeaderWidgetQ)self.QhHeaderWidgetTB.setMinimumSize(QtCore.QSize(0, 68))self.QhHeaderWidgetTB.setMaximumSize(QtCore.QSize(16777215, 68))self.QhHeaderWidgetTB.setObjectName("QhHeaderWidgetTB")self.gridLayout_6 = QtWidgets.QGridLayout(self.QhHeaderWidgetTB)self.gridLayout_6.setContentsMargins(0, 0, 0, 0)self.gridLayout_6.setSpacing(0)self.gridLayout_6.setObjectName("gridLayout_6")self.QhHeaderTableWidget = QtWidgets.QTableWidget(self.QhHeaderWidgetTB)self.QhHeaderTableWidget.setMinimumSize(QtCore.QSize(0, 80))self.QhHeaderTableWidget.setMaximumSize(QtCore.QSize(16777215, 80))self.QhHeaderTableWidget.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)self.QhHeaderTableWidget.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)self.QhHeaderTableWidget.setRowCount(1)self.QhHeaderTableWidget.setColumnCount(30)self.QhHeaderTableWidget.setObjectName("QhHeaderTableWidget")self.gridLayout_6.addWidget(self.QhHeaderTableWidget, 0, 0, 1, 1)self.gridLayout_2.addWidget(self.QhHeaderWidgetTB, 1, 0, 1, 1)self.gridLayout.addWidget(self.QhHeaderWidgetQ, 0, 0, 1, 1)self.QhMainWidgetTB = QtWidgets.QWidget(QhTableWidgetQGN)self.QhMainWidgetTB.setObjectName("QhMainWidgetTB")self.gridLayout_5 = QtWidgets.QGridLayout(self.QhMainWidgetTB)self.gridLayout_5.setContentsMargins(0, 0, 0, 0)self.gridLayout_5.setSpacing(0)self.gridLayout_5.setObjectName("gridLayout_5")self.QhMainTableWidget = QtWidgets.QTableWidget(self.QhMainWidgetTB)self.QhMainTableWidget.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)self.QhMainTableWidget.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustIgnored)self.QhMainTableWidget.setRowCount(1)self.QhMainTableWidget.setColumnCount(3)self.QhMainTableWidget.setObjectName("QhMainTableWidget")self.QhMainTableWidget.verticalHeader().setDefaultSectionSize(37)self.QhMainTableWidget.verticalHeader().setMinimumSectionSize(30)self.gridLayout_5.addWidget(self.QhMainTableWidget, 0, 0, 1, 1)self.gridLayout.addWidget(self.QhMainWidgetTB, 1, 0, 1, 1)self.retranslateUi(QhTableWidgetQGN)QtCore.QMetaObject.connectSlotsByName(QhTableWidgetQGN)def retranslateUi(self, QhTableWidgetQGN):_translate = QtCore.QCoreApplication.translateQhTableWidgetQGN.setWindowTitle(_translate("QhTableWidgetQGN", "Form"))self.QhLabelPageCount.setText(_translate("QhTableWidgetQGN", "共9页,共1000000行"))self.QhButtonTBAdd01.setText(_translate("QhTableWidgetQGN", "增加"))self.QhButtonTBCX01.setText(_translate("QhTableWidgetQGN", "查询"))self.QhButtonTBDel01.setText(_translate("QhTableWidgetQGN", "删除"))
import QhTableQGN_rc
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"><class>QhTableWidgetQGN</class><widget class="QWidget" name="QhTableWidgetQGN"><property name="geometry"><rect><x>0</x><y>0</y><width>965</width><height>652</height></rect></property><property name="windowTitle"><string>Form</string></property><property name="styleSheet"><string notr="true">QScrollBar:vertical {border: none; /* 移除边框,如果需要的话 */width: 15px; /* 设置滚动条的宽度 */margin:0px 0 0px 0; /*为滚动条区域预留空间,这里22px是上下按钮的高度(假设) */
}</string></property><layout class="QGridLayout" name="gridLayout"><property name="leftMargin"><number>0</number></property><property name="topMargin"><number>0</number></property><property name="rightMargin"><number>0</number></property><property name="bottomMargin"><number>0</number></property><property name="spacing"><number>0</number></property><item row="0" column="0"><widget class="QWidget" name="QhHeaderWidgetQ" native="true"><property name="minimumSize"><size><width>0</width><height>108</height></size></property><property name="maximumSize"><size><width>16777215</width><height>108</height></size></property><property name="styleSheet"><string notr="true"/></property><layout class="QGridLayout" name="gridLayout_2"><property name="leftMargin"><number>0</number></property><property name="topMargin"><number>0</number></property><property name="rightMargin"><number>0</number></property><property name="bottomMargin"><number>0</number></property><property name="spacing"><number>0</number></property><item row="0" column="0"><widget class="QWidget" name="QhHeaderWidgetGN" native="true"><property name="minimumSize"><size><width>0</width><height>40</height></size></property><property name="maximumSize"><size><width>16777215</width><height>40</height></size></property><property name="styleSheet"><string notr="true"/></property><layout class="QHBoxLayout" name="horizontalLayout_2"><property name="spacing"><number>0</number></property><property name="leftMargin"><number>0</number></property><property name="topMargin"><number>0</number></property><property name="rightMargin"><number>0</number></property><property name="bottomMargin"><number>0</number></property><item><widget class="QWidget" name="QhPageWidgetCZ01" native="true"><property name="minimumSize"><size><width>0</width><height>40</height></size></property><property name="maximumSize"><size><width>16777215</width><height>40</height></size></property><layout class="QGridLayout" name="gridLayout_3"><property name="topMargin"><number>5</number></property><property name="bottomMargin"><number>5</number></property><item row="0" column="5"><widget class="QWidget" name="widget_ZhanWei01" native="true"><property name="minimumSize"><size><width>0</width><height>30</height></size></property><property name="maximumSize"><size><width>16777215</width><height>30</height></size></property></widget></item><item row="0" column="0"><widget class="QPushButton" name="QhpushButtonUp01"><property name="minimumSize"><size><width>30</width><height>30</height></size></property><property name="maximumSize"><size><width>30</width><height>30</height></size></property><property name="styleSheet"><string notr="true">QPushButton{border-image: url(:/QhImage/QhImage/QhDown01.png);border-radius: 5px;
}QPushButton:hover{border-image: url(:/QhImage/QhImage/QhDown05.png);border-radius: 5px;
}QPushButton:checked{color:#fff;border-color:#66b1ff;background-color: #66b1ff;
}QPushButton:pressed{color:#fff;border-color: #3a8ee6;background-color: #3a8ee6;
}
</string></property><property name="text"><string/></property></widget></item><item row="0" column="1"><widget class="QComboBox" name="QhCobxPageYM01"><property name="minimumSize"><size><width>60</width><height>30</height></size></property><property name="maximumSize"><size><width>16777215</width><height>30</height></size></property><property name="sizeAdjustPolicy"><enum>QComboBox::AdjustToContents</enum></property></widget></item><item row="0" column="4"><widget class="QLabel" name="QhLabelPageCount"><property name="minimumSize"><size><width>0</width><height>30</height></size></property><property name="maximumSize"><size><width>16777215</width><height>30</height></size></property><property name="styleSheet"><string notr="true">QLabel {color: blue; /* 设置字体颜色为红色 */font-weight: bold; /* 设置字体为加粗 */
}</string></property><property name="text"><string>共9页,共1000000行</string></property><property name="alignment"><set>Qt::AlignCenter</set></property></widget></item><item row="0" column="2"><widget class="QPushButton" name="QhpushButtonDown01"><property name="minimumSize"><size><width>30</width><height>30</height></size></property><property name="maximumSize"><size><width>30</width><height>30</height></size></property><property name="styleSheet"><string notr="true">QPushButton{border-image: url(:/QhImage/QhImage/QhUp01.png);border-radius: 5px;
}QPushButton:hover{border-image: url(:/QhImage/QhImage/QhUp05.png);border-radius: 5px;
}QPushButton:checked{color:#fff;border-color:#66b1ff;background-color: #66b1ff;
}QPushButton:pressed{color:#fff;border-color: #3a8ee6;background-color: #3a8ee6;
}
</string></property><property name="text"><string/></property></widget></item><item row="0" column="3"><widget class="QComboBox" name="QhCobxPageC"><property name="minimumSize"><size><width>99</width><height>30</height></size></property><property name="maximumSize"><size><width>16777215</width><height>30</height></size></property><property name="layoutDirection"><enum>Qt::LeftToRight</enum></property><property name="currentText"><string/></property></widget></item></layout></widget></item><item><widget class="QWidget" name="widget_ZhanWei02" native="true"><property name="minimumSize"><size><width>0</width><height>30</height></size></property><property name="maximumSize"><size><width>16777215</width><height>30</height></size></property></widget></item><item><widget class="QWidget" name="QhButwidgetGN" native="true"><property name="minimumSize"><size><width>268</width><height>40</height></size></property><property name="maximumSize"><size><width>268</width><height>40</height></size></property><layout class="QGridLayout" name="gridLayout_4"><property name="topMargin"><number>5</number></property><property name="bottomMargin"><number>5</number></property><item row="0" column="1"><widget class="QPushButton" name="QhButtonTBAdd01"><property name="minimumSize"><size><width>68</width><height>30</height></size></property><property name="maximumSize"><size><width>68</width><height>30</height></size></property><property name="styleSheet"><string notr="true">QPushButton{color:#fff;background-color:#67c23a;border: 1px solid #67c23a;border-radius: 10px;
}QPushButton:hover{color:#fff;border-color:#85ce61;background-color:#85ce61;
}QPushButton:checked{color:#fff;border-color:#85ce61;background-color: #85ce61;
}QPushButton:pressed{color:#fff;border-color: #5daf34;background-color: #5daf34;
}
</string></property><property name="text"><string>增加</string></property></widget></item><item row="0" column="0"><widget class="QPushButton" name="QhButtonTBCX01"><property name="minimumSize"><size><width>68</width><height>30</height></size></property><property name="maximumSize"><size><width>68</width><height>30</height></size></property><property name="styleSheet"><string notr="true">QPushButton{color:#fff;background-color:#409eff;border: 1px solid #409eff;border-radius: 10px;
}QPushButton:hover{color:#fff;border-color:#66b1ff;background-color:#66b1ff;
}QPushButton:checked{color:#fff;border-color:#66b1ff;background-color: #66b1ff;
}QPushButton:pressed{color:#fff;border-color: #3a8ee6;background-color: #3a8ee6;
}
</string></property><property name="text"><string>查询</string></property></widget></item><item row="0" column="2"><widget class="QPushButton" name="QhButtonTBDel01"><property name="minimumSize"><size><width>68</width><height>30</height></size></property><property name="maximumSize"><size><width>68</width><height>30</height></size></property><property name="styleSheet"><string notr="true">QPushButton{color:#fff;background-color:#f56c6c;border: 1px solid #f56c6c;border-radius: 10px;
}QPushButton:hover{color:#fff;border-color:#f78989;background-color:#f78989;
}QPushButton:checked{color:#fff;border-color:#f78989;background-color: #f78989;
}QPushButton:pressed{color:#fff;border-color: #dd6161;background-color: #dd6161;
}
</string></property><property name="text"><string>删除</string></property></widget></item></layout></widget></item></layout></widget></item><item row="1" column="0"><widget class="QWidget" name="QhHeaderWidgetTB" native="true"><property name="minimumSize"><size><width>0</width><height>68</height></size></property><property name="maximumSize"><size><width>16777215</width><height>68</height></size></property><layout class="QGridLayout" name="gridLayout_6"><property name="leftMargin"><number>0</number></property><property name="topMargin"><number>0</number></property><property name="rightMargin"><number>0</number></property><property name="bottomMargin"><number>0</number></property><property name="spacing"><number>0</number></property><item row="0" column="0"><widget class="QTableWidget" name="QhHeaderTableWidget"><property name="minimumSize"><size><width>0</width><height>80</height></size></property><property name="maximumSize"><size><width>16777215</width><height>80</height></size></property><property name="verticalScrollBarPolicy"><enum>Qt::ScrollBarAlwaysOn</enum></property><property name="horizontalScrollBarPolicy"><enum>Qt::ScrollBarAlwaysOff</enum></property><property name="rowCount"><number>1</number></property><property name="columnCount"><number>30</number></property><row/><column/><column/><column/><column/><column/><column/><column/><column/><column/><column/><column/><column/><column/><column/><column/><column/><column/><column/><column/><column/><column/><column/><column/><column/><column/><column/><column/><column/><column/><column/></widget></item></layout></widget></item></layout></widget></item><item row="1" column="0"><widget class="QWidget" name="QhMainWidgetTB" native="true"><layout class="QGridLayout" name="gridLayout_5"><property name="leftMargin"><number>0</number></property><property name="topMargin"><number>0</number></property><property name="rightMargin"><number>0</number></property><property name="bottomMargin"><number>0</number></property><property name="spacing"><number>0</number></property><item row="0" column="0"><widget class="QTableWidget" name="QhMainTableWidget"><property name="verticalScrollBarPolicy"><enum>Qt::ScrollBarAlwaysOn</enum></property><property name="sizeAdjustPolicy"><enum>QAbstractScrollArea::AdjustIgnored</enum></property><property name="rowCount"><number>1</number></property><property name="columnCount"><number>3</number></property><attribute name="verticalHeaderDefaultSectionSize"><number>37</number></attribute><attribute name="verticalHeaderMinimumSectionSize"><number>30</number></attribute><row/><column/><column/><column/></widget></item></layout></widget></item></layout></widget><resources><include location="QhTableQGN.qrc"/></resources><connections/>
</ui>
拓展表格
#模块名:QhQTableWidgetEx.py:将QT5/6的表格控件窗体扩展子类
#包含类名: QhQTableWidgetEx: 继承QTableWidget类的扩展类:支持表格中的单元格可加载多种控件等功能
# QLabelEx:继承QLabel类的扩展类:可作为表格单元格的一个控件,自动加载图片,动画等功能
# QHeaderViewEx:可在表格列头显示一个复选框控件,用于全选一项组合框的功能
# OwnQTextEdit:继承QTextEdit类的扩展类:可作为表格单元格的一个控件,主要是去除了默认的粗边框,其他功能自行扩充
# OwnQLineEdit:继承QLineEdit类的扩展类:可作为表格单元格的一个控件,可自定义掩码,如密码等格式化输入
import os,copy
from PyQt5 import *
from PyQt5 import QtCore
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtGui import QImage, QPixmap
from PyQt5.QtGui import QMovie
from PyQt5.QtCore import QByteArray
from PyQt5.QtWidgets import QTableWidget, QHeaderView,QTableWidgetItem,\QCheckBox,QWidget,QLabel,QPushButton,QComboBox,QLineEdit,QTextEdit
from PyQt5.QtGui import QBrush, QColor
from PyQt5.QtCore import Qtclass QhQTableWidgetEx(QTableWidget):#'NONE':默认数据,采用默认表格单元格,不在表格位置创建任何依附控件()#'INT': 整型数据,采用默认表格单元格#'FLOAT':浮点数据,采用默认表格单元格#'STR':字符串类型,采用默认表格单元格#'DATA':日期类型数据,采用单行OwnQLineEdit控件(设置掩码)#'OWNQLINEEDIT':自定义字符串,采用单行OwnQLineEdit控件#'QComboBox':组合框控件, 参数3表示此组合框在字典dic_TableItemData KEY对应的列表(选择项)#'QCheckBox':复选框控件, 参数3无意义 无法调节宽度 涉及时就必须计算好宽度#'QLabel':采用扩展标签控件QLabelEx, 参数3表示标签可选用的图象列表,在字典dic_TableItemData KEY对应的二进制数据(已将文件加载到内存后)#'QPushButtom':采用按纽, 参数3表示按纽选用图标在字典dic_TableItemData KEY对应的二进制数据(已将文件加载到内存后)DEF_ITEMDATA=['STR','',0,'0,0','',None,None] #默认单元格绑定的数据格式:[类型,值,掩码ID,索引(row,col),对象名str,对象,对象]#定义表格控件要用的的组合框等下拉列表要用到的数据,为单元格列表对象的第2个元素值dic_TableItemData={0:[None], #0: KEY容错处理用1:['选项01','选项02','选项03'], #1:示例-供表格中的下拉组合框用,选择项列表12:['选项A','选项B','选项C','选项D'], #2:示例-供表格中的下拉组合框用,选择项列表23:['1.png','2.png','3.png','4.png'], #3:示例-供表格中的标签、按纽等使用,显示图象4:'999999999999;#', #4:示例-供表格中的自定义编辑框使用的掩码5:'0000-00-00', #5:示例-供表格中的自定义编辑框使用的掩码6:''} scrollbar_value = pyqtSignal(int)#初始化对角需传递的参数为父类: def __init__(self,parent, # 父类QhrowNum, # 行数QhlstHead, # 表头字段列表QhColwidthLs, # 自定义列宽列表QhIsResizeLs, # 自定义不可编辑列列表# QhTableModel, # 表格模型 # 表模型参数 [[字段名,字段宽度 0代表默认120,是否可调节宽度0可 1否,数据结构],...]QhFreeCol=3, # 冻结列数): super(QTableWidget, self).__init__(parent)# 初始化数据self.QhCheckBoxflag = Falseself.QhFreeCol = QhFreeCol # 冻结列数self.QhlstHead = QhlstHead # 表头字段:支持动态增加self.QhColwidthLs = QhColwidthLs # 自定义列宽self.QhIsResizeLs = QhIsResizeLs # 自定义不可编辑列self.QhCheckBoxList = [] # 复选框列表 仅限于第1列,0列 其他暂不支持self.curRowCount=QhrowNum #表格当前的总行数self.curColCount=len(self.QhlstHead) #表格当前的总列数self.QhitemData=[[[],[]],[[],[]]] #定义同表格绑定的列表 self.QhitemData.clear()# self.Qhitem_one=copy.deepcopy(QhQTableWidgetEx.DEF_ITEMDATA) #对列表要用deepcopy来赋值,防止列表变量默认是同内存# for Qhrow in range(QhrowNum):# Qhitem_onerow=[['STR','',0,'0,0','',None,None]]# Qhitem_onerow.clear()# for Qhcol in range(self.curColCount):# self.Qhitem_one[0]=str('STR') # 数据类型 # self.Qhitem_one[1]=str(Qhrow) # 数据值# self.Qhitem_one[3]=str("{},{}".format(Qhrow,Qhcol)) # 数据索引 映射的时候更新# self.Qhitem_one[4]=str('') # 对象名# Qhitem_onerow.append(copy.deepcopy(self.Qhitem_one))# self.QhitemData.append(copy.deepcopy(Qhitem_onerow)) self.setColumnCount(self.curColCount) #设置表格列数 self.QhsetColumnWidth() # 设置列宽 此方法不能重写 否则报错 QhupdateFrozenTableGeometry 有调用原本列宽self.QhinitTable() # 表格设置self.QhFreezeTableWidget() # 初始化冻结列的表格self.setRowCount(self.curRowCount) # 设置表格行数 重写逻辑放冻结表初始化后self.setAlternatingRowColors(True) # 设置交替行颜色 重写逻辑放冻结表初始化后self.setHorizontalHeaderLabels(self.QhlstHead) # 设置行表头字段名 重写逻辑放冻结表初始化后self.QhsetSectionResizeModeLis() # 设置列宽不可编辑 涉及冻结表逻辑放冻结表初始化后# 隐藏表格的垂直表头(通常是行号)。self.verticalHeader().hide() # 隐藏表格的垂直表头(通常是行号)。# self.QhFreeTest() # 冻结表测试#对表格进一步初始化def QhinitTable(self):# 此方法主要是对表格样式进项设置 可拓展# 阙辉# self.setTableHeader(QFrame.Box,QFrame.Sunken,'red','greenyellow') #设置表格头内容和样式# self.setTableHeader(QFrame.Box,QFrame.Sunken,'black','white') # self.setAlternatingRowColors(bAlRow) # 交替行颜色#self.setTableData() #设置表格初始化数据:在主窗体中调用self.alignFlags=Qt.AlignVCenter | Qt.AlignHCenter # self.bkCol=QColor(255,255,255) #如设置不透明时的标签背景颜色# self.setFont(font)# palette = QPalette()# self.fontCol=fcolor #字体颜色# palette.setColor(QPalette.WindowText, self.fontCol) #设置字体颜色# self.setPalette(palette)# header = self.horizontalHeader()# header.setSectionResizeMode(QHeaderView.Fixed)print(2)def QhFreezeTableWidget(self):# 初始化冻结列的表格 if self.QhFreeCol==0:return# 初始化冻结列的表格self.QhfreezeTableWidget = QTableWidget(self)self.QhfreezeTableWidget.setColumnCount(self.QhFreeCol) # 假设我们要冻结第一列# self.QhfreezeTableWidget.setRowCount(100) # 假设我们要冻结第一列# self.QhfreezeTableWidget.setHorizontalHeaderLabels(['Frozen Column'])# 将表格的选择模式设置为 QTableWidget.NoSelection,这意味着用户无法在表格中进行选择操作。self.QhfreezeTableWidget.setSelectionMode(QTableWidget.NoSelection)# 设置表格的焦点策略为 Qt.NoFocus,这意味着表格控件不会接收键盘焦点。self.QhfreezeTableWidget.setFocusPolicy(Qt.NoFocus)# 隐藏表格的垂直表头(通常是行号)。self.QhfreezeTableWidget.verticalHeader().hide()# 设置表格的垂直滚动条策略为 Qt.ScrollBarAlwaysOff,这意味着无论内容是否超出可视区域,垂直滚动条都不会显示。self.QhfreezeTableWidget.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)self.QhfreezeTableWidget.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)# 设置表格的样式,保留原有样式,增加右边框 冻结分割线QhFreeTabOldStyle = self.QhfreezeTableWidget.styleSheet()QhFreeTabStyle = str("QTableWidget { border-top: none; border-bottom: none; border-left: none; border-right: 2px solid black;}")QhFreeTabNewStyle = str(QhFreeTabOldStyle) + "\n" + QhFreeTabStyleself.QhfreezeTableWidget.setStyleSheet(QhFreeTabNewStyle)# 连接表格列宽度变化事件,更新冻结表格的列宽度self.horizontalHeader().sectionResized.connect(self.QhupdateSectionWidth)self.QhfreezeTableWidget.horizontalHeader().sectionResized.connect(self.QhupdateFuSectionWidth)self.verticalHeader().sectionResized.connect(self.QhupdateSectionHeight)# 连接滚动条事件,使两个表格同步滚动self.verticalScrollBar().valueChanged.connect(self.QhfreezeTableWidget.verticalScrollBar().setValue)self.horizontalScrollBar().valueChanged.connect(self.QhfreezeTableWidget.horizontalScrollBar().setValue)self.QhfreezeTableWidget.verticalScrollBar().valueChanged.connect(self.verticalScrollBar().setValue)self.verticalScrollBar().valueChanged.connect(self.QhfreezeTableWidget.verticalScrollBar().setValue)# self.itemSelectionChanged.connect(self.QhfreezeTableWidget.on_item_selection_changed)self.viewport().stackUnder(self.QhfreezeTableWidget)self.QhupdateFrozenTableGeometry()def QhFreeTest(self):# 测试冻结列添加数据for row in range(self.curRowCount):for i in range(self.QhFreeCol):item_text = "{}{}".format(str(row), str(i))item = QTableWidgetItem(item_text) self.QhfreezeTableWidget.setItem(row, i, item)# def on_item_selection_changed(self):# # 获取选中行的索引# selected_rows = self.selectedIndexes()# if not selected_rows:# return# # 假设我们只处理第一列被选中的情况,即整行被选中# selected_row = selected_rows[0].row()# # 获取选中行的数据# for col in range(self.tableWidget1.columnCount()):# item = self.item(selected_row, col)# if item:# # 将数据复制到第二个表格中对应的位置# self.tableWidget2.setItem(selected_row, col, QTableWidgetItem(item.text()))def QhupdateFrozenTableGeometry(self):# 更新冻结表格的几何结构 超级重要# 表格宽度# 阙辉Qhfreewidth = 0for Qhi in range(self.QhFreeCol):Qhfreewidth += self.columnWidth(Qhi)self.QhfreezeTableWidget.setColumnWidth(Qhi,self.columnWidth(Qhi))self.QhfreezeTableWidget.setGeometry(self.verticalHeader().width() + self.frameWidth(), # X 坐标self.frameWidth(), # Y 坐标Qhfreewidth, # 宽度self.viewport().height() + self.horizontalHeader().height() # 高度)def resizeEvent(self, event):# 冻结列 逻辑重写 # 当表格大小发生变化时,更新冻结表格的位置和大小# 阙辉if self.QhFreeCol > 0:self.QhupdateFrozenTableGeometry()super().resizeEvent(event)def setAlternatingRowColors(self,QhIsSet=False):# 冻结列 逻辑重写 # 设置表格的交替行颜色# 阙辉if not QhIsSet:returnif self.QhFreeCol > 0: self.QhfreezeTableWidget.setAlternatingRowColors(QhIsSet)super().setAlternatingRowColors(QhIsSet)def setHorizontalHeaderLabels(self, QhFliedLs):if self.QhFreeCol > 0:QhFliedFreeLs = QhFliedLs[:self.QhFreeCol]self.QhfreezeTableWidget.setHorizontalHeaderLabels(QhFliedFreeLs)super().setHorizontalHeaderLabels(QhFliedLs)def setRowCount(self,QhRowCount):# 冻结列 逻辑重写 # 设置表格的行数# 阙辉if self.QhFreeCol > 0: self.QhfreezeTableWidget.setRowCount(QhRowCount)super().setRowCount(QhRowCount)# def setColumnWidth(self,QhCol,QhWidth): # # 冻结列 逻辑重写 此方法不能重写 否则报错 QhupdateFrozenTableGeometry 有调用原本列宽# # 设置列宽 阙辉# if self.QhFreeCol > 0: self.QhfreezeTableWidget.setColumnWidth(QhCol,QhWidth)# super().setColumnWidth(QhCol,QhWidth)def setRowHeight(self,QhCol,QhWidth): # 冻结列 逻辑重写 此方法不能重写 否则报错 QhupdateFrozenTableGeometry 有调用原本列宽# 设置列宽 阙辉if self.QhFreeCol > 0: self.QhfreezeTableWidget.setRowHeight(QhCol,QhWidth)super().setRowHeight(QhCol,QhWidth)def insertRow(self, Qhrow):# 冻结列 逻辑重写 # 插入行 阙辉if self.QhFreeCol > 0:self.QhfreezeTableWidget.insertRow(Qhrow)super().insertRow(Qhrow)def QhGetitem(self, Qhrow, Qhcolumn):# 冻结列 逻辑重写 # 获取指定行和列的单元格对象 阙辉if Qhcolumn < self.QhFreeCol and self.QhFreeCol> 0:# print("bbb",self.QhfreezeTableWidget.item(0, 2))return self.QhfreezeTableWidget.item(Qhrow, Qhcolumn)else:# print("gg",super().item(0, 5))return self.item(Qhrow, Qhcolumn)def setItem(self, Qhrow, Qhcolumn, Qhitem):# 冻结列 逻辑重写 # 设置指定行和列的单元格 阙辉if self.QhFreeCol > 0 and Qhcolumn < self.QhFreeCol:self.QhfreezeTableWidget.setItem(Qhrow, Qhcolumn, Qhitem)else:super().setItem(Qhrow, Qhcolumn, Qhitem)def setCellWidget(self, Qhrow, Qhcolumn, Qhwightobj):# 冻结列 逻辑重写 # 设置指定行和列的对象 阙辉if self.QhFreeCol > 0 and Qhcolumn < self.QhFreeCol:self.QhfreezeTableWidget.setCellWidget(Qhrow, Qhcolumn, Qhwightobj)else:super().setCellWidget(Qhrow, Qhcolumn, Qhwightobj)def removeCellWidget(self, Qhrow, Qhcolumn):# 冻结列 逻辑重写 # 移除指定行和列的对象 阙辉if self.QhFreeCol > 0 and Qhcolumn < self.QhFreeCol:self.QhfreezeTableWidget.removeCellWidget(Qhrow, Qhcolumn)else:super().removeCellWidget(Qhrow, Qhcolumn)# def QhGetCheckBoxflag(self):# # 冻结列 逻辑重写 # # 获取复选框状态 阙辉# if self.QhFreeCol > 0 and Qhcolumn < self.QhFreeCol:# self.QhfreezeTableWidget.setCellWidget(Qhrow, Qhcolumn, Qhwightobj)# else:# super().setCellWidget(Qhrow, Qhcolumn, Qhwightobj)def verticalScrollbarValueChanged(self, value):self.verticalScrollBar().setValue(value)self.scrollbar_value.emit(value)def QhupdateSectionWidth(self, logicalIndex, oldSize, newSize):# 冻结列 逻辑重写if self.QhFreeCol == 0: returnif logicalIndex <= self.QhFreeCol:self.QhfreezeTableWidget.setColumnWidth(logicalIndex, newSize)self.QhupdateFrozenTableGeometry()def QhupdateFuSectionWidth(self, logicalIndex, oldSize, newSize):if self.QhFreeCol == 0: returnsuper().setColumnWidth(logicalIndex, newSize)self.QhupdateFrozenTableGeometry()def QhupdateSectionHeight(self, logicalIndex, oldSize, newSize):if self.QhFreeCol == 0: returnself.QhfreezeTableWidget.setRowHeight(logicalIndex, newSize)def QhsetSectionResizeModeLis(self):# 冻结列 逻辑重写 # 有冻结列时重合冻结表和原表重合列必须设置不可编辑 此限制已被攻破# 设置列不可编辑 阙辉if len(self.QhIsResizeLs) == 0 and self.QhFreeCol == 0 : returnself.Qhheader = self.horizontalHeader()if self.QhFreeCol > 0:self.QhFreeheader = self.QhfreezeTableWidget.horizontalHeader()# if self.QhFreeCol > 0:# self.QhFreeheader = self.QhfreezeTableWidget.horizontalHeader()# for Qhi in range(self.QhFreeCol):# self.QhFreeheader.setSectionResizeMode(Qhi, QHeaderView.Fixed) # 冻结表设置不可编辑该列宽度# self.Qhheader.setSectionResizeMode(Qhi, QHeaderView.Fixed) # 原表格设置不可编辑该列宽度for QhRow in self.QhIsResizeLs:col = QhRow[0] QhIsResize = QhRow[1]if QhIsResize == 1:if col < self.QhFreeCol:self.QhFreeheader.setSectionResizeMode(col, QHeaderView.Fixed) # 冻结表设置不可编辑该列宽度self.Qhheader.setSectionResizeMode(col, QHeaderView.Fixed) # 原表格设置不可编辑该列宽度def QhsetColumnWidth(self):# 冻结列 逻辑重写 # 设置列宽 阙辉if len(self.QhColwidthLs) == 0 : returnfor QhRow in self.QhColwidthLs:col = QhRow[0]QhWidth = int(QhRow[1])if QhWidth == 0: QhWidth = 120 # 默认宽度self.setColumnWidth(col,QhWidth)#得到类字典指定key的值 def getDicKeyValue(self,keyID,defvalue=None):lst_item = QhQTableWidgetEx.dic_TableItemData.get(keyID,defvalue) #用get函数来得到对应字典key的值,如果没有,得到默认值,防报错return lst_itemdef QhsetItemData(self,Qhrow,Qhcol,QhlstItemData):# self.QhitemData # QhbNew 如果为True 则表格置空 绑定数据还在if(Qhrow>self.curRowCount-1 or Qhrow<0 and Qhcol>self.curColCount and Qhcol<0) : print('行或列号有误')return# if not QhbNew:lstOrdData=copy.deepcopy(self.QhitemData[Qhrow][Qhcol]) #原始表格数据,设置后,后替换原单元格数据self.QhitemData[Qhrow][Qhcol]=copy.deepcopy(QhlstItemData)Qhtypestr=QhlstItemData[0].upper() # 数据类型大写Qhitemtext=QhlstItemData[1] # 数据值QhdicID=QhlstItemData[2] # 数据绑定IDself.removeCellWidget(Qhrow,Qhcol) # 移除原位置上的单元格控件 逻辑重写self.QhclearCell(Qhrow,Qhcol) # 此函数会清空绑定数据列表中的内容, 有重合功能 待验证self.QhitemData[Qhrow][Qhcol][0] = Qhtypestr # 需对绑定的数据重新赋值 数据类型self.QhitemData[Qhrow][Qhcol][1] = Qhitemtext # 需对绑定的数据重新赋值 数据值 self.QhitemData[Qhrow][Qhcol][3] = "{},{}".format(Qhrow,Qhcol) # 需对绑定的数据重新赋值 数据索引if(Qhtypestr==None or Qhtypestr.upper()=='NONE' or Qhtypestr=="INT" or Qhtypestr=="FLOAT" or Qhtypestr=="STR" or Qhtypestr=="DATE"):Qhitem = QTableWidgetItem(str(Qhitemtext))self.setItem(Qhrow,Qhcol,Qhitem) #!!!!重要:必须用此行代码才真正初始化了非控件类的单元格,否则单元格可以录入数据,但实际值为Noneelse: #是控件类的单元格时# 用于让控件居中Qhwidget = QWidget()Qhlayout = QHBoxLayout(Qhwidget)Qhlayout.setContentsMargins(1, 1, 1, 1)Qhlayout.setAlignment(Qt.AlignCenter)self.setItem(Qhrow,Qhcol,None) #对控件类单元格,因控件覆盖在单元格上,应将原单元格设置为None,防止单元格有内容时同控件显示重叠if Qhtypestr=="OWNQLINEEDIT" or Qhtypestr=="QLINEEDIT": #自定义编辑框控件,用掩码显示内容Qhlineedit=OwnQLineEdit(self,'') #当前定义的是默认字符串类型:QhitemobjName = "{}_{}_{}".format(Qhtypestr,Qhrow,Qhcol) # 按钮对象名称 记录按钮索引坐标Qhlineedit.setObjectName(QhitemobjName)self.QhitemData[Qhrow][Qhcol][4]=QhitemobjName # 需对绑定的数据重新赋值 数据对象名 if(QhdicID==4 or QhdicID==5): #只有指定的值才表示是有掩码的编辑框mskstr = self.getDicKeyValue(QhdicID) #从字典中得到掩码字串Qhlineedit.setEditMask(mskstr)Qhlayout.addWidget(Qhlineedit)self.setCellWidget(Qhrow,Qhcol,Qhwidget) # if not QhbNew: Qhlineedit.setText(Qhitemtext) elif Qhtypestr=="MUSTR" or Qhtypestr=="QTEXTEDIT": #对多行文本,要支持多行文本Qhtextedit=OwnQTextEdit(Qhitemtext)QhitemobjName = "{}_{}_{}".format(Qhtypestr,Qhrow,Qhcol) # 按钮对象名称 记录按钮索引坐标Qhtextedit.setObjectName(QhitemobjName)self.QhitemData[Qhrow][Qhcol][4]=QhitemobjName # 需对绑定的数据重新赋值 数据对象名 self.QhitemData[Qhrow][Qhcol][4]=QhitemobjNameQhlayout.addWidget(Qhtextedit)self.setCellWidget(Qhrow,Qhcol,Qhwidget)# if not QhbNew:Qhtextedit.setText(Qhitemtext)elif Qhtypestr=="QCHECKBOX" : #复选框控件Qhcheckbox = QCheckBox(Qhitemtext) #创建按纽并设置文本QhitemobjName = "{}_{}_{}".format(Qhtypestr,Qhrow,Qhcol) # 按钮对象名称 记录按钮索引坐标Qhcheckbox.setObjectName(QhitemobjName)# self.all_header0_chkbox.append(checkbox) #以支持在列表头点击复选框时可全选行头的复选框self.QhitemData[Qhrow][Qhcol][4]=QhitemobjNameQhcheckbox.clicked.connect(lambda state, Qhcheckbox=Qhcheckbox: self.checkbox_clicked0(Qhcheckbox)) # 连接信号槽Qhlayout.addWidget(Qhcheckbox)self.setCellWidget(Qhrow,Qhcol,Qhwidget) # 将按纽添加到表格的单元格中if Qhcol == 0: if Qhrow == 0: # 初始化全选复选框列表self.QhCheckBoxList = []self.QhCheckBoxList.append(Qhcheckbox) #以支持在列表头点击复选框时可全选行头的复选框 仅限于第一列elif Qhtypestr=="QCOMBOBOX" : #组合框控件QhcomboBox = QComboBox() QhitemobjName = "{}_{}_{}".format(Qhtypestr,Qhrow,Qhcol) # 按钮对象名称 记录按钮索引坐标QhcomboBox.setObjectName(QhitemobjName) self.QhitemData[Qhrow][Qhcol][4]=QhitemobjName # 需对绑定的数据重新赋值 数据对象名 Qhlst = self.getDicKeyValue(QhdicID)self.setComboBoxItem(QhcomboBox,Qhlst)Qhlayout.addWidget(QhcomboBox)self.setCellWidget(Qhrow,Qhcol,Qhwidget)QhcomboBox.setCurrentIndex(-1)elif Qhtypestr=="QLABEL" : # 自定义标签控件Qhlabel = QLabelEx(self,Qhitemtext) #定义标签控件QhitemobjName = "{}_{}_{}".format(Qhtypestr,Qhrow,Qhcol) # 按钮对象名称 记录按钮索引坐标Qhlabel.setObjectName(QhitemobjName) self.QhitemData[Qhrow][Qhcol][4]=QhitemobjName # 需对绑定的数据重新赋值 数据对象名 # Qhlayout.setContentsMargins(3, 3, 3, 3)Qhlayout.addWidget(Qhlabel)Qhlabel.signal_Leftclicked.connect(lambda state, Qhlabel=Qhlabel: self.label_clicked(Qhlabel))self.setCellWidget(Qhrow,Qhcol,Qhwidget) # 连接信号槽:因原生标签没有单位信号,用继承标签类elif Qhtypestr=="QPUSHBUTTON" : # 按纽控件 # 按钮添加到表格的单元格中Qhlayout.setContentsMargins(3, 3, 3, 3)Qhitem = QTableWidgetItem()if isinstance(Qhitemtext, list):# 多个按钮# ['QPUSHBUTTON',["执行","修改"],0,'0,0',['ZHIXING','XIUGAI'],None,None]Qhitemtextl = ""for Qhi,QhRow in enumerate(Qhitemtext):QhitemtextRow = QhRowif(Qhrow%2 == 0):Qhbutton = QhQPushButton01(QhitemtextRow) # 创建按纽并设置文本else:Qhbutton = QhQPushButton02(QhitemtextRow) # 创建按纽并设置文本QhitemobjNamels = copy.deepcopy(QhlstItemData[4][Qhi]) # 按钮class对象名称 QhitemobjName = "{}+{}_{}_{}".format(Qhtypestr,QhitemobjNamels,Qhrow,Qhcol) # 按钮对象名称 记录按钮索引坐标Qhbutton.setObjectName(QhitemobjName) self.QhitemData[Qhrow][Qhcol][4][Qhi]=QhitemobjNameQhbutton.clicked.connect(lambda state, Qhbutton=Qhbutton: self.button_clicked(Qhbutton)) # 连接信号槽Qhbutton.setMinimumSize(68, 22)Qhlayout.addWidget(Qhbutton)if Qhi == 0:Qhitemtextl = QhitemtextRowelse:Qhitemtextl = Qhitemtextl + "," + QhitemtextRowQhitem.setToolTip(Qhitemtextl)else:# 单个按钮 # ['QPUSHBUTTON',"执行",0,'0,0','ZHIXING',None,None]if(Qhrow%2 == 0):Qhbutton = QhQPushButton01(Qhitemtext) # 创建按纽并设置文本else:Qhbutton = QhQPushButton02(Qhitemtext) # 创建按纽并设置文本QhitemobjNamels = copy.deepcopy(QhlstItemData[4]) # 按钮class对象名称QhitemobjName = "{}+{}_{}_{}".format(Qhtypestr,QhitemobjNamels,Qhrow,Qhcol) # 按钮对象名称 记录按钮索引坐标Qhbutton.setObjectName(QhitemobjName) self.QhitemData[Qhrow][Qhcol][4]=QhitemobjName # 需对绑定的数据重新赋值 数据对象名 Qhbutton.clicked.connect(lambda state, Qhbutton=Qhbutton: self.button_clicked(Qhbutton)) # 连接信号槽Qhbutton.setMinimumSize(68, 22)Qhlayout.addWidget(Qhbutton)Qhitem.setToolTip(Qhitemtext)self.setCellWidget(Qhrow,Qhcol, Qhwidget) # 将按纽添加到表格的单元格中else: #如控件有错,还是建立标准默认的单元格Qhitem = QTableWidgetItem(Qhitemtext) #默认简化单行文本self.setItem(Qhrow,Qhcol,Qhitem)#标签控件槽函数def label_clicked(self, label):print(f'单击的标签控件: {label.text}') #按纽控件槽函数def button_clicked(self, button):print(f'单击的按纽控件: {button.objectName()}') # print(f'单击的按纽控件 坐标: {(button.objectName().split('_')[-2:])}') def checkbox_clicked0(self, button):# 单选方法# 作者 : 阙辉if button.isChecked():button.setChecked(True) else:button.setChecked(False)print(f'QhNEW单击的复合框控件: {button.objectName()}') #复选按纽控件槽函数def checkbox_clicked(self, button):if self.QhCheckBoxflag:col = 0row = int(self.curRowCount)self.QhSetCheckBoxQuanQuXiao(row,col)button.setChecked(True) # obj=self.findChild(QPushButton,str("pushButton_2"))# obj.setText("全选中") else:print(button.isChecked())if button.isChecked():button.setChecked(True) else:button.setChecked(False)print(f'单击的复合框控件: {button.objectName()}') # print(f'单击的复合框控件 坐标: {(button.objectName().split('_')[-2:])}') def QhclearCell(self, row, col):# 冻结列 逻辑重写 # 清除单元格内容 阙辉if(row>0 and row< (self.curRowCount-1) and col>0 and col< (self.curColCount-1)):item = self.QhGetitem(row, col) # 清除指定行列的单元格内容if(item is not None): item.setText('') #非控件单元格不作移除,但要删除内容self.QhitemData[row][col][1]='' #同时清除绑定的数据列表数据self.QhitemData[row][col][0]='STR' self.removeCellWidget(row,col) #移除原位置上的单元格控件def QhAddAllRow(self,QhRow,QhRowItemData):self.resizeRowToContents(QhRow)for QhI,QhRow01 in enumerate(QhRowItemData):QhItemDataone = copy.deepcopy(QhRow01)self.QhsetItemData(QhRow,QhI,QhItemDataone)#在表格末尾增加一行数据def QhAppendItemRow(self,QhRowItemData):# lstItems=self.getRowItems(self.curRowCount-1) #得到最后一行的数据# self.insertRow(self.curRowCount)self.QhitemData.append(copy.deepcopy(QhRowItemData))self.curRowCount+=1QhRow = self.curRowCount-1self.insertRow(QhRow) #增加一行self.QhAddAllRow(QhRow,QhRowItemData)# self.itemData.append(copy.deepcopy(lstItems))# self.setOneRowTableData(self.curRowCount-1) #刷新最后一行数据显示def setComboBoxItem(self,comboObj,lstItem):comboObj.clear()for item in lstItem:comboObj.addItem(item)def QhSetCheckBoxQuanXuan(self,row,col):for i in range(row):# print(i)QhObjName = self.QhitemData[i][col][4]obj=self.findChild(QCheckBox,str(QhObjName))obj.setChecked(True) self.QhCheckBoxflag = Truedef QhSetCheckBoxQuanQuXiao(self,row,col):for i in range(row):QhObjName = self.QhitemData[i][col][4]obj=self.findChild(QCheckBox,str(QhObjName))obj.setChecked(False) self.QhCheckBoxflag = Falsedef QhSetCheckBoxTF(self):print("QhSetCheckBoxTF")col = 0row = int(self.curRowCount)print(row)# for i in range(row):# print(i)# QhObjName = self.QhitemData[i][col][4]# obj=self.findChild(QCheckBox,str(QhObjName))# obj.setChecked(True) if not self.QhCheckBoxflag:self.QhSetCheckBoxQuanXuan(row,col)# obj=self.findChild(QPushButton,str("pushButton_2"))# print(obj)# obj.setText("全取消")else:self.QhSetCheckBoxQuanQuXiao(row,col)# obj=self.findChild(QPushButton,str("pushButton_2"))# obj.setText("全选中")def QhSelectCheckBoxTF(self):# 全选和取消算法,瞬间响应,不需等待所有复选框都选中或取消# 作者:阙辉# 真 if 条件 else 假print(len(self.QhCheckBoxList))QhCheckBoxFList = [1 if QhRow.isChecked() else 0 for QhRow in self.QhCheckBoxList]if 0 in QhCheckBoxFList:[QhRow.setChecked(True) for QhRow in self.QhCheckBoxList]else:[QhRow.setChecked(False) for QhRow in self.QhCheckBoxList]#自定义格式的编辑框控件,可用为自定义的表格单元格
class OwnQLineEdit(QLineEdit):def __init__(self,parent,txtType='',font=QFont('宋体', 11),fcolor=QColor(0,0,0)): super(QLineEdit, self).__init__(parent)self.txtType=txtType.upper() #编辑框的文本类型:'INT'=整型 'FLOAT'=浮点数,'DATE'=日期,'TIME'=时间,'PASSWORD'=密码self.setFrame(QFrame.NoFrame)self.setEditMask(txtType)#设置文本框的掩码类型 def setEditMask(self,txtType=''):if(len(txtType)>0):self.styleTxt=txtTypeif(self.txtType=='INT'):styleTxt='999999999999;#'elif(self.txtType=='FLOAT'):styleTxt='99999999.999'elif(self.txtType=='DATE'):styleTxt='9999-99-99'elif(self.txtType=='TIME'):styleTxt='99:99:99'elif(self.txtType=='PASSWORD'):self.setEchoMode(QLineEdit.Password) returnelse:self.setInputMask(txtType) #自定义格式的编辑框控件,可用为自定义的表格单元格
class OwnQTextEdit(QTextEdit):def __init__(self,parent,txtType='',font=QFont('宋体', 11),fcolor=QColor(0,0,0)): super(QTextEdit, self).__init__(parent)self.txtType=txtType.upper() #编辑框的文本类型:'INT'=整型 'FLOAT'=浮点数,'DATE'=日期,'TIME'=时间,'PASSWORD'=密码self.setFrameShape(QFrame.NoFrame)#重载标签类,标签可透明显示图像,用于在窗体上加载小分部图像
lst_ImgExName=['BMP','JPG','JPEG','PNG','TIF','TIFF','TGA','WMF','SVG','HEIF','RAW','WEBP']
lst_MovExName=['GIF','AVI','MPEG','MP4','MOV','MKV','WMV','FLV','RMVB','RM','RAM']
lst_AlignType=['TL','TC','TR','CL','CC','CR','DL','DC','DR']
class QLabelEx(QLabel): objcount=0 # signal_Leftclicked = QtCore.pyqtSignal(object) #自定信号,标签被左键单击,传回参数:控件对象本身signal_Rightclicked = QtCore.pyqtSignal(object) #自定信号,标签被右键单击,传回参数:控件对象本身signal_Midclicked = QtCore.pyqtSignal(object) #自定信号,标签被中键单击,传回参数:控件对象本身signal_LeftDropRelease = QtCore.pyqtSignal(object) #自定信号,标签被左键拖动后释放,传回参数:控件对象本身#初始化对角需传递的参数为 父类,创建矩形,内容, 控件透明度 字体 字体颜色 背景颜色 def __init__(self,parent,text='',transt=1.0,font=QFont('宋体', 11),fcolor=QColor(0,0,0)): super(QLabel, self).__init__(parent)self.type='TXT' #标签控件的类型,'TXT'=纯文本标签,‘IMG'=可显示图片标签 'MOV':可播放动画标签#self.setGeometry(x,y,w,h)#self.ctlRect=QRect(x,y,w,h) #控件的矩形区域self.imgRect=QRect() #如果控件加载了图象或视频自身尺寸的矩形区域self.bDrawRect = False #是否在标签控件外边画出矩形框 self.rectCol=QColor(255,0,0) #画矩形边框的颜色self.rectPenWidth=2 #画矩形边框的线宽度self.bChgCtlRect=False #如果self.ctlRect不能满足文字、图象的矩形区域时,是否允许控件变化其矩形来适应文字或图象要求的矩形区域self.move_Flag = False #标签控件是否可以主窗体上拖动:对窗体元素,应设置为Falseself.bZoomImgSize=True #控件的矩形区同图象的矩形区不相符时,是否允许图象或视频自动缩放以适应控件矩形区self.setScaledContents(self.bZoomImgSize) # 设置标签的图片,设置True时图片自适应控件,为False时,只显示控件范围图片self.setAutoFillBackground(False) #不允许自动填充背景底色self.text=text #标签是文本类型时显示的内容self.drawText=text #标签是图片或视频类型时显示的内容self.alignFlags=Qt.AlignTop | Qt.AlignLeft #对齐方式self.bDrawTxt = False #显示图片的同时,是否将self.drawText画到图象上self.fontCol=fcolor #字体颜色self.bkCol=QColor(255,255,255) #如设置不透明时的标签背景颜色self.setFont(font)palette = QPalette()palette.setColor(QPalette.WindowText, self.fontCol) #设置字体颜色self.setPalette(palette)self.SetTransparent(transt) #设置控件的透明度,1=不透明,0=完全透明self.setText(text)self.global_X=self.gobal_Y=0 #标签相对屏幕左上点(0,0)的坐标self.startPoint=QPoint() #鼠标在标签控件上压下开始的坐标点self.endPoint=QPoint() #鼠标在标签控件上压下结束时的坐标点self.mouse_X=self.mouse_Y=0 #鼠标在标签控件上相对标签控件范围的坐标self.origin_x=self.origin_y=0self.globalmouse_X=self.globalmouse_Y=0 #鼠标在标签控件上相对屏幕左上点(0,0)的坐标self.oldPos=QPoint() #移动前标签控件的位置self.curImgfilename=''self.curMovFileName=''self.curData=None #当标签是加载的图片或动画时,将文件同容加载到内存中再显示,避免频繁读写文件self.image=QImage()self.curRotAngle=0.0 #图片当前旋转角度(角度,非弧度,顺时针为正)self.gifSpeed=200 #当前要播放的GIF动画的速度self.drawtxtX=self.drawtxtY=0#如要要不透明的标签,设置标签背景色def setBkCol(self,bkcol=QColor(255,255,255)):self.bkCol=bkcolpalette = QPalette()self.setAutoFillBackground(True) palette.setColor(QPalette.Background, self.bkCol)self.setPalette(palette)#设置标签中的文字/图片/GIF动画对齐方式Qt.AlignLeft:左对齐Qt.AlignRight:右对齐 Qt.AlignTop:顶部对齐Qt.AlignBottom:底部对齐Qt.AlignHCenter:水平居中Qt.AlignVCenter:垂直居中Qt.AlignCenter:同时水平和垂直居中def SetAlign(self,at='TL'): #at=at.upper()self.alignFlags=Qt.AlignTop | Qt.AlignLeftif(at=='TL'): self.alignFlags=Qt.AlignTop | Qt.AlignLeftelif(at=='TC'): self.alignFlags=Qt.AlignTop | Qt.AlignHCenterelif(at=='TR'): self.alignFlags=Qt.AlignTop | Qt.AlignRightelif(at=='CL'): self.alignFlags=Qt.AlignVCenter | Qt.AlignLeftelif(at=='CC'): self.alignFlags=Qt.AlignVCenter | Qt.AlignHCenterelif(at=='CR'): self.alignFlags=Qt.AlignVCenter | Qt.AlignRightelif(at=='DL'): self.alignFlags=Qt.AlignBottom | Qt.AlignLeftelif(at=='DC'): self.alignFlags=Qt.AlignBottom | Qt.AlignHCenterelif(at=='DR'): self.alignFlags=Qt.AlignBottom | Qt.AlignRightelse:self.alignFlags=Qt.AlignVCenter | Qt.AlignLeftself.setAlignment(self.alignFlags)self.setText(self.text) #有时并没有出现对齐效果,只能采用先清除再重加载的方式#旋转控件中的图片一指定的角度:角度为正东向,向顺时针旋转的角度为正,反之为负(非弧度)def RotateImg(self,angle): if(self.type=='IMG' and self.curData!=None):transform = QTransform() transform.rotate(angle) self.image=self.image.transformed(transform); self.setPixmap(QPixmap.fromImage(self.image)) # 显示图片到Qlabel控件if(self.bChgCtlRect): #为真时,旋转后同时调整控件大小self.resize(self.image.width(),self.image.height())#设置标签控件在加载图片时,控件尺寸同图片尺寸不符时,是否允许控件调整自身的矩形区域,以适应1:1的图象显示def ObjToImgSize(self):self.setScaledContents(self.bZoomImgSize) #不允许自适应控件,只1:1显示到控件中,同时调整控件大小if(self.bChgCtlRect): #只有先设置此属性为真时,才允许变化控件尺寸if(self.curData!=None): image= QImage.fromData(self.curData)self.resize(image.width(),image.height()) #用下行后用设置参数中的矩形,用本行就是图片本身的尺寸self.ctlRect=QRect(self.x(),self.y(),self.width(),self.height())#设置标签加载的文件名称,可以是图片也可以是动画GIF或视频def LoadFile(self,filename=''):if(os.path.exists(filename)):file_extension = str(filename.split(".")[-1]).upper()bOK=Falsefor exname in lst_ImgExName:if file_extension == exname:self.type='IMG'bOK=Truebreakfor exname in lst_MovExName:if file_extension == exname:self.type='MOV'bOK=Truebreakif (bOK):with open(filename, 'rb') as f:self.curData = f.read()self.image= QImage.fromData(self.curData) self.curMovFileName=filenameself.RefreshLable()else:print(f'没有找到对应扩展名: {file_extension} 的分类')self.type='TXT'self.ReshowText(self.text)self.ObjToImgSize()else:self.type='TXT'self.ReshowText(self.text)#清除图象,重新显示标签的文本def ReshowText(self,txt):self.text=txtself.clear()self.type='TXT'self.setText(txt)#设置显示图片的同时,画到标签控件上的文本,传入文本为空时,同标签控件初始化时的字符串一致,图形模式下,不调用此函数,默认不会绘出文本def setDrawText(self,txt,x=0,y=0):self.bDrawTxt=Trueif(len(txt)==0):self.drawText=self.textelse:self.drawText=txtself.drawtxtX=xself.drawtxtY=y#重新显示标签(在用了LoadFile后)def RefreshLable(self): #如果图片被调整乱了,且不想要控件尺寸同图片尺寸self.setScaledContents(self.bZoomImgSize) #不允许自适应控件,只1:1显示到控件中,同时调整控件大小if(self.type=='IMG'):self.image= QImage.fromData(self.curData)self.setPixmap(QPixmap.fromImage(self.image)) # 显示图片到Qlabel控件self.imgRect=QRect(self.x(),self.y(),self.image.width(),self.image.height())if(self.bChgCtlRect):self.resize(self.image.width(),self.image.height()) #用下行后用设置参数中的矩形,用本行就是图片本身的尺寸 elif(self.type=='MOV'):self.movie = QMovie(self.curMovFileName)# 将movie应用到label上self.setMovie(self.movie)self.total_frame = self.movie.frameCount()self.gifSpeed=self.movie.speed()#print(f'当前GIF文件=’{self.curMovFileName}‘,总帧数={self.total_frame},默认正常播放速度={self.gifSpeed}')self.set_GifSpeed(self.gifSpeed) #设置播放动画GIF的整速度:方法接受的是每1000毫秒播放的帧数比例,如是1:表示,一秒显示全部帧数,0.5表示一秒显示半数的帧数。self.movie.start()#"""else: #self.type=='TXT'pass #设置播放GIF动画的速度: interval值哦本准备播放GIF的默认播放速度的倍数,如当前GIF默认播放速度为100def set_GifSpeed(self,interval=100.0):self.gifSpeed=intervalif(self.type=='MOV' and self.movie!=None):self.movie.setSpeed(interval) # 设置播放速度#设置标签控件的透明程度:对文字及图片均有效def SetTransparent(self,trans):if trans>1:trans=1elif trans<0:trans=0self.Transparent=transopacity_effect = QGraphicsOpacityEffect(parent=self)opacity_effect.setOpacity(trans) # 设置透明度self.setGraphicsEffect(opacity_effect) # 将透明度效果应用到标签上#self.setWindowOpacity(self.Transparent)#设置本标签对象是在最上方还是在最下方 def setLabelLayer(self,bTop=True):if(bTop):self.raise_()else:self.lower()#设置标签显示的文本的字体def setTextFont(self,fontname='宋体',fontsize=11,bBold=False,bItalic=False,bUnderline=False):font = QFont()font.setFamily(fontname) # 设置字体名称font.setPointSize(fontsize) # 设置字体大小font.setBold(bBold) # 设置字体加粗font.setItalic(False)font.setUnderline(False)self.setFont(font)#设置标签显示的文本的字体def setTextCol(self,fcol=QColor(0,0,0)):self.setStyleSheet(f"QLabel {{ color: {fcol.name()}; }}")#设置标签显示的文本的字体def setTextBkCol(self,bkcol=QColor(255,255,255)):if( not self.bTransparent): #对非透明模式才支持设置标签背景颜色self.setAutoFillBackground(True) # 确保背景自动填充palette = self.palette()palette.setColor(QPalette.Window, bkcol) self.setPalette(palette)#得到标签矩形中心位置 def getObjRect(self):size = self.geometry()self.centerX=size.x()+size.width()/2self.centerY=size.y()+size.height()/2return size.x(),size.y(),size.width(),size.height()#鼠标按下事件重载 def mousePressEvent(self, event): self.startPoint=event.pos()self.oldPos=QPoint(event.globalX(),event.globalY()) # 核心部分: 当鼠标点击是左键 并且 在top控件内点击时候触发 if (event.button() == Qt.LeftButton and self.move_Flag): #and self.top.underMouse():self.setCursor(Qt.OpenHandCursor) #移动时设置成手型光标# 但判断条件满足时候, 把拖动标识位设定为真#self.move_Flag = Trueself.globalmouse_X = event.globalX()self.globalmouse_Y = event.globalY()# 获取窗体当前坐标self.origin_x = self.x()self.origin_y = self.y()#鼠标移动事件重载 def mouseMoveEvent(self, event): # 拖动标识位设定为真时, 进入移动事件if self.move_Flag:# 计算鼠标移动的x,y位移move_x = event.globalX() - self.globalmouse_Xmove_y = event.globalY() - self.globalmouse_Y# 计算窗体更新后的坐标:更新后的坐标 = 原本的坐标 + 鼠标的位移dest_x = self.origin_x + move_xdest_y = self.origin_y + move_y# 移动本标签控件size = self.geometry()self.move(dest_x, dest_y)self.ctlRect=QRect(self.x(),self.y(),self.width(),self.height())self.setLabelLayer(True) #拖动的标签控件角色在最顶端显示# 鼠标左键释放 def mouseReleaseEvent(self, event):self.endPoint=event.pos()newPos=QPoint(event.globalX(),event.globalY()) if (event.button() == Qt.LeftButton and self.move_Flag): self.setCursor(Qt.ArrowCursor) # 设定鼠标为普通状态: 箭头if(self.move_Flag==False): #非对象拖动状态,鼠标在控件区域移动一位置if(abs(self.endPoint.x()-self.startPoint.x())<2 and abs(self.endPoint.y()-self.startPoint.y())<2 ): #判断是否单击if(event.button() == Qt.LeftButton):print('非拖动状态下:是左键单击不是拖动')self.signal_Leftclicked.emit(self)elif(event.button() == Qt.RightButton):print('非拖动状态下:是右键单击不是拖动')self.signal_Rightclicked.emit(self)elif(event.button() == Qt.MidButton):print('非拖动状态下:是中键单击不是拖动')self.signal_Midclicked.emit(self)else:print('非拖动状态下,鼠标在控件上移动了一位置')else: #拖动对象状态,除非一点也没拖动,否则不对单位处理if(abs(self.oldPos.x()-newPos.x())<2 and abs(self.oldPos.y()-newPos.y())<2 ):print('虽是拖动状态但是并没拖动对象')if(event.button() == Qt.LeftButton):print('拖动状态下:是左键单击不是拖动')self.signal_Leftclicked.emit(self)elif(event.button() == Qt.RightButton):print('拖动状态下:是右键单击不是拖动')self.signal_Rightclicked.emit(self)elif(event.button() == Qt.MidButton):print('拖动状态下:是中键单击不是拖动')self.signal_Midclicked.emit(self)else: #拖动对象移动了位置 print('拖动状态下:左键拖动控件移动了位置')self.signal_LeftDropRelease.emit(self)#重载绘图函数:def paintEvent(self, event):if (self.bDrawRect): #标签控件是否绘制边框架self.DrawObjRect(self.rectCol,self.rectPenWidth) #为控件画出外边框if(self.bDrawTxt): #是否在标签控件上画出文本pen = QPen() # 创建画笔对象painter = QPainter(self) # 此QPainter只能在paintEvent中定义,不能定义成类的self成员对象,也不能在其地方(如其他窗口,线程中)定义,否则没有绘画功能显示#绘制pen.setColor(self.fontCol) painter.drawText(self.drawtxtX,self.drawtxtY,self.width(),self.height(),self.alignFlags,self.drawText) return super().paintEvent(event) #调用主窗口的重绘事件,不用不会加载动画只显示第一帖,用了动画加载正常,但又多了一静态图第一帖#画出当前控件的矩形框(用于对象被选择时)def DrawObjRect(self,pencol,penwidth):self.rectCol=pencolself.rectPenWidth=penwidthif(self.bDrawRect):pen = QPen() # 创建画笔对象brush = QBrush() # 创建画刷对象painter = QPainter(self) # 此QPainter只能在paintEvent中定义,不能定义成类的self成员对象,也不能在其地方(如其他窗口,线程中)定义,否则没有绘画功能显示#绘制pen.setColor(pencol) pen.setStyle(Qt.SolidLine) pen.setWidth(penwidth) # 设置画笔宽度painter.setPen(pen) # 设置画笔self.pixmap = QPixmap.fromImage(self.image)#painter.drawPixmap(0, 0, self.pixmap)painter.drawRect(0,0,self.width(),self.height()) class QhQPushButton01(QPushButton):def __init__(self,parent): super(QPushButton, self).__init__(parent)class QhQPushButton02(QPushButton):def __init__(self,parent): super(QPushButton, self).__init__(parent)
相关文章:
pyqt5冻结+分页表
逻辑代码 # -*- coding: utf-8 -*- import sys,time,copy from PyQt5.QtWidgets import QWidget,QApplication, QDesktopWidget,QTableWidgetItem from QhTableWidgetQGN import Ui_QhTableWidgetQGN from PyQt5.QtCore import Qt from PyQt5 import QtCore, QtGui, QtWidgets…...
uniapp中实现APP调用本地通知栏通知、震动、本地提示音或者mp3提醒
要在uniapp中实现APP调用本地通知栏通知、震动和本地提示音或者mp3提醒,你可以使用uni-app提供的原生API和插件来实现。 通知栏通知: 你可以使用uni-app的原生API uni.showToast() 或者 uni.showModal() 来实现通知栏通知的功能。可以在需要发送通知的地…...
JS 数组创建、访问、常用方法
文章目录 创建访问常用属性和相关方法1. length 长度属性2. push() 新增元素 - 末尾添加3. unshift() 新增元素 - 开头添加4. pop() 移除元素 - 末尾删除5. shift() 移除元素 - 开头删除6. concat() 复制数组后新增7. slice() 复制数组8. splice() 增删改9. toString() 转字符串…...
【C++】ceil 和 floor 函数的实现与分析
博客主页: [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 💯前言💯ceil 和 floor 函数的基础介绍1. ceil 函数定义与功能示例代码输出结果功能分析使用场景 2. floor 函数定义与功能示例代码输出结果功能分析使用场景 💯自行实现…...
每天40分玩转Django:Django类视图
Django类视图 一、今日学习内容概述 学习模块重要程度主要内容类视图基础⭐⭐⭐⭐⭐View类、URLconf配置通用视图⭐⭐⭐⭐⭐ListView、DetailView等Mixin机制⭐⭐⭐⭐多重继承、功能组合自定义类视图⭐⭐⭐⭐视图定制、方法重写 二、类视图基础 2.1 基本类视图 # views.py…...
运动控制卡网络通讯的心跳检测之C#上位机编程
本文导读 今天,正运动小助手给大家分享一下如何使用C#上位机编程实现运动控制卡网络通讯的心跳检测功能。 01 ECI2618B硬件介绍 ECI2618B经济型多轴运动控制卡是一款脉冲型、模块化的网络型运动控制卡。控制卡本身最多支持6轴,可扩展至12轴的运动控制…...
秒验简介与下载说明
秒验简介与下载说明 产品概述 秒验是一款帮助开发者实现一键验证功能的产品,从根源上降低企业验证成本, 有效提高拉新转化率,降低因验证带来的流失率,3秒完成手机号验证 SDK信息 下载SDK 下载地址 SDK提供Maven和pod引入两种方…...
Redis中的数据类型
文章目录 前言一、字符串(String)应用场景常用命令 二、哈希(Hash)应用场景常用命令 三、列表(List)应用场景常用命令 四、集合(Set)应用场景常用命令 五、有序集合(Sort…...
esp8266_TFTST7735语音识别UI界面虚拟小助手
文章目录 一 实现思路1 项目简介1.1 项目效果1.2 实现方式 2 项目构成2.1 软硬件环境2.2 完整流程总结(重点整合)(1) 功能逻辑图(2) 接线(3) 使用esp8266控制TFT屏(4)TFT_espI库配置方法(5) TFT_esp库常用代码详解(6)TFT屏显示图片(7) TFT屏显示汉字(8) …...
RTOS 基础知识
**实时操作系统(RTOS, Real-Time Operating System)**是一种专为实时性要求设计的操作系统,具有确定性和高效性。RTOS 的系统架构围绕任务调度、时间管理和资源管理展开,以确保系统能够在规定时间内响应外部事件。以下是RTOS的系统…...
【 thefuck 安装与使用】Linux 终端自动纠错工具:一头GitHub上的“草泥马“ - thefuck,妈妈再也不用担心我打错命令行了!
目录 快速安装使用 . 1.简介 2.安装 3.配置 4.补充 官方盗料参考 快速安装使用 快速安装使用,四步即可: #Ubuntu/Debian系统 sudo apt update sudo apt install python3-dev python3-pip sudo pip3 install thefuck #编辑bashrc配置文件 vim ~/.bashrc…...
在Nginx部署Web应用,如何保障后端API的安全
1. 使用HTTPS和http2.0 参考:Nginx配置HTTP2.0_nginx 支持 2.0-CSDN博客 2. 设置严格的CORS策略 通过add_header指令设置CORS头。 只允许来自https://frontend.yourdomain.com的请求访问API location /api/ {if ($http_origin ~* (https://frontend\.yourdomai…...
vue关闭eslint校验及开启debugger
文章目录 在Vue项目中关闭ESLint检查,可以通过以下几种方式实现:修改package.json文件中的eslintScript,将其设置为空字符串或者直接删除。在项目根目录下创建.eslintrc.js文件,并设置rules为关闭所有规则。如果使用Vue CLI创建的…...
docker mysql5.7安装
一.更改 /etc/docker/daemon.json sudo mkdir -p /etc/dockersudo tee /etc/docker/daemon.json <<-EOF {"registry-mirrors": ["https://do.nark.eu.org","https://dc.j8.work","https://docker.m.daocloud.io","https:/…...
json字符串或者json文件转换成相应的bean,报错“Unrecognized field xxx , not marked as ignorable”
1. 异常描述 将一个json字符串或者json文件转换成相应的bean的时候,报如下错误: 2. 异常分析 bean中某个字段的get和set方法可能不是工具自动生成的,而是自己写的,譬如字段是“sInfo”,本来get方法是应该写成getsI…...
Windows下C++使用SQLite
1、安装 进入SQLite Download Page页面,下载sqlite-dll-win-x86-*.zip、sqlite-amalgamation-*.zip、sqlite-tools-win-x64-*.zip三个包,这三个包里分别包含dll文件和def文件、头文件、exe工具。 使用vs命令行工具生成.lib文件:进入dll和def文…...
依图科技简介
依图科技(YITU Technology)是中国一家全球领先的人工智能(AI)公司,成立于2012年,总部位于上海。公司专注于计算机视觉、语音识别和自然语言处理等核心AI技术,致力于推动AI技术在医疗、安防、金融…...
BiLSTM模型详解及代码复现(源码)
(需要源码请私信或留言) LSTM基础 LSTM (Long Short-Term Memory) 是一种特殊类型的循环神经网络(RNN),旨在解决传统RNN在处理长序列时面临的梯度消失和梯度爆炸问题。其核心创新在于引入了 门控机制 ,包括遗忘门、输入门和输出门,有效控制信息的流动和存储。这种独特的…...
HTMLCSS:超炫丝滑的卡片水波纹效果
这段代码创建了一个卡片,卡片上有三个波动效果,这些波动效果通过 CSS 的keyframes 动画实现,创建了一个旋转的动画效果。这种效果适用于创建动态的视觉效果,例如音乐播放器的封面、动态背景或其他需要动态效果的界面元素。 演示效…...
8086汇编(16位汇编)学习笔记05.asm基础语法和串操作
8086汇编(16位汇编)学习笔记05.asm基础语法和串操作-C/C基础-断点社区-专业的老牌游戏安全技术交流社区 - BpSend.net asm基础语法 1. 环境配置 xp环境配置 1.拷贝masm615到指定目录 2.将masm615目录添加进环境变量 3.在cmd中输入ml,可以识别即配置成功 dosbox…...
【漏洞复现】BIG-IP Next Central Manager OData 注入漏洞(CVE-2024-21793)
免责声明 请勿利用文章内的相关技术从事非法测试,由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,作者不为此承担任何责任。工具来自网络,安全性自测,如有侵权请联系删除。本次测试仅供学习使用,如若非法他用,与平台和本文作…...
Go语言及MongoDB数据库安装配置详解!
Go语言安装 首先讲一下go语言的安装,这部分可直接从官网下载,基本上一键配置的: 官网地址:All releases - The Go Programming Language 选择自己对应系统的安装包,这里官网提供了5种不同的包可自行下载 之后便是默认…...
数据库管理-第275期 Oracle 23ai:画了两张架构图(20241225)
数据库管理275期 2024-12-25 数据库管理-第275期 Oracle 23ai:画了两张架构图(20241225)1 系统管理分片2 用户定义分片总结 数据库管理-第275期 Oracle 23ai:画了两张架构图(20241225) 作者:胖…...
HTML速查
HTML 基本文档 <!DOCTYPE html> <html><head><meta charset"utf-8"><title>文档标题</title></head><body>可见文本...</body> </html>基本标签(Basic Tags) <h1>最大的…...
系统分析师第二版口诀
【绪 数 计 网 库】、【信 工 项 安 规 】、【需 架 设 测 运】、【We 嵌 移 大 微 物 论】(第1章 绪论、第2章 数学与工程基础、第3章 计算机系统、第4章 计算机网络与分布式系统、第5章 数据库系统、第6章 企业信息化、第7章 软件工程、第8章 项目管理、第9章 信息…...
E-commerce .net+React(一)——项目初始化
文章目录 项目地址一、创建.Net环境1.1环境配置1.1.1 使用vscode创建webapi1.1.2 Clean architecture结构创建1.1.3 将创建好结构的项目添加到git里1.1.4 EF Core配置1. 在infrastructure里安装EF所需环境2. 创建Product数据模型3. 创建EF Core的DbContext 数据库上下文4. 创建…...
15 break和continue
while True: content input("请输入你要喷的内容") print("发送给下路",content) #上述的程序如果没有外力干扰:程序会一直进行输入下去 #break:就能让当前这个循环立即进行停止 while True: content input("请输入…...
SwiftUI 入门趣谈:在文本框(TextField)内限制数字的输入
概述 虽然 SwiftUI 本身提供了海量内置的原生视图供我们使用,但对于某些情况我们还需要根据实际需求“量体裁衣、专属定制”。 在日常的撸码场景中,我们有时需要限制文本框(TextField)中数字内容的输入,如何又简单又快…...
JOGL 从入门到精通:开启 Java 3D 图形编程之旅
一、引言 Java 作为一门广泛应用的编程语言,在图形编程领域也有着强大的工具和库。JOGL(Java OpenGL)便是其中之一,它为 Java 开发者提供了访问 OpenGL(Open Graphics Library)功能的接口,使得…...
scrollIntoView() 滚动到元素顶部和底部
scrollIntoView() 是一个 DOM 方法,通常用于将某个元素滚动到视口内(可视区域)。这个方法能够使目标元素在页面上可见,尤其是在有滚动条的容器中。当你调用 scrollIntoView() 时,浏览器会自动滚动页面,直到…...
数据预处理
数据预处理科普指南 一、数据预处理:开启数据价值之门的钥匙 在当今数字化浪潮中,数据被视作蕴含无尽宝藏的富矿。然而,原始数据就如同刚从矿山采出的原石,虽内藏珍贵信息,却混杂着诸多瑕疵,如噪声、缺失…...
关于分布式数据库需要了解的相关知识!!!
成长路上不孤单😊😊😊😊😊😊 【14后😊///计算机爱好者😊///持续分享所学😊///如有需要欢迎收藏转发///😊】 今日分享关于关于分布式数据库方面的相关内容&a…...
IP代理测试要测试哪些方面?
在数据采集的征途上,IP代理是我们的得力助手,它不仅帮助我们高效地收集信息,还能在保护数据安全方面发挥重要作用。但面对众多的IP代理服务,如何知道哪一个才是最适合我们的呢?这就需要我们进行一系列的测试。 速度与…...
【前沿 热点 顶会】AAAI 2025中与目标检测有关的论文
CP-DETR: Concept Prompt Guide DETR Toward Stronger Universal Object Detection(AAAI 2025) 最近关于通用物体检测的研究旨在将语言引入最先进的闭集检测器,然后通过构建大规模(文本区域)数据集进行训练࿰…...
【Unity3D】Jobs、Burst并行计算裁剪Texture3D物体
版本:Unity2019.4.0f1 PackageManager下载Burst插件(1.2.3版本) 利用如下代码,生成一个Texture3D资源,它只能脚本生成,是一个32*32*32的立方体,导出路径记得改下,不然报错。 using UnityEditor; using Uni…...
HTML与数据抓取:GET与POST请求处理流程
请求数据最重要的三个要点 1. 请求URL 请求URL是客户端向服务器发出请求的目标地址。它指定了要访问的资源位置,并且可以包含路径和查询参数。URL不仅决定了请求的目标,还可以传递必要的信息给服务器; 格式:http(s)://域名/路径…...
TCP客户端模拟链接websocket服务端发送消息(二)
兄弟们,我来填坑了,o(╥﹏╥)o o(╥﹏╥)o o(╥﹏╥)o o(╥﹏╥)o o(╥﹏╥)o o(╥﹏╥)o,前几天写了个tcp模拟websocket客户端的以为完成,后面需要发送消息给服务端,以为简单不就是一个发送消息么,这不是一…...
使用Quick 录屏为视频生成二维码
Quick 可以将 录屏视频、截图、录音等生成二维码或链接分享给任何人,通过设置访问权限,仅对允许的访客开放。 首先下载安装Quick客户端,安装完成后打开界面如下 点击 选区录制 ,按住鼠标左键拖动选区待录制区域 释放鼠标左键&…...
harmony数据保存-数据持久化
preference的介绍 preference的使用 数据库 sqlite的使用 可以写sql语句用executsql进行增删改查. 也可以使用提供的接口(insert,delete,update,query)进行增删改查。...
【Spring AI】Spring AI Alibaba的简单使用
提示:文章最后有详细的参考文档。 前提条件 SpringBoot版本为3.x以上JDK为17以上申请api-key,地址:百炼平台 引入依赖 说明:我的springboot版本为3.2.4,spring-ai-alibaba-starter版本为1.0.0-M2.1(对应spring-ai版本…...
redhawk如何看高toggle rate instance
我正在「拾陆楼」和朋友们讨论有趣的话题,你⼀起来吧? 拾陆楼知识星球入口 redhaw...
C语言学习笔记(2)
在学习前,需要有一定的C语言基础。不必很深入,只需要知道函数,头文件,指针,数组等的概念就可以,但并非0基础笔记。 由于写到后面,不好编辑了,决定分成多篇写,请按编号学…...
macos 隐藏、加密磁盘、文件
磁盘加密 打开磁盘工具 点击添加 设置加密参数 设置密码 查看文件 不用的时候右键卸载即可使用的时候装载磁盘,并输入密码即可 修改密码 解密 加密,输入密码即可 禁止开机自动挂载此加密磁盘 如果不禁止自动挂载磁盘,开机后会弹出输入…...
机器学习(二)-简单线性回归
文章目录 1. 简单线性回归理论2. python通过简单线性回归预测房价2.1 预测数据2.2导入标准库2.3 导入数据2.4 划分数据集2.5 导入线性回归模块2.6 对测试集进行预测2.7 计算均方误差 J2.8 计算参数 w0、w12.9 可视化训练集拟合结果2.10 可视化测试集拟合结果2.11 保存模型2.12 …...
TP5 动态渲染多个Layui表格并批量打印所有表格
记录: TP5 动态渲染多个Layui表格每个表格设置有2行表头,并且第一行表头在页面完成后动态渲染显示内容每个表格下面显示统计信息可点击字段排序一次打印页面上的所有表格打印页面上多个table时,让每个table单独一页 后端代码示例: /*** Nod…...
Random模拟概率问题
问题背景: 使用 random.nextInt(100) < 10 这段代码来模拟 10% 的概率,其中: random.nextInt(100) 会生成一个 0 到 99 之间的整数。 如果结果小于 10,则表示触发事件,概率为 10/100 10%。 核心问题:…...
适用于Synology NAS的在线办公套件:ONLYOFFICE安装指南
使用 Synology NAS 上的 ONLYOFFICE 文档,您能在私有云中直接编辑文本文档、电子表格、演示文稿和 PDF,确保工作流程既安全又高效。本指南将分步介绍如何在 Synology 上安装 ONLYOFFICE 文档。 关于 Synology Synology NAS(网络附加存储&…...
Go的defer原理
Go 语言中的 defer 语句用于延迟执行一个函数,直到包含该 defer 语句的函数执行完毕时才执行。defer 主要用于资源清理、文件关闭、解锁互斥锁等操作,以确保这些操作在函数返回前被执行,无论函数是正常返回还是由于错误提前返回。 以下是 de…...
达梦数据库迁移到MySQL字段注释缺失问题处理
目录 1、环境信息 2、问题详情 3、处理方案 3.1、提取备用库字段注释 3.2、生成正式库字段注释 1、环境信息 达梦数据库版本:v8 MySQL数据库版本:5.7.11 正式库:通过DTS迁移后的MySQL数据库 备用库:表结构与正式库一致&#…...
IntelliJ Idea常用快捷键详解
文章目录 IntelliJ Idea常用快捷键详解一、引言二、文本编辑与导航1、文本编辑2、代码折叠与展开 三、运行和调试四、代码编辑1、代码补全 五、重构与优化1、重构 六、使用示例代码注释示例代码补全示例 七、总结 IntelliJ Idea常用快捷键详解 一、引言 在Java开发中ÿ…...