目录
效果
代码
使用
PyQt5实现QTableWidget分页,右键菜单自定义设置,集成在一个控件中,方便使用。
效果
代码
分页表格控件代码
import sys,math
from typing import Any,List,Dict
from PyQt5 import QtCore,QtWidgets,QtGui
from PyQt5.QtCore import Qt
# 分页表格控件,单选
class PageTableWidget(QtWidgets.QWidget):
sinout_signal = QtCore.pyqtSignal(object)
def __init__(self):
super().__init__()
self.init_data()
self.init_ui()
pass
def init_data(self):
# 表格全数据 二维数组
self.table_full_data: List[Any] = []
# 表格右键菜单 {菜单名:索引指向}
self.table_right_menus: Dict[str,str] = {}
self.total_page_count: int = 0
self.total_rows_count: int = 0
self.current_page: int = 1
self.single_page_rows: int = 5
pass
def init_ui(self):
pre_page_btn = QtWidgets.QPushButton('上一页')
pre_page_btn.clicked.connect(self.pre_page_btn_clicked)
next_page_btn = QtWidgets.QPushButton('下一页')
next_page_btn.clicked.connect(self.next_page_btn_clicked)
tip_label_0 = QtWidgets.QLabel('第')
self.witch_page_lineedit = QtWidgets.QLineEdit()
self.int_validator = QtGui.QIntValidator()
self.witch_page_lineedit.setValidator(self.int_validator)
self.witch_page_lineedit.setMaximumWidth(20)
tip_label_1 = QtWidgets.QLabel('页')
go_page_btn = QtWidgets.QPushButton('前往')
go_page_btn.clicked.connect(self.go_page_btn_clicked)
layout_witch_page = QtWidgets.QHBoxLayout()
layout_witch_page.addWidget(tip_label_0)
layout_witch_page.addWidget(self.witch_page_lineedit)
layout_witch_page.addWidget(tip_label_1)
layout_witch_page.addWidget(go_page_btn)
layout_witch_page.addStretch(1)
self.total_page_count_label = QtWidgets.QLabel(f"共0页")
self.total_rows_count_label = QtWidgets.QLabel(f"共0行")
self.current_page_label = QtWidgets.QLabel(f"当前第0页")
layout_pagestatus = QtWidgets.QHBoxLayout()
layout_pagestatus.addWidget(self.total_page_count_label)
layout_pagestatus.addWidget(self.total_rows_count_label)
layout_pagestatus.addWidget(self.current_page_label)
layout_top = QtWidgets.QHBoxLayout()
layout_top.addWidget(pre_page_btn)
layout_top.addWidget(next_page_btn)
layout_top.addLayout(layout_witch_page)
layout_top.addLayout(layout_pagestatus)
layout_top.addStretch(1)
self.target_table = QtWidgets.QTableWidget()
self.target_table.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
self.target_table.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
self.target_table.setContextMenuPolicy(Qt.CustomContextMenu)
self.target_table.customContextMenuRequested.connect(self.target_table_rightclicked_menu)
layout = QtWidgets.QVBoxLayout()
layout.addLayout(layout_top)
layout.addWidget(self.target_table)
self.setLayout(layout)
pass
def set_table_init_data(self,data:Dict[str,Any]):
'''设置表头、右键菜单等初始化内容'''
headers:List[str] = data['headers']
self.table_right_menus = data['table_right_menus']
self.target_table.setColumnCount(len(headers))
self.target_table.setHorizontalHeaderLabels(headers)
pass
def set_table_full_data(self,data:Dict[str,str]):
'''表格全数据'''
self.table_full_data = data
self.total_rows_count = len(data)
self.total_page_count = math.ceil(self.total_rows_count/self.single_page_rows)
self.current_page = 1
self.int_validator.setRange(1,self.total_page_count)
self.total_page_count_label.setText(f"共{self.total_page_count}页")
self.total_rows_count_label.setText(f"共{self.total_rows_count}行")
self.caculate_current_show_data()
pass
def setting_current_pagestatus_label(self):
self.current_page_label.setText(f"当前第{self.current_page}页")
pass
def caculate_current_show_data(self):
'''计算当前要显示的数据'''
start_dot = (self.current_page-1)*self.single_page_rows
end_dot = start_dot + self.single_page_rows
current_data = self.table_full_data[start_dot:end_dot]
self.fill_table_content(current_data)
self.setting_current_pagestatus_label()
pass
def fill_table_content(self,data:List[Any]):
self.target_table.clearContents()
self.target_table.setRowCount(len(data))
for r_i,r_v in enumerate(data):
for c_i,c_v in enumerate(r_v):
cell = QtWidgets.QTableWidgetItem(c_v)
self.target_table.setItem(r_i, c_i, cell)
pass
pass
self.target_table.resizeColumnsToContents()
pass
def go_page_btn_clicked(self):
'''前往按钮点击'''
input_page = self.witch_page_lineedit.text()
input_page = input_page.strip()
if not input_page:
QtWidgets.QMessageBox.information(
self,
'提示',
'请输入要跳转的页码',
QtWidgets.QMessageBox.Yes
)
return
input_page = int(input_page)
if input_page<0 or input_page>self.total_page_count:
QtWidgets.QMessageBox.information(
self,
'提示',
'输入的页码超出范围',
QtWidgets.QMessageBox.Yes
)
return
self.current_page = input_page
self.caculate_current_show_data()
pass
def pre_page_btn_clicked(self):
'''上一页按钮点击'''
if self.current_page<=1:
QtWidgets.QMessageBox.information(
self,
'提示',
'已经是首页',
QtWidgets.QMessageBox.Yes
)
return
self.current_page -= 1
self.caculate_current_show_data()
pass
def next_page_btn_clicked(self):
'''下一页按钮点击'''
if self.current_page>=self.total_page_count:
QtWidgets.QMessageBox.information(
self,
'提示',
'已经是最后一页',
QtWidgets.QMessageBox.Yes
)
return
self.current_page += 1
self.caculate_current_show_data()
pass
def target_table_rightclicked_menu(self,pos):
'''表格右键菜单'''
selectedItems = self.target_table.selectedItems()
if len(selectedItems)<=0:
QtWidgets.QMessageBox.information(
self,
'提示',
'请选择要操作的行',
QtWidgets.QMessageBox.Yes
)
return
if not self.table_right_menus:
QtWidgets.QMessageBox.information(
self,
'提示',
'没有右键菜单',
QtWidgets.QMessageBox.Yes
)
return
menu = QtWidgets.QMenu()
menu_item_list = []
for item in self.table_right_menus.keys():
temp_item = menu.addAction(item)
menu_item_list.append(temp_item)
pass
current_action = menu.exec_(self.target_table.mapToGlobal(pos))
for item in menu_item_list:
if item == current_action:
# 发出信号
action_name = item.text()
pre_res_map = {}
pre_res_map['action_name'] = action_name
pre_res_map['action_target'] = self.table_right_menus[action_name]
action_res_data = [i.text() for i in selectedItems]
pre_res_map['action_data'] = action_res_data
self.sinout_signal.emit(pre_res_map)
break
pass
pass
pass
放置分页表格控件的容器
class Example_widget(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.init_ui()
pass
def init_ui(self):
self.setWindowTitle('表格显示示例')
self.table = PageTableWidget()
self.table.sinout_signal.connect(self.table_signal_recive)
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.table)
self.setLayout(layout)
pass
def setting_data(self,data1,data2):
self.table.set_table_init_data(data1)
self.table.set_table_full_data(data2)
pass
def table_signal_recive(self,data:Dict[str,Any]):
print(data)
pass
使用
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
pre_data = {}
pre_data['headers'] = ['编号','姓名','性别','归属']
pre_data['table_right_menus'] = {
'右菜1':'target_11',
'右菜2':'target_22',
'右菜3':'target_33'
}
pre_body_data = [
['000','林黛玉','女','红楼梦'],
['001','孙尚香','女','三国演义'],
['002','孙悟空','男','西游记'],
['003','刘备','男','三国演义'],
['004','宋江','男','水浒传'],
['005','贾宝玉','男','红楼梦'],
['006','关羽','男','三国演义'],
['007','张飞','男','三国演义']
]
t_win = Example_widget()
t_win.setting_data(pre_data,pre_body_data)
t_win.show()
sys.exit(app.exec_())
pass
右键选择菜单点击后,该行的内容会回传到容器控件
控制台输出了容器中接收到的信息
{'action_name': '右菜1', 'action_target': 'target_11', 'action_data': ['002', '孙悟空', '男', '西游记']}



