gpt4 book ai didi

python - PyQt6 在同一窗口中跨选项卡实现复制粘贴功能

转载 作者:行者123 更新时间:2023-12-05 05:35:25 28 4
gpt4 key购买 nike

我正在尝试在 PyQt 中创建一个具有复制粘贴功能和创建新选项卡功能的 tableWidget。我的表加载了一个初始化的工作表,但让用户能够使用新的 qTableWidgets 创建新的选项卡,每次在我的 add_sheet() 中创建新选项卡时,我都会使用 for 循环来创建和初始化小部件。功能。

我还想添加在每个选项卡内和跨选项卡进行复制和粘贴的功能。现在,当我添加按键事件功能来执行此操作时,在尝试将新选项卡复制和粘贴到索引之外时,我一直遇到错误。我试图通过保留所选索引来自哪个选项卡的指针来解决此问题,但这只允许我在创建的第一个新选项卡上进行编辑。尝试执行操作时初始电子表格崩溃,其他选项卡无法正常工作。它也不会在选项卡之间普遍复制和粘贴。

我觉得我的处理太复杂了,我的设计模式有缺陷或遗漏了一些东西。

我如何才能正确实现我的复制粘贴功能,以便在所有具有自己的 QTableWidget 实例的动态选项卡之间工作,包括在本地和全局创建的初始 QTableWidget?

import sys
from PyQt6.QtWidgets import (QApplication, QMainWindow,
QTableWidget, QTableWidgetItem,QVBoxLayout,QTabWidget,QWidget,QToolButton,QToolBar)
from PyQt6.QtCore import Qt



class MainWindow(QMainWindow):

def __init__(self):
super().__init__()
self.tab_widget = MyTabWidget(self)
self.setCentralWidget(self.tab_widget)
self.initializeUI()

def initializeUI(self):
"""Set up the application's GUI."""
self.setMinimumSize(1200, 500)
self.setWindowTitle("Spreadsheet - QTableWidget Example")

# Used for copy and paste actions
self.item_text = None

self.setUpMainWindow()
self.show()


def setUpMainWindow(self):
"""Create and arrange widgets in the main window."""

# Set initial row and column values
main_spreadsheet_widget.setRowCount(10)
main_spreadsheet_widget.setColumnCount(10)



class MyTabWidget(QWidget):
def __init__(self, parent):
super(QWidget, self).__init__(parent)
self.layout = QVBoxLayout(self)

# Initialize tab screen
self.sheets = QTabWidget()
self.main_sheet = QWidget()
self.sheets.resize(300, 200)
self.extra_sheets_tracker = list()
self.tab_index = []
self.copied_cells_list = []
self.paste_index = []


# Add sheets
self.sheets.addTab(self.main_sheet, "Main Sheet")
#self.sheets.addTab(self.tab3, "Geeks")

# Create first tab
self.main_sheet.layout = QVBoxLayout(self)
self.main_sheet.layout.addWidget(main_spreadsheet_widget)
self.main_sheet.setLayout(self.main_sheet.layout)
self.tabButton = QToolButton(self)
self.tabButton.setText('+')
font = self.tabButton.font()
font.setBold(True)
self.tabButton.setFont(font)
self.sheets.setCornerWidget(self.tabButton)
self.tabButton.clicked.connect(self.add_sheet)


# Add sheets to widget
self.layout.addWidget(self.sheets)
self.setLayout(self.layout)

def add_sheet(self):

self.sheet = QWidget()
self.main_tab_sheet_widget = QTableWidget()
self.extra_sheets_tracker.append(self.main_tab_sheet_widget)
self.main_tab_sheet_widget.setRowCount(10)
self.main_tab_sheet_widget.setColumnCount(10)


self.sheet.layout = QVBoxLayout(self)

self.sheet.layout.addWidget(self.main_tab_sheet_widget)
self.sheet.setLayout(self.sheet.layout)
self.sheets.addTab(self.main_tab_sheet_widget, "Sheet" + str(len(self.extra_sheets_tracker)))



def keyPressEvent(self, event):
super().keyPressEvent(event)
if event.key() == Qt.Key.Key_C and (event.modifiers() & Qt.KeyboardModifier.ControlModifier):
self.tab_index = []
for i in self.extra_sheets_tracker:
if i.selectedIndexes() is not None:
self.tab_index.append(self.extra_sheets_tracker.index(i))
self.copied_cells = sorted(self.extra_sheets_tracker[self.tab_index[0]].selectedIndexes())
self.copied_cells_list.append(self.copied_cells)
self.copied_cells = None
elif event.key() == Qt.Key.Key_V and (event.modifiers() & Qt.KeyboardModifier.ControlModifier):
self.paste_index = []
for i in self.extra_sheets_tracker:
self.paste_index.append(self.extra_sheets_tracker.index(i))
r = self.extra_sheets_tracker[self.paste_index[0]].currentRow() - self.copied_cells_list[0][0].row()
c = self.extra_sheets_tracker[self.paste_index[0]].currentColumn() - self.copied_cells_list[0][0].column()
for cell in self.copied_cells_list[0]:
self.extra_sheets_tracker[self.paste_index[0]].setItem(cell.row() + r, cell.column() + c, QTableWidgetItem(cell.data()))


if __name__ == "__main__":
app = QApplication(sys.argv)
main_spreadsheet_widget = QTableWidget()
window = MainWindow()
window.show()
sys.exit(app.exec())

最佳答案

我已经设法做到了以下几点:

1- 我将主工作表视为“只是另一张工作表”,并确保它遵循相同的相对例程。这包括删除不必要的函数,如 setUpMainWindow 并引入静态值,如 MAX_ROWSMAX_COLS 分别用于最大行数和最大列数。这还需要将 extra_sheets_tracker 重命名为 sheets_tracker,因为它将容纳所有工作表。

