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_n
    print(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, QtWidgets


class 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.translate
        QhTableWidgetQGN.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 Qt


class 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:示例-供表格中的下拉组合框用,选择项列表1
                    2:['选项A','选项B','选项C','选项D'],               #2:示例-供表格中的下拉组合框用,选择项列表2
                    3:['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 = False
        self.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" + QhFreeTabStyle
        self.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 = 0
        for 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:return
        if 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: return
        if logicalIndex <= self.QhFreeCol:
            self.QhfreezeTableWidget.setColumnWidth(logicalIndex, newSize)
            self.QhupdateFrozenTableGeometry()
    
    def QhupdateFuSectionWidth(self, logicalIndex, oldSize, newSize):
        if self.QhFreeCol == 0: return
        super().setColumnWidth(logicalIndex, newSize)
        self.QhupdateFrozenTableGeometry()
 
    def QhupdateSectionHeight(self, logicalIndex, oldSize, newSize):
        if self.QhFreeCol == 0: return
        self.QhfreezeTableWidget.setRowHeight(logicalIndex, newSize)

    def QhsetSectionResizeModeLis(self):
        # 冻结列 逻辑重写 
        # 有冻结列时重合冻结表和原表重合列必须设置不可编辑  此限制已被攻破
        # 设置列不可编辑 阙辉
    
        if len(self.QhIsResizeLs) == 0 and self.QhFreeCol == 0 : return
        self.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 : return
        for 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_item
        
    def 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]              # 数据绑定ID
        self.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)          #!!!!重要:必须用此行代码才真正初始化了非控件类的单元格,否则单元格可以录入数据,但实际值为None
        else: #是控件类的单元格时
            # 用于让控件居中
            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]=QhitemobjName
                Qhlayout.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]=QhitemobjName
                Qhcheckbox.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 = QhRow
                        if(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]=QhitemobjName
                        Qhbutton.clicked.connect(lambda state, Qhbutton=Qhbutton: self.button_clicked(Qhbutton))  # 连接信号槽
                        Qhbutton.setMinimumSize(68, 22)
                        Qhlayout.addWidget(Qhbutton)
                        if Qhi == 0:
                            Qhitemtextl = QhitemtextRow
                        else:
                            Qhitemtextl = Qhitemtextl + "," + QhitemtextRow
                    Qhitem.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 = 0
            row = 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+=1
        QhRow = self.curRowCount-1
        self.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 = True

    def 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 = False

    def QhSetCheckBoxTF(self):
        print("QhSetCheckBoxTF")
        col = 0
        row = 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=txtType
            if(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) 
                return
            else:
                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           #标签控件是否可以主窗体上拖动:对窗体元素,应设置为False
        self.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=0
        self.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=bkcol
        palette = 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.AlignLeft
        if(at=='TL'): self.alignFlags=Qt.AlignTop | Qt.AlignLeft
        elif(at=='TC'): self.alignFlags=Qt.AlignTop | Qt.AlignHCenter
        elif(at=='TR'): self.alignFlags=Qt.AlignTop | Qt.AlignRight
        elif(at=='CL'): self.alignFlags=Qt.AlignVCenter | Qt.AlignLeft
        elif(at=='CC'): self.alignFlags=Qt.AlignVCenter | Qt.AlignHCenter
        elif(at=='CR'): self.alignFlags=Qt.AlignVCenter | Qt.AlignRight
        elif(at=='DL'): self.alignFlags=Qt.AlignBottom | Qt.AlignLeft
        elif(at=='DC'): self.alignFlags=Qt.AlignBottom | Qt.AlignHCenter
        elif(at=='DR'): self.alignFlags=Qt.AlignBottom | Qt.AlignRight
        else:self.alignFlags=Qt.AlignVCenter | Qt.AlignLeft
        self.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=False
            for exname in lst_ImgExName:
                if file_extension == exname:
                    self.type='IMG'
                    bOK=True
                    break
            for exname in lst_MovExName:
                if file_extension == exname:
                    self.type='MOV'
                    bOK=True
                    break
            if (bOK):
                with open(filename, 'rb') as f:
                    self.curData = f.read()
                self.image= QImage.fromData(self.curData)    
                self.curMovFileName=filename
                self.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=txt
        self.clear()
        self.type='TXT'
        self.setText(txt)
    #设置显示图片的同时,画到标签控件上的文本,传入文本为空时,同标签控件初始化时的字符串一致,图形模式下,不调用此函数,默认不会绘出文本
    def setDrawText(self,txt,x=0,y=0):
        self.bDrawTxt=True
        if(len(txt)==0):
            self.drawText=self.text
        else:
            self.drawText=txt
        self.drawtxtX=x
        self.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默认播放速度为100
    def set_GifSpeed(self,interval=100.0):
        self.gifSpeed=interval
        if(self.type=='MOV' and self.movie!=None):
            self.movie.setSpeed(interval)  # 设置播放速度
    #设置标签控件的透明程度:对文字及图片均有效
    def SetTransparent(self,trans):
        if trans>1:trans=1
        elif trans<0:trans=0
        self.Transparent=trans
        opacity_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()/2
        self.centerY=size.y()+size.height()/2
        return 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 = True
            self.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_X
            move_y = event.globalY() - self.globalmouse_Y
            # 计算窗体更新后的坐标:更新后的坐标 = 原本的坐标 + 鼠标的位移
            dest_x = self.origin_x + move_x
            dest_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=pencol
        self.rectPenWidth=penwidth
        if(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)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/943302.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Windows 使用 非安装版MySQL 8

