I have a QTableWidget, that allows moving of rows by dragging and dropping.
The initial table looks as follows:
If clicking on the button, it prints all the values as they are in the table.
Now after dragging row 2 to the the position of row 4, the output does not change.
Output:
Item in row 0, col 0 has value Name
Item in row 0, col 1 has value City
Item in row 1, col 0 has value Aloysius
Item in row 1, col 1 has value Indore
Item in row 2, col 0 has value Alan
Item in row 2, col 1 has value Bhopal
Item in row 3, col 0 has value Arnavi
Item in row 3, col 1 has value Mandsaur
The expected output:
Item in row 0, col 0 has value Name
Item in row 0, col 1 has value City
Item in row 1, col 0 has value Alan
Item in row 1, col 1 has value Bhopal
Item in row 2, col 0 has value Arnavi
Item in row 2, col 1 has value Mandsaur
Item in row 3, col 0 has value Aloysius
Item in row 3, col 1 has value Indore
Why is this the case and how can I print all the rows by their actual, new location?
Example:
import sys
import PyQt5
from PyQt5.QtCore import *#QPointF, QRectF
from PyQt5.QtGui import *#QPainterPath, QPolygonF, QBrush,QPen,QFont,QColor, QTransform
from PyQt5.QtWidgets import *#QApplication, QGraphicsScene, QGraphicsView, QGraphicsSimpleTextIt
class App(QWidget):
def __init__(self):
super().__init__()
self.title = 'PyQt5 - QTableWidget'
self.left = 0
self.top = 0
self.width = 300
self.height = 200
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
self.tableWidget = QTableWidget()
self.tableWidget.verticalHeader().setSectionsMovable(True)
self.tableWidget.verticalHeader().setDragEnabled(True)
self.tableWidget.verticalHeader().setDragDropMode(QAbstractItemView.InternalMove)
# Row count
self.tableWidget.setRowCount(4)
# Column count
self.tableWidget.setColumnCount(2)
self.tableWidget.setItem(0, 0, QTableWidgetItem("Name"))
self.tableWidget.setItem(0, 1, QTableWidgetItem("City"))
self.tableWidget.setItem(1, 0, QTableWidgetItem("Aloysius"))
self.tableWidget.setItem(1, 1, QTableWidgetItem("Indore"))
self.tableWidget.setItem(2, 0, QTableWidgetItem("Alan"))
self.tableWidget.setItem(2, 1, QTableWidgetItem("Bhopal"))
self.tableWidget.setItem(3, 0, QTableWidgetItem("Arnavi"))
self.tableWidget.setItem(3, 1, QTableWidgetItem("Mandsaur"))
# Table will fit the screen horizontally
self.tableWidget.horizontalHeader().setStretchLastSection(True)
self.tableWidget.horizontalHeader().setSectionResizeMode(
QHeaderView.Stretch)
self.layout = QVBoxLayout()
self.layout.addWidget(self.tableWidget)
self.button = QPushButton("Print all the values in the table, in the right order!")
def get_all_the_values_in_the_table():
#row_counter = 0
print(" ")
print(" ")
for row in range(self.tableWidget.rowCount()):
for col in range(self.tableWidget.columnCount()):
print("Item in row "+str(row)+", col "+str(col)+" has value "+str(self.tableWidget.item(row,col).text()))
self.button.clicked.connect(lambda: get_all_the_values_in_the_table())
self.layout.addWidget(self.button)
self.setLayout(self.layout)
# Show window
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())
Edit 1:
Thought that perhaps the item has the same location in the table, but a different index. Yet trying to solve this by getting the index does not work neither. Where's the trick?
print("Item in row "+str(row_)+", col "+str(col_)+" has value "+str(self.tableWidget.itemFromIndex(self.tableWidget.indexFromItem(self.tableWidget.item(row_,col_))).text()))
Moving header sections does not change the model layout, only the visual representation: if you move the first header to another place, the first row in the model will still be the previous one. In fact, if you closely look at the vertical header, the labels (which by default indicate the model index) are moved also.
If you want to print the model based on the header layout, you need to call logicalIndex()
:
def get_all_the_values_in_the_table():
print()
print()
header = self.tableWidget.verticalHeader()
for i in range(self.tableWidget.rowCount()):
# get the logical index based on the visual index
row = header.logicalIndex(i)
for col in range(self.tableWidget.columnCount()):
print("Item in row {}, col {} has value {}".format(
i, col, self.tableWidget.item(row,col).text()))
self.button.clicked.connect(get_all_the_values_in_the_table)
Note that:
width()
and height()
are existing members of all QWidgets, you should not overwrite them;setDragEnabled
and setDragDropMode
to make header sections movable, as setSectionsMovable
will suffice;