2

I'm trying to drag and drop files into a table-widget, but the path will not appear when I drop the files. When I test by using print() the path appears, but the path will not appear in the table. I am not sure why this is happening, I would greatly appreciate some help.

Main code:

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 code:

# -*- 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_()) 

2 Answers 2

2

In order to do this using an event-filter, you need to handle the drag-enter, drag-move and drag-drop events, and accept the events when the mime-data contains urls. The following changes to your example should work as expected:

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) 
Sign up to request clarification or add additional context in comments.

Comments

0

The table has no columns: setItemData() will be ignored if no valid row and column are given:

 def addFile(self, filepath): if not self.tableWidget.columnCount(): self.tableWidget.setColumnCount(1) # ... 

Note that you must always check the event type in an event filter before accessing the event functions, otherwise you'll get an error or even a crash:

 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) 

Also, remove the following line, which is completely wrong:

 self.tableWidget.dropEvent(self.eventFilter()) 

4 Comments

I tried this our and it didn't work, @ekhumoro 's answer did work. Thank you though!
@cwdesignsvs sorry but "didn't work" alone means nothing. Have you properly edited the code as suggested? Did you run the code in a terminal or prompt to see for any useful output and debug? ekhumoro's answer is correct and complete, but mine should be valid as much as long as it's based on your code. It is possible that it won't work, but knowing why is not only useful to you but also so me and to anybody reading this answer. "It doesn't work" is meaningless without further explanation, so, please add further details.
I edited the code as you suggested and received the following error: Traceback (most recent call last): File "D:\Python Projects\HATS SAMS Conversion\Vituix Converter.py", line 113, in eventFilter if event.mimeData().hasUrls(): AttributeError: 'QEvent' object has no attribute 'mimeData'
@cwdesignsvs that's not my code, that's still yours. Read more carefully what I wrote: the if in eventFilter() starts with a check of the event type, and I specifically explained that you must do that to avoid exactly what you just wrote.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.