1.下载MySQL 8 https://cdn.mysql.com//Downloads/MySQL-8.0/mysql-8.0.40-winx64.zip 2.创建my.ini 下载解压后&#xff0c;发现根目录没有my.ini文件&#xff0c;需手动创建 my.ini # For advice on how to change settings please see # http://dev.mysql.com/doc/refma…

海外招聘丨 苏黎世联邦理工学院—机器学习在社会和政治科学中的应用博士后

雇主简介 苏黎世联邦理工学院是世界领先的科技大学之一。我们以优质的教育、尖端的基础研究和将新知识直接转化为社会而闻名。来自 120 多个国家的 30,000 多名学生认为我们的大学是一个鼓励独立思考和激励卓越的环境的地方。 我们位于欧洲中心&#xff0c;但与世界各地建立联…

微信小程序中遇到过的问题

记录微信小程序中遇到的问题&#xff08;持续更新ing&#xff09; 问题描述&#xff1a;1. WXML中无法直接调用JavaScript方法。2. css中无法直接引用背景图片。3. 关于右上角胶囊按钮。4. 数据绑定问题。5. 事件处理问题。 问题描述&#xff1a; 1. WXML中无法直接调用JavaSc…

idea 8年使用整理

文章目录 前言idea 8年使用整理1. 覆盖application配置2. 启动的时候设置编辑空间大小&#xff0c;并忽略最大空间3. 查询类的关系4. 查看这个方法的引用关系5. 查看方法的调用关系5.1. 查看被调用关系5.2. 查看调用关系 6. 方法分隔线7. 选择快捷键类型8. 代码预览插件9. JReb…

RAGFLOW使用笔记【更新ing】

0.引言 本文记录使用RAGFLOW的一些问题以及解决办法&#xff0c;它以笔记的形式存在&#xff0c;方便我以后回顾自己的学习工作。 1.RAGFLOW上传文件大小默认是128M,如何修改上传文件大小&#xff1f; 更新ragflow/docker/.env中的MAX_CONTENT_LENGTH 环境变量 然后同步更新…

ubuntu22.04安装PaddleX3

PaddleOCR 安装过程可以参考PaddleX本地安装教程 我的电脑环境配置&#xff1a; ubuntu22.04 cuda11.8&#xff08;之前安装的是12.4没有匹配的paddle-gpu;这里改成11.8&#xff09; 一、安装基础环境 1、 conda create -n ppx1 python3.10 2、 conda activate ppx1 3、…

Android 之 Activity 的启动模式(launchMode)

一、Activity 启动模式 在实际项目中&#xff0c;应该根据项目的实际需要来为每个 Activity 指定恰当的启动模式 launchMode。启动模式一共有四种&#xff0c;分别是 standard、singleTop、singleTask 和 singleInstance。可以在 AndroidManifest.xml 中通过给 <activity&g…

软件老化分析

软件老化 课程&#xff1a;软件质量分析 作业 解答 Python代码如下&#xff1a; n int(input("类别数&#xff1a;")) theta list(map(float, input("各个类别的权重&#xff1a;").split())) m list(map(int, input("各个类别的度量元数量&…

Jenkins 构建流水线

在 Linux 系统上安装 Jenkins 服务&#xff0c;以及配置自动化构建项目 前置准备环境&#xff1a;docker、docker-compose、jdk、maven 一、环境搭建 1. Jenkins 安装 &#xff08;1&#xff09;拉取镜像 # 安装镜像包&#xff0c;默认安装最新版本 docker pull jenkins/jen…

