将文件拖放到 QTableWidget
Drag and drop files to QTableWidget
我正在尝试将文件拖放到 table-widget 中,但是当我拖放文件时路径不会出现。当我使用 print() 测试时,路径出现,但路径不会出现在 table 中。我不确定为什么会这样,非常感谢您的帮助。
主要代码:
import os
import shutil
import sys
import pandas as pd
from PyQt5 import QtGui, QtWidgets, QtCore
from PyQt5.QtWidgets import *
from vituix_converter_UI import (Ui_MainWindow)
def no_file_selected():
msg = QMessageBox()
msg.setIcon(QMessageBox.Warning)
msg.setWindowIcon(QtGui.QIcon("D:/Python Projects/HATS SAMS Conversion/Icon/Vituix_Converter_Icon_R1.ico"))
msg.setText("No File Was Selected!")
msg.setWindowTitle("Warning!")
retval = msg.exec_()
def process_completed():
msg = QMessageBox()
msg.setIcon(QMessageBox.Information)
msg.setWindowIcon(QtGui.QIcon("D:/Python Projects/HATS SAMS Conversion/Icon/Vituix_Converter_Icon_R1.ico"))
msg.setText("Files are converted.")
msg.setWindowTitle("Completed!")
retval = msg.exec_()
class MyMainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super(MyMainWindow, self).__init__(parent)
self.setupUi(self)
self.pushButton_hats.clicked.connect(self.hats_conversion)
self.pushButton_sams.clicked.connect(self.sams_conversion)
self.tableWidget.setAcceptDrops(True)
self.tableWidget.viewport().installEventFilter(self)
types = ['text/uri-list']
types.extend(self.tableWidget.mimeTypes())
self.tableWidget.mimeTypes = lambda: types
self.tableWidget.setRowCount(0)
self.tableWidget.dropEvent(self.eventFilter())
def hats_conversion(self):
hats_file = QtWidgets.QFileDialog.getOpenFileName(self, "Select HATS File", "", 'txt (*.txt)')[0]
if hats_file == '':
no_file_selected()
else:
hats_data = pd.read_csv(hats_file, sep="\t", skiprows=3, header=None, on_bad_lines='skip')
txt_name = []
for i in range(1, 148, 2):
txt_name.append(hats_data.loc[0, i])
hats_data = hats_data.drop([0, 1])
hats_data = hats_data.reset_index(drop=True)
# Select folder to save data output
save_folder = QtWidgets.QFileDialog.getExistingDirectory(self, "Select HATS Save Folder")
# iteration variable for lists in following for loop
i = 1
# iterate over all text names, allocate corresponding data, and then save as txt
for j in range(0, len(txt_name)):
test_df_1 = hats_data[0].values.tolist()
test_df_2 = hats_data[i].values.tolist()
test_df_3 = hats_data[i + 1].values.tolist()
export_df = pd.DataFrame(
{'0': test_df_1,
'1': test_df_2,
'2': test_df_3
})
save_file = save_folder + '/' + txt_name[j] + '.txt'
export_df.to_csv(save_file, sep='\t', index=False, na_rep='NaN', header=False)
i = i + 2
process_completed()
def sams_conversion(self):
sams_file = QtWidgets.QFileDialog.getExistingDirectory(self, "Select SAMS Folder")
if sams_file == '':
no_file_selected()
else:
output_folder = QtWidgets.QFileDialog.getExistingDirectory(self, "Select/Create Save Folder")
if output_folder == '':
no_file_selected()
else:
file_names = []
for x in os.listdir(sams_file):
if x.endswith(".txt"):
file_names.append(x)
for i in range(len(file_names)):
newPath = shutil.copy(os.path.join(sams_file, file_names[i]), output_folder)
sams_data = pd.read_csv(newPath, sep="\t", skiprows=5, header=None, on_bad_lines='skip')
sams_data.to_csv(newPath, sep='\t', index=False, na_rep='NaN', header=False)
process_completed()
def eventFilter(self, source, event):
if event.mimeData().hasUrls():
for url in event.mimeData().urls():
self.addFile(url.toLocalFile())
return True
return super().eventFilter(source, event)
def addFile(self, filepath):
row = self.tableWidget.rowCount()
self.tableWidget.insertRow(row)
item = QtWidgets.QTableWidgetItem(filepath)
self.tableWidget.setItem(row, 0, item)
self.tableWidget.resizeColumnToContents(0)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
app.setWindowIcon(QtGui.QIcon("D:/Python Projects/HATS SAMS Conversion/Icon/Vituix_Converter_Icon_R1.ico"))
win = MyMainWindow()
win.show()
sys.exit(app.exec_())
UI代码:
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'vituix converter.ui'
#
# Created by: PyQt5 UI code generator 5.15.6
#
# 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_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(400, 500)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(MainWindow.sizePolicy().hasHeightForWidth())
MainWindow.setSizePolicy(sizePolicy)
MainWindow.setMinimumSize(QtCore.QSize(400, 500))
MainWindow.setMaximumSize(QtCore.QSize(400, 500))
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap("Icon/Vituix_Converter_Icon_R1.ico"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
MainWindow.setWindowIcon(icon)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
self.verticalLayout.setObjectName("verticalLayout")
self.tableWidget = QtWidgets.QTableWidget(self.centralwidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.MinimumExpanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.tableWidget.sizePolicy().hasHeightForWidth())
self.tableWidget.setSizePolicy(sizePolicy)
self.tableWidget.setMinimumSize(QtCore.QSize(0, 350))
self.tableWidget.setDragEnabled(False)
self.tableWidget.setDragDropMode(QtWidgets.QAbstractItemView.DropOnly)
self.tableWidget.setDefaultDropAction(QtCore.Qt.LinkAction)
self.tableWidget.setAlternatingRowColors(True)
self.tableWidget.setObjectName("tableWidget")
self.tableWidget.setColumnCount(0)
self.tableWidget.setRowCount(0)
self.verticalLayout.addWidget(self.tableWidget, 0, QtCore.Qt.AlignVCenter)
self.gridLayout = QtWidgets.QGridLayout()
self.gridLayout.setSizeConstraint(QtWidgets.QLayout.SetDefaultConstraint)
self.gridLayout.setVerticalSpacing(6)
self.gridLayout.setObjectName("gridLayout")
self.pushButton_hats = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_hats.setMinimumSize(QtCore.QSize(0, 55))
font = QtGui.QFont()
font.setPointSize(9)
font.setBold(True)
font.setWeight(75)
self.pushButton_hats.setFont(font)
self.pushButton_hats.setObjectName("pushButton_hats")
self.gridLayout.addWidget(self.pushButton_hats, 0, 0, 1, 1)
self.pushButton_sams = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_sams.setMinimumSize(QtCore.QSize(0, 55))
font = QtGui.QFont()
font.setPointSize(9)
font.setBold(True)
font.setWeight(75)
self.pushButton_sams.setFont(font)
self.pushButton_sams.setObjectName("pushButton_sams")
self.gridLayout.addWidget(self.pushButton_sams, 0, 1, 1, 1, QtCore.Qt.AlignVCenter)
self.verticalLayout.addLayout(self.gridLayout)
MainWindow.setCentralWidget(self.centralwidget)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "Vituix Converter"))
self.pushButton_hats.setText(_translate("MainWindow", "Vituix HATS"))
self.pushButton_sams.setText(_translate("MainWindow", "Vituix SAMS"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
为了使用 event-filter 执行此操作,您需要处理 drag-enter、drag-move 和 drag-drop 事件,并在 mime-data 包含 url。对您的示例进行的以下更改应该会按预期工作:
class MyMainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
...
self.tableWidget.setAcceptDrops(True)
self.tableWidget.viewport().installEventFilter(self)
self.tableWidget.setRowCount(0)
self.tableWidget.setColumnCount(1)
def eventFilter(self, source, event):
if (source is self.tableWidget.viewport() and
(event.type() == QtCore.QEvent.DragEnter or
event.type() == QtCore.QEvent.DragMove or
event.type() == QtCore.QEvent.Drop) and
event.mimeData().hasUrls()):
if event.type() == QtCore.QEvent.Drop:
for url in event.mimeData().urls():
if url.isLocalFile():
self.addFile(url.path())
event.accept()
return True
return super().eventFilter(source, event)
table 没有列:如果没有给出有效的行和列,setItemData()
将被忽略:
def addFile(self, filepath):
if not self.tableWidget.columnCount():
self.tableWidget.setColumnCount(1)
# ...
请注意,在访问事件函数之前,您必须始终检查事件过滤器中的事件类型,否则您将收到错误甚至崩溃:
def eventFilter(self, source, event):
if event.type() == event.Drop and event.mimeData().hasUrls():
for url in event.mimeData().urls():
self.addFile(url.toLocalFile())
return True
return super().eventFilter(source, event)
此外,请删除以下完全错误的行:
self.tableWidget.dropEvent(self.eventFilter())
我正在尝试将文件拖放到 table-widget 中,但是当我拖放文件时路径不会出现。当我使用 print() 测试时,路径出现,但路径不会出现在 table 中。我不确定为什么会这样,非常感谢您的帮助。
主要代码:
import os
import shutil
import sys
import pandas as pd
from PyQt5 import QtGui, QtWidgets, QtCore
from PyQt5.QtWidgets import *
from vituix_converter_UI import (Ui_MainWindow)
def no_file_selected():
msg = QMessageBox()
msg.setIcon(QMessageBox.Warning)
msg.setWindowIcon(QtGui.QIcon("D:/Python Projects/HATS SAMS Conversion/Icon/Vituix_Converter_Icon_R1.ico"))
msg.setText("No File Was Selected!")
msg.setWindowTitle("Warning!")
retval = msg.exec_()
def process_completed():
msg = QMessageBox()
msg.setIcon(QMessageBox.Information)
msg.setWindowIcon(QtGui.QIcon("D:/Python Projects/HATS SAMS Conversion/Icon/Vituix_Converter_Icon_R1.ico"))
msg.setText("Files are converted.")
msg.setWindowTitle("Completed!")
retval = msg.exec_()
class MyMainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super(MyMainWindow, self).__init__(parent)
self.setupUi(self)
self.pushButton_hats.clicked.connect(self.hats_conversion)
self.pushButton_sams.clicked.connect(self.sams_conversion)
self.tableWidget.setAcceptDrops(True)
self.tableWidget.viewport().installEventFilter(self)
types = ['text/uri-list']
types.extend(self.tableWidget.mimeTypes())
self.tableWidget.mimeTypes = lambda: types
self.tableWidget.setRowCount(0)
self.tableWidget.dropEvent(self.eventFilter())
def hats_conversion(self):
hats_file = QtWidgets.QFileDialog.getOpenFileName(self, "Select HATS File", "", 'txt (*.txt)')[0]
if hats_file == '':
no_file_selected()
else:
hats_data = pd.read_csv(hats_file, sep="\t", skiprows=3, header=None, on_bad_lines='skip')
txt_name = []
for i in range(1, 148, 2):
txt_name.append(hats_data.loc[0, i])
hats_data = hats_data.drop([0, 1])
hats_data = hats_data.reset_index(drop=True)
# Select folder to save data output
save_folder = QtWidgets.QFileDialog.getExistingDirectory(self, "Select HATS Save Folder")
# iteration variable for lists in following for loop
i = 1
# iterate over all text names, allocate corresponding data, and then save as txt
for j in range(0, len(txt_name)):
test_df_1 = hats_data[0].values.tolist()
test_df_2 = hats_data[i].values.tolist()
test_df_3 = hats_data[i + 1].values.tolist()
export_df = pd.DataFrame(
{'0': test_df_1,
'1': test_df_2,
'2': test_df_3
})
save_file = save_folder + '/' + txt_name[j] + '.txt'
export_df.to_csv(save_file, sep='\t', index=False, na_rep='NaN', header=False)
i = i + 2
process_completed()
def sams_conversion(self):
sams_file = QtWidgets.QFileDialog.getExistingDirectory(self, "Select SAMS Folder")
if sams_file == '':
no_file_selected()
else:
output_folder = QtWidgets.QFileDialog.getExistingDirectory(self, "Select/Create Save Folder")
if output_folder == '':
no_file_selected()
else:
file_names = []
for x in os.listdir(sams_file):
if x.endswith(".txt"):
file_names.append(x)
for i in range(len(file_names)):
newPath = shutil.copy(os.path.join(sams_file, file_names[i]), output_folder)
sams_data = pd.read_csv(newPath, sep="\t", skiprows=5, header=None, on_bad_lines='skip')
sams_data.to_csv(newPath, sep='\t', index=False, na_rep='NaN', header=False)
process_completed()
def eventFilter(self, source, event):
if event.mimeData().hasUrls():
for url in event.mimeData().urls():
self.addFile(url.toLocalFile())
return True
return super().eventFilter(source, event)
def addFile(self, filepath):
row = self.tableWidget.rowCount()
self.tableWidget.insertRow(row)
item = QtWidgets.QTableWidgetItem(filepath)
self.tableWidget.setItem(row, 0, item)
self.tableWidget.resizeColumnToContents(0)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
app.setWindowIcon(QtGui.QIcon("D:/Python Projects/HATS SAMS Conversion/Icon/Vituix_Converter_Icon_R1.ico"))
win = MyMainWindow()
win.show()
sys.exit(app.exec_())
UI代码:
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'vituix converter.ui'
#
# Created by: PyQt5 UI code generator 5.15.6
#
# 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_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(400, 500)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(MainWindow.sizePolicy().hasHeightForWidth())
MainWindow.setSizePolicy(sizePolicy)
MainWindow.setMinimumSize(QtCore.QSize(400, 500))
MainWindow.setMaximumSize(QtCore.QSize(400, 500))
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap("Icon/Vituix_Converter_Icon_R1.ico"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
MainWindow.setWindowIcon(icon)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
self.verticalLayout.setObjectName("verticalLayout")
self.tableWidget = QtWidgets.QTableWidget(self.centralwidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.MinimumExpanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.tableWidget.sizePolicy().hasHeightForWidth())
self.tableWidget.setSizePolicy(sizePolicy)
self.tableWidget.setMinimumSize(QtCore.QSize(0, 350))
self.tableWidget.setDragEnabled(False)
self.tableWidget.setDragDropMode(QtWidgets.QAbstractItemView.DropOnly)
self.tableWidget.setDefaultDropAction(QtCore.Qt.LinkAction)
self.tableWidget.setAlternatingRowColors(True)
self.tableWidget.setObjectName("tableWidget")
self.tableWidget.setColumnCount(0)
self.tableWidget.setRowCount(0)
self.verticalLayout.addWidget(self.tableWidget, 0, QtCore.Qt.AlignVCenter)
self.gridLayout = QtWidgets.QGridLayout()
self.gridLayout.setSizeConstraint(QtWidgets.QLayout.SetDefaultConstraint)
self.gridLayout.setVerticalSpacing(6)
self.gridLayout.setObjectName("gridLayout")
self.pushButton_hats = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_hats.setMinimumSize(QtCore.QSize(0, 55))
font = QtGui.QFont()
font.setPointSize(9)
font.setBold(True)
font.setWeight(75)
self.pushButton_hats.setFont(font)
self.pushButton_hats.setObjectName("pushButton_hats")
self.gridLayout.addWidget(self.pushButton_hats, 0, 0, 1, 1)
self.pushButton_sams = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_sams.setMinimumSize(QtCore.QSize(0, 55))
font = QtGui.QFont()
font.setPointSize(9)
font.setBold(True)
font.setWeight(75)
self.pushButton_sams.setFont(font)
self.pushButton_sams.setObjectName("pushButton_sams")
self.gridLayout.addWidget(self.pushButton_sams, 0, 1, 1, 1, QtCore.Qt.AlignVCenter)
self.verticalLayout.addLayout(self.gridLayout)
MainWindow.setCentralWidget(self.centralwidget)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "Vituix Converter"))
self.pushButton_hats.setText(_translate("MainWindow", "Vituix HATS"))
self.pushButton_sams.setText(_translate("MainWindow", "Vituix SAMS"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
为了使用 event-filter 执行此操作,您需要处理 drag-enter、drag-move 和 drag-drop 事件,并在 mime-data 包含 url。对您的示例进行的以下更改应该会按预期工作:
class MyMainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
...
self.tableWidget.setAcceptDrops(True)
self.tableWidget.viewport().installEventFilter(self)
self.tableWidget.setRowCount(0)
self.tableWidget.setColumnCount(1)
def eventFilter(self, source, event):
if (source is self.tableWidget.viewport() and
(event.type() == QtCore.QEvent.DragEnter or
event.type() == QtCore.QEvent.DragMove or
event.type() == QtCore.QEvent.Drop) and
event.mimeData().hasUrls()):
if event.type() == QtCore.QEvent.Drop:
for url in event.mimeData().urls():
if url.isLocalFile():
self.addFile(url.path())
event.accept()
return True
return super().eventFilter(source, event)
table 没有列:如果没有给出有效的行和列,setItemData()
将被忽略:
def addFile(self, filepath):
if not self.tableWidget.columnCount():
self.tableWidget.setColumnCount(1)
# ...
请注意,在访问事件函数之前,您必须始终检查事件过滤器中的事件类型,否则您将收到错误甚至崩溃:
def eventFilter(self, source, event):
if event.type() == event.Drop and event.mimeData().hasUrls():
for url in event.mimeData().urls():
self.addFile(url.toLocalFile())
return True
return super().eventFilter(source, event)
此外,请删除以下完全错误的行:
self.tableWidget.dropEvent(self.eventFilter())