I am trying to write a small app and want to somehow "catch" the row numbers of when a row is dragged / dropped but with no effect on the table. I have created two files, the first is a MainWindow UI file created in Qt Designer for the basic GUI and the second has the code to layout the QTableWidget with some data.
It works as I want, that is to say it shows a drag and drop movement to the user, but changes nothing when dropped. I have read other posts, but they all seem to be wanting to move the data, so they haven't been of any help with this.
UiFile.py
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'UiFile.ui'
#
# Created: Thu Apr 7 21:07:11 2016
# by: PyQt4 UI code generator 4.11.2
#
# WARNING! All changes made in this file will be lost!
from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName(_fromUtf8("MainWindow"))
MainWindow.resize(763, 269)
self.centralwidget = QtGui.QWidget(MainWindow)
self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
self.gridLayout = QtGui.QGridLayout(self.centralwidget)
self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
self.tableWidget = QtGui.QTableWidget(self.centralwidget)
self.tableWidget.setDragEnabled(False)
self.tableWidget.setDragDropOverwriteMode(False)
self.tableWidget.setDragDropMode(QtGui.QAbstractItemView.DragDrop)
self.tableWidget.setDefaultDropAction(QtCore.Qt.ActionMask)
self.tableWidget.setSelectionMode(QtGui.QAbstractItemView.SingleSelection)
self.tableWidget.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
self.tableWidget.setObjectName(_fromUtf8("tableWidget"))
self.tableWidget.setColumnCount(7)
self.tableWidget.setRowCount(0)
item = QtGui.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(0, item)
item = QtGui.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(1, item)
item = QtGui.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(2, item)
item = QtGui.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(3, item)
item = QtGui.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(4, item)
item = QtGui.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(5, item)
item = QtGui.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(6, item)
self.gridLayout.addWidget(self.tableWidget, 0, 0, 1, 1)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtGui.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 763, 24))
self.menubar.setObjectName(_fromUtf8("menubar"))
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtGui.QStatusBar(MainWindow)
self.statusbar.setObjectName(_fromUtf8("statusbar"))
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None))
item = self.tableWidget.horizontalHeaderItem(0)
item.setText(_translate("MainWindow", "Column 1", None))
item = self.tableWidget.horizontalHeaderItem(1)
item.setText(_translate("MainWindow", "Column 2", None))
item = self.tableWidget.horizontalHeaderItem(2)
item.setText(_translate("MainWindow", "Column 3", None))
item = self.tableWidget.horizontalHeaderItem(3)
item.setText(_translate("MainWindow", "Column 4", None))
item = self.tableWidget.horizontalHeaderItem(4)
item.setText(_translate("MainWindow", "Column 5", None))
item = self.tableWidget.horizontalHeaderItem(5)
item.setText(_translate("MainWindow", "New Column", None))
item = self.tableWidget.horizontalHeaderItem(6)
item.setText(_translate("MainWindow", "Column 7", None))
main.py
#!/usr/bin/env python
import sys
from PyQt4 import QtGui
import UiFile
class ExampleApp(QtGui.QMainWindow, UiFile.Ui_MainWindow):
def __init__(self, parent=None):
super(ExampleApp, self).__init__(parent)
self.setupUi(self)
self.home()
def home(self):
self.tableWidget.itemChanged.connect(self.my_item_changed_info)
self.add_row_to_ml_table("R1C1", "R1C2", "R1C3", "R1C4", "R1C5", "R1C6", "R1C7")
self.add_row_to_ml_table("R2C1", "R2C2", "R2C3", "R2C4", "R2C5", "R2C6", "R2C7")
self.add_row_to_ml_table("R3C1", "R3C2", "R3C3", "R3C4", "R3C5", "R3C6", "R3C7")
self.add_row_to_ml_table("R4C1", "R4C2", "R4C3", "R4C4", "R4C5", "R4C6", "R4C7")
self.add_row_to_ml_table("R5C1", "R5C2", "R5C3", "R5C4", "R5C5", "R5C6", "R5C7")
self.add_row_to_ml_table("R6C1", "R6C2", "R6C3", "R6C4", "R6C5", "R6C6", "R6C7")
self.add_row_to_ml_table("R7C1", "R7C2", "R7C3", "R7C4", "R7C5", "R7C6", "R7C7")
def add_row_to_ml_table(self, c1, c2, c3, c4, c5, c6, c7):
rowposition = self.tableWidget.rowCount()
self.tableWidget.insertRow(rowposition)
self.tableWidget.setItem(rowposition, 0, QtGui.QTableWidgetItem(c1))
self.tableWidget.setItem(rowposition, 1, QtGui.QTableWidgetItem(c2))
self.tableWidget.setItem(rowposition, 2, QtGui.QTableWidgetItem(c3))
self.tableWidget.setItem(rowposition, 3, QtGui.QTableWidgetItem(c4))
self.tableWidget.setItem(rowposition, 4, QtGui.QTableWidgetItem(c5))
self.tableWidget.setItem(rowposition, 5, QtGui.QTableWidgetItem(c6))
self.tableWidget.setItem(rowposition, 6, QtGui.QTableWidgetItem(c7))
def my_item_changed_info(self, something):
if self.tableWidget.currentRow() != -1:
print("current", self.tableWidget.currentRow(), self.tableWidget.currentColumn())
print(something.row(), something.column())
def closeEvent(self, event):
choice = QtGui.QMessageBox.question(self, 'Xmms2 Skin', 'Do you want to quit the applictaion?', QtGui.QMessageBox.Yes | QtGui.QMessageBox.No)
if choice == QtGui.QMessageBox.Yes:
event.accept()
else:
event.ignore()
def main():
app = QtGui.QApplication(sys.argv)
form = ExampleApp()
form.show()
app.exec_()
if __name__ == '__main__':
main()
So what I need to do is get the information of the row that has been dragged and the row that is being dropped onto.
From what I have read on this I would have to create a sub-Class of the QTableWidget in order to catch the event.
Can I do that using Qt Designer? I picked this in the first place according to my programming skills, and this is a small fragment of a much more complex GUI layout.
I solved it myself by adding
self.tableWidget.__class__.dropEvent = self.testdropfunc
into the home function, and then the testdropfunc looks like this :-
def testdropfunc(self, event):
moved_from = self.tableWidget.currentRow()
moved_to = self.tableWidget.rowAt(event.pos().y())
print("Drop from " + str(moved_from) + " into row " + str(moved_to))
event.accept()
I do realise that this does not actually move anything as all I wanted was the row information for the item ("dragged from" and "dropped to")
Related
I have taken two comboBoxes i.e., comboBox1 and comboBox_2 and two functions test and test1 and calling them using currentIndexChanged (self.comboBOx1.currentIndexChanged and self.comboBOx_2.currentIndexChanged). When a value is selected from comboBox1 its corresponding function(self.comboBOx1.currentIndexChanged) is called and same for comboBox_2. On selection of value from comboBox1 changes the values in comboBox_2 and its working fine. But the problem I have got here is that at first when I select a value from comboBox1 and comboBox_2 I'm getting the expected values from the called function(printing 'hello'). The second time when I select a value from comboBox1 only test function should be called but here both the functions(test and test1) are getting called and the second function (test1) is getting called twice(printing 'hello' twice) and for third time its getting called four times(printing 'hello' four times). Please can anyone help me with this problem.?
Code:
from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName(_fromUtf8("MainWindow"))
MainWindow.resize(800, 600)
self.centralwidget = QtGui.QWidget(MainWindow)
self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
self.comboBox1 = QtGui.QComboBox(self.centralwidget)
self.comboBox1.setGeometry(QtCore.QRect(310, 150, 171, 31))
self.comboBox1.setObjectName(_fromUtf8("comboBox1"))
self.comboBox1.addItem(_fromUtf8(""))
self.comboBox1.addItem(_fromUtf8(""))
self.comboBox1.addItem(_fromUtf8(""))
self.comboBox1.addItem(_fromUtf8(""))
self.comboBox_2 = QtGui.QComboBox(self.centralwidget)
self.comboBox_2.setGeometry(QtCore.QRect(310, 240, 171, 41))
self.comboBox_2.setObjectName(_fromUtf8("comboBox_2"))
self.comboBox_2.addItem(_fromUtf8(""))
self.comboBox_2.addItem(_fromUtf8(""))
self.comboBox_2.addItem(_fromUtf8(""))
self.comboBox_2.addItem(_fromUtf8(""))
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtGui.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 21))
self.menubar.setObjectName(_fromUtf8("menubar"))
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtGui.QStatusBar(MainWindow)
self.statusbar.setObjectName(_fromUtf8("statusbar"))
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None))
self.comboBox1.setItemText(0, _translate("MainWindow", "select", None))
self.comboBox1.setItemText(1, _translate("MainWindow", "a", None))
self.comboBox1.setItemText(2, _translate("MainWindow", "b", None))
self.comboBox1.setItemText(3, _translate("MainWindow", "c", None))
self.comboBox_2.setItemText(0, _translate("MainWindow", "select", None))
self.comboBox_2.setItemText(1, _translate("MainWindow", "p", None))
self.comboBox_2.setItemText(2, _translate("MainWindow", "q", None))
self.comboBox_2.setItemText(3, _translate("MainWindow", "r", None))
self.comboBox_2.setEnabled(0)
self.comboBox1.currentIndexChanged.connect(self.test)
def test(self):
s = str(self.comboBox1.currentText())
res=['aa','bb','cc','dd']
if (s == "- - select - -"):
self.comboBox_2.setEnabled(0)
self.comboBox_2.setCurrentIndex(0)
elif(len(s)== 0):
self.comboBox_2.setEnabled(1)
self.comboBox_2.clear()
self.comboBox_2.addItem("- - select - -")
self.comboBox_2.addItem("New Checklist")
else:
self.comboBox_2.setEnabled(1)
self.comboBox_2.clear()
self.comboBox_2.addItem("- - select - -")
self.comboBox_2.addItem("New Checklist")
self.comboBox_2.addItems(res)
self.comboBox_2.currentIndexChanged.connect(self.test1)
def test1(self):
print ("Hello")
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
MainWindow = QtGui.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
To understand the behavior we will use the following examples:
Example 1:
from PyQt4 import QtCore, QtGui
def on_clicked():
print("clicked")
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
button = QtGui.QPushButton("Press me")
for _ in range(4):
button.clicked.connect(on_clicked)
button.show()
sys.exit(app.exec_())
When you press the button it prints 4 times because Qt does not remember if there was already a connection between signal and a function previously, so if there are n connections between the same signal and function they will be invoked n times when the signal is emitted.
Example 2:
from PyQt4 import QtCore, QtGui
def on_currentIndexChanged(ix):
print("currentIndex:", ix)
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
combo = QtGui.QComboBox()
print("currentIndex:", combo.currentIndex())
combo.currentIndexChanged.connect(on_currentIndexChanged)
button_add = QtGui.QPushButton("Add Items")
button_add.clicked.connect(lambda: combo.addItems("1 2 3".split()))
button_clear = QtGui.QPushButton("Clear")
button_clear.clicked.connect(combo.clear)
w = QtGui.QWidget()
lay = QtGui.QVBoxLayout(w)
for widget in (combo, button_add, button_clear):
lay.addWidget(widget)
w.show()
sys.exit(app.exec_())
The default currentIndex of the QComboBox is -1, when you add items this changes to the currentIndex of 0, and when you clean the QComboBox the currentIndex reverts to -1. So when you add or clean the items, the currentIndexChanged signal is emitted.
Based on the above, I will explain the behavior that you point out: When a new currentIndex is selected in the QCombobox 1 the test method is invoked and if it enters the else statement after cleaning and adding the items you make the first connection, if the same thing is repeated now as there is a connection, the currentIndexChanged signal is emitted twice (one for clear() and another for addItems()) and you also create a second connection, if it is repeated again, the signal is emitted 4 times (1 clear() x 2 connections + 1 addItems() x 2 connections).
Solution:
Make the connection in a function that is invoked only once.
So that the clear() signal and addItems() do not emit the currentIndexChanged signal you must use blockSignals().
As an additional point it is recommended not to modify the code generated by Qt Designer, it is advisable to create another class that uses the initial class as an interface, in addition to using the decoration #QtCore.pyqtSlot().
from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName(_fromUtf8("MainWindow"))
MainWindow.resize(800, 600)
self.centralwidget = QtGui.QWidget(MainWindow)
self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
self.comboBox1 = QtGui.QComboBox(self.centralwidget)
self.comboBox1.setGeometry(QtCore.QRect(310, 150, 171, 31))
self.comboBox1.setObjectName(_fromUtf8("comboBox1"))
self.comboBox1.addItem(_fromUtf8(""))
self.comboBox1.addItem(_fromUtf8(""))
self.comboBox1.addItem(_fromUtf8(""))
self.comboBox1.addItem(_fromUtf8(""))
self.comboBox_2 = QtGui.QComboBox(self.centralwidget)
self.comboBox_2.setGeometry(QtCore.QRect(310, 240, 171, 41))
self.comboBox_2.setObjectName(_fromUtf8("comboBox_2"))
self.comboBox_2.addItem(_fromUtf8(""))
self.comboBox_2.addItem(_fromUtf8(""))
self.comboBox_2.addItem(_fromUtf8(""))
self.comboBox_2.addItem(_fromUtf8(""))
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtGui.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 21))
self.menubar.setObjectName(_fromUtf8("menubar"))
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtGui.QStatusBar(MainWindow)
self.statusbar.setObjectName(_fromUtf8("statusbar"))
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None))
self.comboBox1.setItemText(0, _translate("MainWindow", "select", None))
self.comboBox1.setItemText(1, _translate("MainWindow", "a", None))
self.comboBox1.setItemText(2, _translate("MainWindow", "b", None))
self.comboBox1.setItemText(3, _translate("MainWindow", "c", None))
self.comboBox_2.setItemText(0, _translate("MainWindow", "select", None))
self.comboBox_2.setItemText(1, _translate("MainWindow", "p", None))
self.comboBox_2.setItemText(2, _translate("MainWindow", "q", None))
self.comboBox_2.setItemText(3, _translate("MainWindow", "r", None))
class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.setupUi(self)
self.comboBox_2.setEnabled(False)
self.comboBox1.currentIndexChanged[str].connect(self.test)
self.comboBox_2.currentIndexChanged.connect(self.test1)
#QtCore.pyqtSlot(str)
def test(self, s):
res=['aa','bb','cc','dd']
if s == "- - select - -":
self.comboBox_2.setEnabled(False)
self.comboBox_2.setCurrentIndex(0)
elif not s:
self.comboBox_2.setEnabled(True)
self.comboBox_2.blockSignals(True)
self.comboBox_2.clear()
self.comboBox_2.addItem("- - select - -")
self.comboBox_2.addItem("New Checklist")
self.comboBox_2.blockSignals(False)
else:
self.comboBox_2.setEnabled(True)
self.comboBox_2.blockSignals(True)
self.comboBox_2.clear()
self.comboBox_2.addItem("- - select - -")
self.comboBox_2.addItem("New Checklist")
self.comboBox_2.addItems(res)
self.comboBox_2.blockSignals(False)
#QtCore.pyqtSlot(int)
def test1(self, ix):
print("Hello", ix)
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
I have a PyQt5 QTableWidget with two connected signals. One signal is meant to fire and print text to the screen when the user starts editing a cell in the table; the other is meant to fire and print text when the user finishes editing.
The latter works by connecting a function to the cellChanged signal; however, the cellActivated signal doesn't fire when the user starts editing a cell in the table.
To be clear: I want a catch-all signal for any time the cell editing starts (i.e. when the blinking cursor appears in a table cell indicating the user can now type in the cell). So connecting to the doubleClick signal will not do the trick. Although, I would settle for just having it fire when the user begins editing by pressing the enter key.
Here is my code:
from PyQt5 import QtCore, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(790, 472)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.tbwMain = QtWidgets.QTabWidget(self.centralwidget)
self.tbwMain.setGeometry(QtCore.QRect(0, 0, 801, 451))
self.tbwMain.setObjectName("tbwMain")
self.tabBoxes = QtWidgets.QWidget()
self.tabBoxes.setObjectName("tabBoxes")
self.horizontalLayoutWidget = QtWidgets.QWidget(self.tabBoxes)
self.horizontalLayoutWidget.setGeometry(QtCore.QRect(0, 0, 791, 421))
self.horizontalLayoutWidget.setObjectName("horizontalLayoutWidget")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget)
self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout.setObjectName("horizontalLayout")
spacerItem = QtWidgets.QSpacerItem(220, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.horizontalLayout.addItem(spacerItem)
self.tblBoxes = QtWidgets.QTableWidget(self.horizontalLayoutWidget)
self.tblBoxes.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
self.tblBoxes.setVerticalScrollMode(QtWidgets.QAbstractItemView.ScrollPerPixel)
self.tblBoxes.setRowCount(1)
self.tblBoxes.setObjectName("tblBoxes")
self.tblBoxes.setColumnCount(3)
item = QtWidgets.QTableWidgetItem()
self.tblBoxes.setHorizontalHeaderItem(0, item)
item = QtWidgets.QTableWidgetItem()
self.tblBoxes.setHorizontalHeaderItem(1, item)
item = QtWidgets.QTableWidgetItem()
self.tblBoxes.setHorizontalHeaderItem(2, item)
item = QtWidgets.QTableWidgetItem()
item.setTextAlignment(QtCore.Qt.AlignCenter)
self.tblBoxes.setItem(0, 0, item)
item = QtWidgets.QTableWidgetItem()
item.setTextAlignment(QtCore.Qt.AlignCenter)
self.tblBoxes.setItem(0, 1, item)
item = QtWidgets.QTableWidgetItem()
item.setTextAlignment(QtCore.Qt.AlignCenter)
self.tblBoxes.setItem(0, 2, item)
self.tblBoxes.horizontalHeader().setStretchLastSection(True)
self.tblBoxes.verticalHeader().setVisible(False)
self.horizontalLayout.addWidget(self.tblBoxes)
spacerItem1 = QtWidgets.QSpacerItem(220, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.horizontalLayout.addItem(spacerItem1)
self.tbwMain.addTab(self.tabBoxes, "")
MainWindow.setCentralWidget(self.centralwidget)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
self.tbwMain.setCurrentIndex(0)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
# - - - - -
self.tblBoxes.cellActivated.connect(self.test1)
self.tblBoxes.cellChanged.connect(self.test2)
def test1(self):
print('Start cell edit!')
def test2(self):
print('End cell edit!')
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_())
To reiterate, I'm looking for a solution for printing the text "Start Cell Edit" whenever a cell of the table begins to be edited.
There are several different ways to do this. One way is to reimplement the edit method of the table-widget, and emit a custom signal:
class TableWidget(QtWidgets.QTableWidget):
cellEditingStarted = QtCore.pyqtSignal(int, int)
def edit(self, index, trigger, event):
result = super(TableWidget, self).edit(index, trigger, event)
if result:
self.cellEditingStarted.emit(index.row(), index.column())
return result
However, if you're using Qt Designer, it might be preferrable to avoid sub-classing the table-widget, and use an item-delegate instead:
class ItemDelegate(QtWidgets.QStyledItemDelegate):
cellEditingStarted = QtCore.pyqtSignal(int, int)
def createEditor(self, parent, option, index):
result = super(ItemDelegate, self).createEditor(parent, option, index)
if result:
self.cellEditingStarted.emit(index.row(), index.column())
return result
class Ui_MainWindow(object):
...
def retranslateUi(self, MainWindow):
self.delegate = ItemDelegate(MainWindow)
self.delegate.cellEditingStarted.connect(self.test1)
self.tblBoxes.setItemDelegate(self.delegate)
self.tblBoxes.cellActivated.connect(self.test2)
I am developing an application using PyQt4 and Qt4Designer, I have designed from designer and generated python code. As you can see in the below image, when I am adding first row, it's occupying whole layout space, but later rows are of fixed width.
Image showing the actual problem
Here's my code...
main.py
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'pyqt.ui'
#
# Created by: PyQt4 UI code generator 4.11.4
#
# WARNING! All changes made in this file will be lost!
from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName(_fromUtf8("MainWindow"))
MainWindow.resize(983, 600)
MainWindow.setMinimumSize(QtCore.QSize(900, 600))
self.centralwidget = QtGui.QWidget(MainWindow)
self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
self.gridLayoutWidget = QtGui.QWidget(self.centralwidget)
self.gridLayoutWidget.setGeometry(QtCore.QRect(100, 90, 675, 441))
self.gridLayoutWidget.setObjectName(_fromUtf8("gridLayoutWidget"))
self.gridLayout = QtGui.QGridLayout(self.gridLayoutWidget)
self.gridLayout.setContentsMargins(0, -1, -1, -1)
self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
self.tableWidget = QtGui.QTableWidget(self.gridLayoutWidget)
self.tableWidget.setMinimumSize(QtCore.QSize(589, 439))
self.tableWidget.setObjectName(_fromUtf8("tableWidget"))
self.tableWidget.setColumnCount(4)
self.tableWidget.setRowCount(0)
item = QtGui.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(0, item)
item = QtGui.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(1, item)
item = QtGui.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(2, item)
item = QtGui.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(3, item)
self.tableWidget.horizontalHeader().setCascadingSectionResizes(False)
self.tableWidget.verticalHeader().setStretchLastSection(True)
self.gridLayout.addWidget(self.tableWidget, 0, 0, 1, 1)
self.label = QtGui.QLabel(self.centralwidget)
self.label.setGeometry(QtCore.QRect(100, 20, 85, 27))
self.label.setObjectName(_fromUtf8("label"))
self.AddTask = QtGui.QPushButton(self.centralwidget)
self.AddTask.setGeometry(QtCore.QRect(610, 20, 85, 27))
self.AddTask.setObjectName(_fromUtf8("AddTask"))
self.gridLayoutWidget.raise_()
self.label.raise_()
self.AddTask.raise_()
self.tableWidget.raise_()
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(_translate("MainWindow", "Stockroom Adidas", None))
self.tableWidget.setToolTip(_translate("MainWindow", "<html><head/><body><p>This is where you can add new jobs</p></body></html>", None))
item = self.tableWidget.horizontalHeaderItem(0)
item.setText(_translate("MainWindow", "Name", None))
item = self.tableWidget.horizontalHeaderItem(1)
item.setText(_translate("MainWindow", "SKU", None))
item = self.tableWidget.horizontalHeaderItem(2)
item.setText(_translate("MainWindow", "Size", None))
item = self.tableWidget.horizontalHeaderItem(3)
item.setText(_translate("MainWindow", "Status", None))
self.label.setText(_translate("MainWindow", "<html><head/><body><p><span style=\" font-size:14pt;\">Lobby</span></p></body></html>", None))
self.AddTask.setText(_translate("MainWindow", "Add Task", None))
app.py
from PyQt4.QtCore import QRegExp
from PyQt4.QtGui import QHeaderView
from PyQt4.QtGui import QTableWidgetItem
from main import Ui_MainWindow, QtCore, QtGui
import sys
from newtask import Ui_NewTask
class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
resolution = QtGui.QDesktopWidget().screenGeometry()
# positioning window to center
self.move((resolution.width() / 2) - (self.frameSize().width() / 2),
(resolution.height() / 2) - (self.frameSize().height() / 2))
self.setupUi(self)
# Customizing Columns in Table
rowHeader = self.tableWidget.horizontalHeader()
rowHeader.setResizeMode(0, QHeaderView.ResizeToContents)
rowHeader.setResizeMode(1, QHeaderView.Stretch)
rowHeader.setResizeMode(2, QHeaderView.Stretch)
rowHeader.setResizeMode(3, QHeaderView.ResizeToContents)
# self.tableWidget.resizeColumnsToContents()
# self.tableWidget.resizeRowsToContents()
# When clicked on Add Task button
def showDialog():
newdialog = NewTask(parent=self)
newdialog.show()
if newdialog.exec_():
# adding rows to the table
for i in range(len(newdialog.data)):
currentrow = self.tableWidget.rowCount()
self.tableWidget.insertRow(currentrow)
for j in range(len(newdialog.data[i])):
self.tableWidget.setItem(currentrow, j, newdialog.data[i][j])
self.AddTask.clicked.connect(showDialog)
header = self.tableWidget.verticalHeader()
header.setResizeMode(0, QHeaderView.Stretch)
# header.setDefaultSectionSize(12)
I have another class which inherits QDialog which has lot code, don't want to make this complex, not posting it... you can seee that when the AddTask button is clicked I am connecting the signal to showDialog function. There I am adding rows, I don't know where I am doing wrong, I have tried all the below possible ways.
self.tableWidget.resizeColumnsToContents()
self.tableWidget.resizeRowsToContents()
OR
header.setResizeMode(QHeaderView.Stretch)
OR
header.setResizeMode(QHeaderView.Fixed)
OR
self.tableWidget.rowHeight(20)
OR
self.tableWidget.resizeColumnsToContents()
self.tableWidget.resizeRowsToContents()
None of them worked... Please help...
EDIT1:
When I try to add rows in qtdesigner, facing the same problem, attaching the image here
QtDesigner
May be self.tableWidget.verticalHeader().setStretchLastSection(True) is causing problem.
Reading data in from a simple dict d={key:['desc',dateadded]}
Goal is to add data into table view and sort by date in the list. Cannot get any data to add when trying to put table on main window.
The issue lies with how I am placing the table on the main window. I have a working widget with table and am now trying to combine the two files. Currently the application crashes. Dont want you to write the code but a nudge in the right direction would be a big help.
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'display.ui'
#
# Created by: PyQt4 UI code generator 4.11.4
#
# WARNING! All changes made in this file will be lost!
from PyQt4.QtGui import (QMainWindow, QApplication)
from PyQt4 import QtCore, QtGui
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Ui_MainWindow(object):
def __init__(self):
#app = QApplication(sys.argv)
self.window = QMainWindow()
self.setupUi(self.window)
self.window.show()
self.setmydata()
def setupUi(self, MainWindow):
MainWindow.setObjectName(_fromUtf8("MainWindow"))
MainWindow.resize(296, 478)
MainWindow.setIconSize(QtCore.QSize(0, 0))
MainWindow.setAnimated(False)
MainWindow.setTabShape(QtGui.QTabWidget.Rounded)
self.centralwidget = QtGui.QWidget(MainWindow)
self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
self.tableView = QtGui.QTableView(self.centralwidget)
self.tableView.setGeometry(QtCore.QRect(20, 50, 261, 391))
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.tableView.sizePolicy().hasHeightForWidth())
self.tableView.setSizePolicy(sizePolicy)
self.tableView.setEditTriggers(QtGui.QAbstractItemView.AllEditTriggers)
self.tableView.setDragEnabled(True)
self.tableView.setAlternatingRowColors(True)
self.tableView.setSelectionMode(QtGui.QAbstractItemView.MultiSelection)
self.tableView.setSortingEnabled(False)
self.tableView.setObjectName(_fromUtf8("tableView"))
self.pushButton = QtGui.QPushButton(self.centralwidget)
self.pushButton.setGeometry(QtCore.QRect(20, 10, 121, 31))
self.pushButton.setObjectName(_fromUtf8("pushButton"))
self.pushButton_2 = QtGui.QPushButton(self.centralwidget)
self.pushButton_2.setGeometry(QtCore.QRect(160, 10, 121, 31))
self.pushButton_2.setObjectName(_fromUtf8("pushButton_2"))
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtGui.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 296, 21))
self.menubar.setObjectName(_fromUtf8("menubar"))
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtGui.QStatusBar(MainWindow)
self.statusbar.setObjectName(_fromUtf8("statusbar"))
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def setmydata(self):
d={"12345678":["do some stuff here that needs to be in a large cell to wrap text","1"],"12343378":["do stuff","1"]}
self.data = {}
keys=d.keys()
self.data['col1']=keys
self.data['col2']=[]
for key in keys:
self.data['col2'].append(d[key][0])
horHeaders = []
for n, key in enumerate(sorted(self.data.keys())):
horHeaders.append(key)
for m, item in enumerate(self.data[key]):
newitem = QTableWidgetItem(item)
self.setItem(m, n, newitem)
self.setHorizontalHeaderLabels(horHeaders)
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None))
self.pushButton.setText(_translate("MainWindow", "Add New", None))
self.pushButton_2.setText(_translate("MainWindow", "Save", None))
app = QApplication(sys.argv)
frame = Ui_MainWindow()
#frame.show()
app.exec_()
After digging through the code I found line
self.tableView = QtGui.QTableView(self.centralwidget)
needed to be QTableWidget rather than a View. This allows for me to set values and so on.
I've some data in mysql database and I want to display it into table using pyqt,
this is query from database (SELECT * FROM MONITORING).
Help me in displaying the contents of database inside the table widget.
Here is source code of my program :
from PyQt4 import QtCore, QtGui
import sys
import MySQLdb
from form.DBConnection import Connection
import MySQLdb as mdb
db = Connection()
myCursor = db.name().cursor()
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
try:
_efncoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName(_fromUtf8("MainWindow"))
MainWindow.resize(655, 356)
self.centralwidget = QtGui.QWidget(MainWindow)
self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
self.tbl_anggota = QtGui.QTableWidget(self.centralwidget)
self.tbl_anggota.setGeometry(QtCore.QRect(15, 40, 511, 192))
self.tbl_anggota.setObjectName(_fromUtf8("tbl_anggota"))
self.tbl_anggota.setColumnCount(5)
self.tbl_anggota.setRowCount(0)
item = QtGui.QTableWidgetItem()
self.tbl_anggota.setHorizontalHeaderItem(0, item)
item = QtGui.QTableWidgetItem()
self.tbl_anggota.setHorizontalHeaderItem(1, item)
item = QtGui.QTableWidgetItem()
self.tbl_anggota.setHorizontalHeaderItem(2, item)
item = QtGui.QTableWidgetItem()
self.tbl_anggota.setHorizontalHeaderItem(3, item)
item = QtGui.QTableWidgetItem()
self.tbl_anggota.setHorizontalHeaderItem(4, item)
self.bt_hapus = QtGui.QPushButton(self.centralwidget)
self.bt_hapus.setGeometry(QtCore.QRect(350, 250, 75, 23))
self.bt_hapus.setObjectName(_fromUtf8("bt_hapus"))
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtGui.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 655, 21))
self.menubar.setObjectName(_fromUtf8("menubar"))
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtGui.QStatusBar(MainWindow)
self.statusbar.setObjectName(_fromUtf8("statusbar"))
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None))
item = self.tbl_anggota.horizontalHeaderItem(0)
item.setText(_translate("MainWindow", "nim", None))
item = self.tbl_anggota.horizontalHeaderItem(1)
item.setText(_translate("MainWindow", "nama", None))
item = self.tbl_anggota.horizontalHeaderItem(2)
item.setText(_translate("MainWindow", "jabatan", None))
item = self.tbl_anggota.horizontalHeaderItem(3)
item.setText(_translate("MainWindow", "email", None))
item = self.tbl_anggota.horizontalHeaderItem(4)
item.setText(_translate("MainWindow", "nohp", None))
self.bt_hapus.setText(_translate("MainWindow", "Hapus", None))
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
MainWindow = QtGui.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
this is how I done that:
import sqlite3 as lite
...
cur = self.SQLiteDB.cursor()
cur.execute("SELECT * FROM SQLTable")
allSQLRows= cursor.fetchall()
self.myTableWidget.setRowCount(len(allSQLRows)) ##set number of rows
self.myTableWidget.setColumnCount(8) ##this is fixed for myTableWidget, ensure that both of your tables, sql and qtablewidged have the same number of columns
row = 0
while True:
sqlRow = cur.fetchone()
if sqlRow == None:
break ##stops while loop if there is no more lines in sql table
for col in range(0, 8): ##otherwise add row into tableWidget
self.myTableWidget.setItem(row, col, QtGui.QTableWidgetItem(sqlRow[col]))
row += 1