5G学习笔记之Non-Public Network

目录 0. NPN系列 1. 概述 2. SNPN 2.1 SNPN概述 2.2 SNPN架构 2.3 SNPN部署 2.3.1 完全独立 2.3.2 共享PLMN基站 2.3.3 共享PLMN基站和PLMN频谱 3. PNI-NPN 3.1 PNI-NPN概述 3.2 PNI-NPN部署 3.2.1 UPF独立 3.2.2 完全共享 0. NPN系列 1. NPN概述 2. NPN R18 3. 【SNPN系列】S…

若依plus apifox导入接口显示为空

项目已经正常启动 访问接口有些没问题&#xff0c;有些有问题 其他模块都可以正常导入 解决&#xff1a;

elementPlus消息组件多按钮案例

let customClass zsl-el-message-box efb.messageBox({title: 操作提示,showConfirmButton: false,customClass,message: efb.VNode(div, null, [efb.VNode(style, null, .${customClass} .el-message-box__message {width: 100%;}),efb.VNode(div, null, hello world),efb.VN…

计算机网络:应用层 —— 网络应用模式

文章目录 客户—服务器方式和对等方式客户/服务器方式 (C/S方式)工作流程特点 对等方式 (P2P方式)工作流程P2P 应用特点 客户—服务器方式和对等方式 网络应用程序运行在处于网络边缘的不同的端系统上&#xff0c;通过彼此间的通信来共同完成某项任务。 开发一种新的网络应用…

科技创新 数智未来|清科·沙丘投研院走进竹云

12月20日&#xff0c;清科沙丘投研院带领企投家团队走进竹云交流分享&#xff0c;聚焦技术创新、企业数字化管理、行业前沿应用案例等热点议题&#xff0c;深入探讨数字技术如何点燃企业高质量发展的澎湃动力&#xff0c;共话企业数字化、智能化发展之道。 达晨财智股权管理部…

外连接转AntiJoin的应用场景与限制条件 | OceanBase SQL 查询改写系列

在《SQL 改写系列&#xff1a;外连接转内连接的常见场景与错误》一文中&#xff0c;我们了解到谓词条件可以过滤掉连接结果中的 null 情形的&#xff0c;将外连接转化为内连接的做法是可行的&#xff0c;正如图1中路径(a)所示。此时&#xff0c;敏锐的你或许会进一步思考&#…

Java - 日志体系_Apache Commons Logging(JCL)日志接口库

文章目录 官网1. 什么是JCL&#xff1f;2. JCL的主要特点3. JCL的核心组件4. JCL的实现机制5. SimpleLog 简介6. CodeExample 1 &#xff1a; 默认日志实现 (JCL 1.3.2版本)Example 2 &#xff1a; JCL (1.2版本&#xff09; Log4J 【安全风险高&#xff0c;请勿使用】 7. 使用…

mavlink移植到单片机stm32f103c8t6,实现接收和发送数据

前言&#xff1a; 好久没更新博客了&#xff0c;这两个月真的是异常的忙&#xff0c;白天要忙着公司里的事&#xff0c;晚上还要忙着修改小论文&#xff0c;一点自己的时间都没有了&#xff0c;不过确确实实是学到了很多东西&#xff0c;对无人机的技术研究也更深了一些。不过好…

GitLab的安装与卸载

目录 GitLab安装 GitLab使用 使用前可选操作 修改web端口 修改Prometheus端口 使用方法 GitLab的卸载 环境说明 系统版本 CentOS 7.2 x86_64 软件版本 gitlab-ce-10.8.4 GitLab安装 Gitlab的rpm包集成了它需要的软件&#xff0c;简化了安装步骤&#xff0c;所以直接…

子网掩码计算route命令

子网掩码 - 站长工具 1.子网掩码 子网掩码就是用来遮掩IP地址并划分网段的工具&#xff0c;根据遮掩的位数不同来划分不同的网段。 2.网关 网关(Gateway)又称网间连接器、协议转换器。默认网关在网络层上以实现网络互连&#xff0c;是最复杂的网络互连设备&#xff0c;仅用…

基本操作:iframe、alert

背景 如果你的目标元素出现在一个iframe标签下&#xff0c;则不能直接定位&#xff0c;必须先完成切换才能进行定位操作&#xff0c;如下图 整个理解为一个大的房间&#xff0c;里面是客厅&#xff0c;driver进到客厅后&#xff0c;如果想操作iframe A里的数据&#xff0c;需…