PyQt5 QTableWidget的显示、添加和删除多行

最近为了写软著,一直在用PyQt5进行开发,但因为本身对PyQt5并不熟悉,所以在写代码的过程中遇到了很多问题,只能在网上疯狂百度找办法,这一篇博客简单总结一下PyQt5中QTableWidget的显示、添加和删除操作的方法。

1. QTableWidget的显示

首先给出我的界面如下,其中红色框就是显示的表格。

PyQt5 QTableWidget的显示、添加和删除多行_第1张图片

显示表格的代码如下,具体细节已经在代码的注释中给出。

    def show_events(self, event_table, total_events, cause_tag):
        """
            将事件列表显示在tableWidget中
        :param event_table: tableWidget控件
        :param total_events: 所有事件的列表
        :param cause_tag: 所有的标签值列表
        :return: None
        """
		
        # 先给出表格中需要显示的行列数。注意这个是必须要提前设置的,否则无法显示
        event_table.setColumnCount(2)
        event_table.setRowCount(len(total_events))

        # 设置表格的列标题,并设置列的模式为"Stretch",在这种模式下列直接自适应显示,无法对列的宽度和高度进行设置
        header_list = ['event', 'cause']  # set header labels
        event_table.setHorizontalHeaderLabels(header_list)
        event_table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)

        # event_table.setColumnWidth(0, 685)
        # event_table.setColumnWidth(1, 100)
		
        # 表格中的每个cell都是一个Item,所以显示时需要分别显示每个cell的内容,每个cell的坐标都是(行号,列号),行号和列号都是从0开始
        for index, event in enumerate(total_events):
			
			# 在每一行中显示每个样本的每个元素
        	for column_index in range(7):
                self.main_ui.tuple_events_table.setItem(cur_row - 1, column_index, QTableWidgetItem(''))
            # event_table.setItem(index, 1, QTableWidgetItem(event_node.getAttribute('cause')))

            # 下拉框,默认值为'N',因为大部分值都为'N'
            combox_list = ['N', 'Y']
            combox = QtWidgets.QComboBox()
            combox.addItems(combox_list)
            if cause_tag[index] == 'N':
                combox.setCurrentIndex(0)
            else:
                combox.setCurrentIndex(1)
            # 这个函数可以用来定义所有控件的
            combox.setStyleSheet('QComboBox{margin:3px;font-family:Times New Roman;font-size:18;border-radius:8px}')
            event_table.setCellWidget(index, 1, combox)

2. QTableWidget绑定右键菜单

​ 首先需要在表格中绑定右键菜单,同时定义右键菜单的点击事件:

 # 设置events_table的右键菜单
self.tag_ui.events_table.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)  
 # 在tableWidget中点击右键的触发事件
self.tag_ui.events_table.customContextMenuRequested[QtCore.QPoint].connect(self.context_menu_of_events_table)

​ 在右键菜单的绑定事件中,我们需要定义右键菜单中显示的操作,同时定义显示的操作再被点击后的具体操作过程,代码如下:

def context_menu_of_events_table(self, pos):
    """
            用于在tableWidget中点击右键的触发事件,显示右键菜单
        :return:
        """
    pop_menu = QMenu()
    add_new_event = pop_menu.addAction('添加新事件')
    del_selected_event = pop_menu.addAction('删除选中事件')
	
    # 获取右键菜单中当前被点击的是哪一项
    action = pop_menu.exec_(self.tag_ui.events_table.mapToGlobal(pos))


实现后的界面如下:

PyQt5 QTableWidget的显示、添加和删除多行_第2张图片

3. QTableWidget中添加和删除事件

​ 在定义了QTableWidget的右键菜单的基础上,实现表格中的添加和删除事件的代码如下,具体细节在代码中给出。

def context_menu_of_events_table(self, pos):
    """
            用于在tableWidget中点击右键的触发事件,显示右键菜单
        :return:
        """
    pop_menu = QMenu()
    add_new_event = pop_menu.addAction('添加新事件')
    del_selected_event = pop_menu.addAction('删除选中事件')

    action = pop_menu.exec_(self.tag_ui.events_table.mapToGlobal(pos))

    if action == add_new_event:  # 如果选中的是添加新的事件
        """
        	如果是添加新行,首先必须先将表格的总行数加1,才能进行后续操作,将表格的行数加1之后,再在新加的行内每一列中添加Item
        
        """
        
        cur_total_row = self.tag_ui.events_table.rowCount()
        cur_row = cur_total_row + 1
        self.tag_ui.events_table.setRowCount(cur_row)  # 将当前的总行数加1

        self.tag_ui.events_table.setItem(cur_row-1, 0, QTableWidgetItem("请添加新的事件"))
        # event_table.setItem(index, 1, QTableWidgetItem(event_node.getAttribute('cause')))

        # 下拉框,默认值为'N',因为大部分值都为'N'
        combox_list = ['N', 'Y']
        combox = QtWidgets.QComboBox()
        combox.addItems(combox_list)
        combox.setCurrentIndex(0)
        # 这个函数可以用来定义所有控件的
        combox.setStyleSheet('QComboBox{margin:3px;font-family:Times New Roman;font-size:14;border-radius:8px}')
        self.tag_ui.events_table.setCellWidget(cur_row-1, 1, combox)

        elif action == del_selected_event:
            """
            	如果我们选择用.selectedItems()函数来得到当前选中的多行,一定要注意,这个函数返回的是所有选中的item,即返回的item的个数为:选中的行数 * 每一行的item数(我这个代码中有8列,但每行只返回7个item,我也不知道为什么,这一点需要注意一下)。
         		每个item都可以通过.indexFromItem(items).row()得到其所在的行号,再通过.removeRow(row_number)删除对应的行。
         		所以在删除时并不是所有的item都需要用,因为很显然要删除每一行都只需要一个该行的item即可,如果有多个肯定会报错,所以我才做了如下操作,在固定间隔取一个item,保证每一行中都只有一个item保留下来,这样就能保证每个被选中的行都只被删除一次。
         		还有一个需要注意的问题,如果选择多行的话,比如选择的行号为1,2,3,7,9,如果我们从前面开始删除,比如先删除第1行,则剩下的行的行的删除会出现问题,因为第1行删除后,原来的第2行会变成新的第1行,原来的第3行会变成新的第2行,以此类推,这很显然会导致剩余行的删除出现问题。我这里的解决办法是先将要删除的行进行降序排序,从后往前删除则可以保证删除的行不会发生错误。        
            
            
            """

            selected_items = self.main_ui.tuple_events_table.selectedItems()
            if len(selected_items) == 0:  # 说明没有选中任何行
                return
            selected_items = [selected_items[i] for i in range(len(selected_items)-1, -1, -7)]
            # 将选定行的行号降序排序,只有从索引大的行开始删除,才不会出现错误
            for items in selected_items:
                self.main_ui.tuple_events_table.removeRow(self.main_ui.tuple_events_table.indexFromItem(items).row())

你可能感兴趣的:(PyQt5)