import sys
from PyQt6.QtCore import Qt, QRect, pyqtSignal
from PyQt6.QtGui import QBrush, QColor
from PyQt6.QtWidgets import QApplication, QMainWindow
from PyQt6.QtWidgets import QHBoxLayout, QLineEdit, QComboBox, QSpacerItem, QSizePolicy
from PyQt6.QtWidgets import QTableWidget, QTableWidgetItem, QCheckBox, QPushButton, QHeaderView, QStyleOptionButton, \
QStyle
from PyQt6.QtWidgets import QWidget, QVBoxLayout
class TopControlBar(QWidget):
"""顶部控制栏组件"""
search_requested = pyqtSignal(str, str, str, str) # 查询信号: name, dept, mentor, status
batch_remind_requested = pyqtSignal() # 批量提醒信号
def __init__(self, parent=None):
super().__init__(parent)
self.init_ui()
self.init_connections()
def init_ui(self):
layout = QHBoxLayout(self)
layout.setSpacing(10)
layout.setContentsMargins(0, 0, 0, 0)
# 名称输入框
self.name_input = QLineEdit()
self.name_input.setPlaceholderText("请输入名称")
self.name_input.setMaximumWidth(100)
# 部门下拉框
self.department_combo = QComboBox()
self.department_combo.addItems(["全部部门", "技术部", "市场部", "财务部", "人力资源部", "行政部"])
self.department_combo.setMaximumWidth(100)
# 导师下拉框
self.mentor_combo = QComboBox()
self.mentor_combo.addItems(["全部导师", "导师A", "导师B", "导师C"])
self.mentor_combo.setMaximumWidth(100)
# 状态下拉框
self.status_combo = QComboBox()
self.status_combo.addItems(["全部状态", "进行中", "已完成", "已过期"])
self.status_combo.setMaximumWidth(100)
# 查询按钮
self.search_button = QPushButton("查询")
self.search_button.setFixedWidth(80)
# 批量提醒按钮
self.batch_remind_button = QPushButton("批量提醒")
self.batch_remind_button.setMaximumWidth(100)
# 添加控件到布局
layout.addWidget(self.name_input)
layout.addWidget(self.department_combo)
layout.addWidget(self.mentor_combo)
layout.addWidget(self.status_combo)
layout.addWidget(self.search_button)
# 添加弹性空间
layout.addSpacerItem(QSpacerItem(
20, 20,
QSizePolicy.Policy.Expanding,
QSizePolicy.Policy.Minimum
))
layout.addWidget(self.batch_remind_button)
def init_connections(self):
"""初始化信号连接"""
self.search_button.clicked.connect(self.emit_search_signal)
self.batch_remind_button.clicked.connect(self.batch_remind_requested.emit)
def emit_search_signal(self):
"""发射查询信号"""
name = self.name_input.text()
dept = self.department_combo.currentText()
mentor = self.mentor_combo.currentText()
status = self.status_combo.currentText()
self.search_requested.emit(name, dept, mentor, status)
def apply_styles(self, input_style, select_style, query_style, notice_style):
"""应用样式表"""
self.name_input.setStyleSheet(input_style)
self.department_combo.setStyleSheet(select_style)
self.mentor_combo.setStyleSheet(select_style)
self.status_combo.setStyleSheet(select_style)
self.search_button.setStyleSheet(query_style)
self.batch_remind_button.setStyleSheet(notice_style)
class CheckBoxHeader(QHeaderView):
"""自定义表头复选框"""
allChecked = pyqtSignal(bool) # 全选信号
def __init__(self, parent=None):
super().__init__(Qt.Orientation.Horizontal, parent)
self.isChecked = False
def paintSection(self, painter, rect, logicalIndex):
if logicalIndex == 0:
option = QStyleOptionButton()
option.rect = QRect(rect.x() + 10, rect.y() + 10, 20, 20)
option.state = QStyle.StateFlag.State_Enabled
if self.isChecked:
option.state |= QStyle.StateFlag.State_On
else:
option.state |= QStyle.StateFlag.State_Off
self.style().drawControl(QStyle.ControlElement.CE_CheckBox, option, painter)
else:
super().paintSection(painter, rect, logicalIndex)
def mousePressEvent(self, event):
if event.pos().x() < 50 and event.pos().y() < 50:
self.isChecked = not self.isChecked
self.updateSection(0)
self.allChecked.emit(self.isChecked) # 发射全选信号
super().mousePressEvent(event)
class DataTable(QTableWidget):
"""数据表格组件"""
row_selected = pyqtSignal(int, bool) # 行选择信号: row_index, is_checked
detail_requested = pyqtSignal(int) # 详情请求信号: row_index
def __init__(self, parent=None):
super().__init__(parent)
self.checkboxes = []
self.init_ui()
def init_ui(self):
self.setColumnCount(9)
self.setHorizontalHeader(CheckBoxHeader(self))
self.setHorizontalHeaderLabels(
["", "姓名", "导师姓名", "部门", "导师邮箱", "第一天", "第一周", "第一月", "操作"])
# 连接表头全选信号
self.horizontalHeader().allChecked.connect(self.update_all_checkboxes)
def update_all_checkboxes(self, checked):
"""更新所有行复选框"""
for i, checkbox in enumerate(self.checkboxes):
checkbox.setChecked(checked)
self.row_selected.emit(i, checked)
def populate_data(self, data):
"""填充表格数据"""
self.setRowCount(len(data))
self.checkboxes = []
for row, emp in enumerate(data):
self.setRowHeight(row, 50)
# 复选框
checkbox = QCheckBox()
checkbox.setFixedSize(15, 15)
checkbox.stateChanged.connect(lambda state, r=row: self.row_selected.emit(r, bool(state)))
self.setCellWidget(row, 0, checkbox)
self.checkboxes.append(checkbox)
# 填充数据
self.setItem(row, 1, QTableWidgetItem(emp["name"]))
self.setItem(row, 2, QTableWidgetItem(emp["account"]))
self.setItem(row, 3, QTableWidgetItem(emp["department"]))
self.setItem(row, 4, QTableWidgetItem(emp["email"]))
# 日期项
item = QTableWidgetItem("07/30")
item.setForeground(QBrush(QColor("#4CAF50")))
self.setItem(row, 5, item)
item = QTableWidgetItem("08/06")
item.setForeground(QBrush(QColor("#F44336")))
self.setItem(row, 6, item)
item = QTableWidgetItem("08/30")
item.setForeground(QBrush(QColor("#9E9E9E")))
self.setItem(row, 7, item)
# 操作按钮
detail_button = QPushButton("查看详情")
detail_button.setMaximumWidth(80)
detail_button.clicked.connect(lambda _, r=row: self.detail_requested.emit(r))
self.setCellWidget(row, 8, detail_button)
def apply_styles(self, table_style):
"""应用表格样式"""
self.setStyleSheet(table_style)
self.horizontalHeader().setStretchLastSection(True)
class MainTableWidget(QWidget):
"""主表格界面组件"""
def __init__(self, parent=None):
super().__init__(parent)
self.top_bar = TopControlBar()
self.data_table = DataTable()
self.init_ui()
self.init_connections()
self.populate_sample_data()
def init_ui(self):
layout = QVBoxLayout(self)
layout.setContentsMargins(0, 0, 0, 0)
# 顶部控制栏
layout.addWidget(self.top_bar)
# 数据表格
layout.addWidget(self.data_table)
def init_connections(self):
"""初始化信号连接"""
# 顶部控制栏信号
self.top_bar.search_requested.connect(self.handle_search)
self.top_bar.batch_remind_requested.connect(self.handle_batch_remind)
# 表格信号
self.data_table.row_selected.connect(self.handle_row_selection)
self.data_table.detail_requested.connect(self.handle_detail_request)
def populate_sample_data(self):
"""填充示例数据"""
employees = [
{"name": "张三", "account": "zhangsan", "department": "技术部", "email": "zhangsan@example.com"},
{"name": "李四", "account": "lisi", "department": "市场部", "email": "lisi@example.com"},
{"name": "王五", "account": "wangwu", "department": "财务部", "email": "wangwu@example.com"},
{"name": "赵六", "account": "zhaoliu", "department": "人力资源部", "email": "zhaoliu@example.com"},
{"name": "孙七", "account": "sunqi", "department": "行政部", "email": "sunqi@example.com"},
]
self.data_table.populate_data(employees)
def handle_search(self, name, dept, mentor, status):
"""处理查询请求"""
print(f"查询条件: 姓名={name}, 部门={dept}, 导师={mentor}, 状态={status}")
# 实现实际的过滤逻辑
def handle_batch_remind(self):
"""处理批量提醒请求"""
print("执行批量提醒操作")
# 实现批量提醒逻辑
def handle_row_selection(self, row, selected):
"""处理行选择事件"""
print(f"行 {row} {'选中' if selected else '取消选中'}")
def handle_detail_request(self, row):
"""处理详情查看请求"""
print(f"查看第 {row} 行详情")
def apply_styles(self):
"""应用所有样式"""
# 定义样式
input_style = """
padding: 8px 12px;
border: 1px solid #e6e6e6;
border-radius: 5px;
font-size: 14px;
"""
select_style = """
QComboBox {
padding: 5px 10px;
border: 1px solid #e6e6e6;
border-radius: 5px;
background-color: white;
min-height: 24px;
font-size: 14px;
}
QComboBox:hover {
border-color: #4CAF50;
}
QComboBox::drop-down {
border: none;
background: transparent;
padding-right: 5px;
}
QComboBox QAbstractItemView {
outline: 0px;
border: 1px solid #e6e6e6;
background-color: white;
font-size: 14px;
}
QComboBox QAbstractItemView::item {
padding: 4px 10px;
}
QComboBox QAbstractItemView::item:selected {
background-color: #f0f0f0;
color: black;
}
QComboBox QAbstractItemView::item:hover {
background-color: #e0e0e0;
}
"""
query_style = """
background-color: #4564a8;
color: white;
border: none;
padding: 10px;
border-radius: 5px;
font-size: 14px;
"""
notice_style = """
background-color: #ffa300;
color: white;
border: none;
padding: 10px;
border-radius: 5px;
font-size: 14px;
"""
table_style = """
QTableWidget {
border: 1px solid #e6e6e6;
border-radius: 2px;
background-color: white;
font-size: 14px;
color: #333;
}
QHeaderView::section {
background-color: #f5f7fa;
color: #333;
padding: 8px;
border: none;
font-weight: bold;
}
QTableWidget::item {
padding: 10px;
border-bottom: 1px solid #f0f0f0;
}
QTableWidget::item:selected {
background-color: #e5ebee;
color: #000;
}
QTableWidget::item:hover {
background-color: #f0f5f9;
}
"""
# 应用样式
self.top_bar.apply_styles(input_style, select_style, query_style, notice_style)
self.data_table.apply_styles(table_style)
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("模块化表格应用")
self.resize(1000, 600)
# 创建主表格组件
self.table_widget = MainTableWidget()
self.table_widget.apply_styles() # 应用样式
# 设置为主窗口中心部件
self.setCentralWidget(self.table_widget)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec())
初始默认 下来框为空 点击批量提醒 则自动将现在下来数据添加下拉框中
最新发布