2- 我已经创建了两种粘贴策略:1st-cell 用于选择表格中的第一个单元格,或 1-to-1 用于选择确切的计数粘贴侧的单元格。这也意味着,预先检查尺寸并在尺寸不匹配时引发异常 Unmatching pasting size

3- 我删除了 self.tab_indexself.copied_cells_list 因为它们未被使用。 copy_list 全局使用,留在self 中是个不错的主意。然而,paste_list 除了粘贴例程之外没有在其他任何地方使用,我将它从 self 中删除。您需要查看您的 self 变量,您似乎过度使用了它们。

import sys
from PyQt6.QtWidgets import QApplication, QMainWindow, QTableWidget, QTableWidgetItem, QVBoxLayout, QTabWidget, QWidget, QToolButton, QToolBar
from PyQt6.QtCore import Qt



class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.tab_widget = MyTabWidget(self)
self.setCentralWidget(self.tab_widget)
self.initializeUI()

def initializeUI(self):
"""Set up the application's GUI."""
self.setMinimumSize(1200, 500)
self.setWindowTitle("Spreadsheet - QTableWidget Example")

# Used for copy and paste actions
self.item_text = None
self.show()


class MyTabWidget(QWidget):
def __init__(self, parent):
super(QWidget, self).__init__(parent)
self.layout = QVBoxLayout(self)

# Initialize tab screen
self.MAX_ROWS = 10
self.MAX_COLS = 10
self.STRATEGY = {0:'1st-cell', 1:'1-to-1'}
self.sheets = QTabWidget()
self.main_sheet = QWidget()
self.sheets.resize(300, 200)
self.sheets_tracker = list()
self.copy_list = []
#self.copied_cells_list = []
#self.paste_list = []


# Add a sheet and create first tab
self.main_sheet.layout = QVBoxLayout(self)
# Setup main window
self.add_sheet()

tabButton = QToolButton(self)
tabButton.setText('+')
font = tabButton.font()
font.setBold(True)
tabButton.setFont(font)
tabButton.clicked.connect(self.add_sheet)

self.sheets.setCornerWidget(tabButton)

# Add sheets to widget
self.layout.addWidget(self.sheets)
self.setLayout(self.layout)

def add_sheet(self):
sheets_count = len(self.sheets_tracker)
if sheets_count < 1:
label = "Main sheet"
else:
label = f"Sheet{sheets_count}"

self.main_tab_sheet_widget = QTableWidget()
self.main_tab_sheet_widget.setRowCount(self.MAX_ROWS)
self.main_tab_sheet_widget.setColumnCount(self.MAX_COLS)
self.sheets_tracker.append(self.main_tab_sheet_widget)

self.sheet = QWidget()
self.sheet.layout = QVBoxLayout(self)
self.sheet.layout.addWidget(self.main_tab_sheet_widget)
self.sheet.setLayout(self.sheet.layout)
self.sheets.addTab(self.main_tab_sheet_widget, label)


def keyPressEvent(self, event):
super().keyPressEvent(event)
if event.key() == Qt.Key.Key_C and (event.modifiers() & Qt.KeyboardModifier.ControlModifier):
self.copy_list = sorted([(e.row(), e.column(), e.data()) for e in self.sheets_tracker[self.sheets.currentIndex()].selectedIndexes()])
if len(self.copy_list) != 0:
# recalculate the indicies to absolute values
least_row = self.copy_list[0][0]
least_col = sorted(self.copy_list, key=lambda tup: tup[1])[0][1]
self.copy_list = [(e[0]-least_row, e[1]-least_col, e[2]) for e in self.copy_list]
print(self.copy_list)
elif event.key() == Qt.Key.Key_V and (event.modifiers() & Qt.KeyboardModifier.ControlModifier):
paste_list = sorted([(element.row(), element.column(), element.data()) for element in self.sheets_tracker[self.sheets.currentIndex()].selectedIndexes()])
if len(paste_list) != 0:
if len(paste_list) == 1:
# The given paste position is the first cell only
current_r, current_c, _ = paste_list[-1]
last_r, last_c, _ = self.copy_list[-1]
if last_r + current_r - 1 < self.MAX_ROWS and last_c + current_c - 1 < self.MAX_COLS:
strategy = self.STRATEGY[0]
else:
raise Exception('Unmatching pasting size')
elif len(self.copy_list) == len(paste_list):
# You can paste in one-to-one correspondence
strategy = self.STRATEGY[1]
else:
raise Exception('Unmatching pasting size')

if strategy == self.STRATEGY[0]:
r, c, _ = paste_list[0]
for index, e in enumerate(self.copy_list):
_, _, d = self.copy_list[index]
d = '' if d is None else d
print(f"Pasting at index [{self.sheets.currentIndex()}] cell ({e[0]+r}, {e[1]+c})")
textCell = QTableWidgetItem(); textCell.setText(f'{d}')
self.sheets_tracker[self.sheets.currentIndex()].setItem(e[0]+r, e[1]+c, textCell)

if strategy == self.STRATEGY[1]:
for index, e in enumerate(paste_list):
_, _, d = self.copy_list[index]
d = '' if d is None else d
print(f"Pasting at index [{self.sheets.currentIndex()}] cell ({e[0]}, {e[1]})")
textCell = QTableWidgetItem(); textCell.setText(f'{d}')
self.sheets_tracker[self.sheets.currentIndex()].setItem(e[0], e[1], textCell)


if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec())

关于python - PyQt6 在同一窗口中跨选项卡实现复制粘贴功能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73520821/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com