This question already has an answer here:
How to expand top-level QTreeview items
(1 answer)
Closed 3 years ago.
How can I expand a QTreeView item knowing it's modelIndex. I'm trying to call the following piece of code and it doesn't throw any errors but it does not expand the treeview item...
parentIndex = self.categoryModel.indexFromItem(parent)
if parentIndex.isValid():
self.uiTreeView.setExpanded(parentIndex, True)
To test, select the first item in the list and click the Add button. When a user adds a new category i want it to expand the item it's being added to.
import os, sys
from Qt import QtWidgets, QtGui, QtCore
################################################################################
# Widgets
################################################################################
class CategoryView(QtWidgets.QWidget):
def __init__(self):
QtWidgets.QWidget.__init__(self)
self.resize(250,400)
self.uiAdd = QtWidgets.QPushButton('Add')
self.categoryModel = QtGui.QStandardItemModel()
self.categoryModel.setHorizontalHeaderLabels(['Items'])
self.categoryProxyModel = QtCore.QSortFilterProxyModel()
self.categoryProxyModel.setSourceModel(self.categoryModel)
self.categoryProxyModel.setFilterCaseSensitivity(QtCore.Qt.CaseInsensitive)
self.categoryProxyModel.setSortCaseSensitivity(QtCore.Qt.CaseInsensitive)
self.categoryProxyModel.setDynamicSortFilter(True)
self.uiTreeView = QtWidgets.QTreeView()
self.uiTreeView.setModel(self.categoryProxyModel)
self.uiTreeView.sortByColumn(0, QtCore.Qt.AscendingOrder)
self.uiTreeView.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
self.layout = QtWidgets.QVBoxLayout()
self.layout.setContentsMargins(0,0,0,0)
self.layout.setSpacing(0)
self.layout.addWidget(self.uiAdd)
self.layout.addWidget(self.uiTreeView)
self.setLayout(self.layout)
# Selections
self.categorySelection = self.uiTreeView.selectionModel()
# Signals
self.uiAdd.clicked.connect(self.slotAddNewCategory)
parent = self.categoryModel.invisibleRootItem()
parent.appendRow(QtGui.QStandardItem('Fruit'))
# Methods
def getSelectedItems(self):
items = []
for proxyIndex in self.categorySelection.selectedIndexes():
sourceIndex = self.categoryProxyModel.mapToSource(proxyIndex)
item = self.categoryModel.itemFromIndex(sourceIndex)
items.append(item)
return items
def slotAddNewCategory(self):
text, ok = QtWidgets.QInputDialog.getText(self, 'Input Dialog', 'Enter your name:')
if ok:
item = QtGui.QStandardItem(text)
parent = self.categoryModel.invisibleRootItem()
items = self.getSelectedItems()
if len(items) == 1:
parent = items[0]
parent.appendRow(item)
parentIndex = self.categoryModel.indexFromItem(parent)
print parentIndex.data()
if parentIndex.isValid():
self.uiTreeView.setExpanded(parentIndex, True)
################################################################################
# Unit Testing
################################################################################
def test_CategoryView():
app = QtWidgets.QApplication(sys.argv)
ex = CategoryView()
ex.show()
sys.exit(app.exec_())
if __name__ == '__main__':
pass
test_CategoryView()
# test_PainterSettingsDialog()
Answer found here... How to expand top-level QTreeview items
parentIndex = self.categoryModel.indexFromItem(parent)
px = self.categoryProxyModel.mapFromSource(parentIndex)
if parentIndex.isValid():
self.uiTreeView.setExpanded(px, True)
Related
I am trying to make a simple input form that accepts certain inputs and shows output in a table.
As per the code, I get the following output.
But I am looking for the following output.
Following is the code snippet that I have attempted.
import sys
from PyQt5.QtWidgets import *
from PyQt5 import QtCore, QtGui
from PyQt5.QtGui import *
from PyQt5.QtCore import *
# Subclass QMainWindow to customize your application's main window
class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setWindowTitle("Check Distance Travelled By Vehicles")
self.vehicleNamelbl = QLabel('VehicleName : ')
self.vehicleNamecombo = QComboBox()
self.vehicleNamecombo.addItem('SwitftDzire')
self.dateEdit = QDateEdit()
self.dateEdit.__init__(calendarPopup=True)
self.dateEdit.setDateTime(QtCore.QDateTime.currentDateTime())
self.dateEdit.editingFinished.connect(lambda: date_method())
self.petrolCB = QCheckBox('Petrol')
self.petrolCB.setChecked(True)
self.dieselCB = QCheckBox('Diesel')
self.dieselCB.setChecked(False)
self.petrolCB.stateChanged.connect(self.checkpetrolCB)
self.dieselCB.stateChanged.connect(self.checkdieselCB)
self.submitBtn = QPushButton('Submit ')
# adding action to the date when enter key is pressed
self.submitBtn.clicked[bool].connect(self.collecInput)
grid = QGridLayout()
grid.setSpacing(10)
grid.addWidget(self.vehicleNamelbl,1,0)
grid.addWidget(self.vehicleNamecombo,1,1)
grid.addWidget(self.dateEdit,1,2)
grid.addWidget(self.petrolCB,1,3)
grid.addWidget(self.dieselCB,1,4)
grid.addWidget(self.submitBtn,1,5)
# geometry of the main window
qtRectangle = self.frameGeometry()
# center point of screen
centerPoint = QDesktopWidget().availableGeometry().center()
# move rectangle's center point to screen's center point
qtRectangle.moveCenter(centerPoint)
# top left of rectangle becomes top left of window centering it
self.move(qtRectangle.topLeft())
self.setLayout(grid)
self.show()
# method called by date edit
def date_method():
print('Inside date_method')
# getting the date
value = self.dateEdit.date()
print(value)
print(value.toPyDate())
def checkpetrolCB(self,checked):
if checked :
print('Petrol Vehicle Is Selected')
self.OdFlag = 1
else:
print('Petrol Vehicle Is De-Selected')
def checkdieselCB(self,checked):
if checked :
print('Diesel Vehicle Is Selected')
self.OdFlag = 2
else:
print('Diesel Vehicle Is De-Selected')
def collecInput(self) :
print('Submit Button Pressed!! Inputs Selected')
print(self.vehicleNamecombo.currentText())
print(self.dateEdit.date().toPyDate())
if self.petrolCB.isChecked() == True and self.dieselCB.isChecked() == False :
print('Petrol Vehicle Is Selected')
if self.dieselCB.isChecked() == True and self.petrolCB.isChecked() == False :
print('Diesel Vehicle Is Selected')
if self.petrolCB.isChecked() == True and self.dieselCB.isChecked() == True :
print('Both Petrol And Diesel Vehicle Are Selected')
msgBox = QMessageBox()
msgBox.setIcon(QMessageBox.Critical)
msgBox.setText('Select Either Petrol Or Diesel')
msgBox.setWindowTitle("Alert PopUp")
returnValue = msgBox.exec_()
return
# Call A Module To Get The List Of Files Present As per The Input
vehicleFileList = [ 'dist_SwitftDzire_CityA.13OCT2020','dist_SwitftDzire_CityB.13OCT2020','dist_SwitftDzire_CityC.13OCT2020']
print('Back to collecInput')
print(vehicleFileList)
print('Num Of Files Found : '+str(len(vehicleFileList)))
numOfFiles = len(vehicleFileList)
if numOfFiles == 0 : # No Files Have Been Detected
print('No Files Found')
msgBox = QMessageBox()
msgBox.setIcon(QMessageBox.Critical)
msgBox.setText('No Files Found')
msgBox.setWindowTitle("Alert PopUp")
returnValue = msgBox.exec_()
else: # Atleast 1 File Is Detected
print('Populating table entries')
table = MyTable(vehicleFileList, numOfFiles, 2, self)
# add Qt.Window to table's flags
table.setWindowFlags(table.windowFlags() | Qt.Window)
table.show()
class MyTable(QTableWidget):
def __init__(self, vehicleFileList, *args):
QTableWidget.__init__(self, *args)
self.data = vehicleFileList
self.setWindowFlags(Qt.WindowStaysOnTopHint)
self.resizeColumnsToContents()
self.resizeRowsToContents()
self.horizontalHeader().setStretchLastSection(False)
self.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
self.setHorizontalHeaderLabels(['Available Vehicle Data Files','Missing Files'])
print('Inside MyTable')
print(vehicleFileList)
rowCount=0
for item in vehicleFileList :
print(item)
self.setItem(rowCount,0,QTableWidgetItem(item))
rowCount+=1
def main():
app = QApplication(sys.argv)
window = MainWindow()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
What changes do I need to make to get the window positioning of my choice?
Note: The second window is not a child of the first window.
The idea is to calculate the geometry of the first window and use that information to modify the geometry of the second window:
table = MyTable(vehicleFileList, numOfFiles, 2, self)
# add Qt.Window to table's flags
table.setWindowFlags(table.windowFlags() | Qt.Window)
table.resize(self.width(), table.sizeHint().height())
table.window().move(self.geometry().bottomLeft())
table.show()
what I need in this case is "uncheck or check" the items in QListView with mouse hold and press
I've added Items with check boxes , I need to change the state of the items (check or uncheck) for multi items with just press and hold , like making multi selection .
from PyQt4.QtGui import *
from PyQt4.QtCore import *
import sys
class items_List(QListView):
clicked = pyqtSignal()
def __init__(self,items):
QListView.__init__(self)
#self.setSelectionMode(QAbstractItemView.ExtendedSelection)
self.model = QStandardItemModel()
self.setModel(self.model)
self.model.itemChanged.connect(self.on_itemChanged)
self.items = items
self.add_items_(self.items)
self.show()
def add_items_(self,all_items=None):
self.active_items = []
if all_items == None:
return
for item in all_items:
#self.model.appendRow(str(i))
self.item = QStandardItem(str(item))
self.item.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled | Qt.ItemIsSelectable)
self.item.setData(QVariant(Qt.Checked), Qt.CheckStateRole)
self.model.appendRow(self.item)
self.active_items.append(str(item))
def selected_item(self):
print "Selected "
#pyqtSlot(QStandardItem)
def on_itemChanged(self, item):
state = ['UNCHECKED', 'TRISTATE', 'CHECKED'][item.checkState()]
if state == 'UNCHECKED':
self.active_items.remove(item.text())
else:
if item.text() not in self.active_items:
self.active_items.append(str(item.text()))
print self.active_items
def main():
app = QApplication(sys.argv)
items = [1001,1002,1003,1004,1005]
win = items_List(items)
sys.exit(app.exec_())
if __name__ == "__main__":
main()
I have a QListWidget with custom widgets. I am seeing an issue where if I do the following:
add two items
Remove the second item
Add another item
then the first item's widget contents disappears until I either resize the window, or add a third item.
import sys
from PySide.QtGui import *
from PySide.QtCore import *
class StagingWidget(QGroupBox):
def __init__(self,parent=None):
#QWidget.__init__(self,parent)
super(StagingWidget,self).__init__()
self.itemWidgets = list()
self.count = 1
self.createUi()
def createUi(self):
self.widget_layout=QVBoxLayout(self)
self.list_widget=QListWidget()
self.setFixedWidth(450)
self.setFixedHeight(600)
self.list_widget.setStyleSheet("QListWidget::item:selected{background:lightblue}")
self.widget_layout.addWidget(self.list_widget)
self.buttonHLayout = QHBoxLayout()
self.add = QPushButton("Add Item")
self.add.clicked.connect(self.addListItem)
self.buttonHLayout.addWidget(self.add)
self.widget_layout.addLayout(self.buttonHLayout)
def addListItem(self):
itemN = QListWidgetItem()
widget = QWidget()
Button1 = QPushButton(str(self.count))
Button2 = QPushButton("Remove")
Button2.clicked.connect(lambda item=itemN:self.removeJob(item))
widgetLayout = QHBoxLayout()
widgetLayout.addWidget(Button1)
widgetLayout.addWidget(Button2)
widget.setLayout(widgetLayout)
itemN.setSizeHint(widget.sizeHint())
self.itemWidgets.append(widget)
self.list_widget.addItem(itemN)
self.list_widget.setItemWidget(itemN, self.itemWidgets[-1])
self.count = self.count + 1
def removeJob(self,item):
print("Removing Job")
row = self.list_widget.indexFromItem(item).row()
self.list_widget.takeItem(row)
if __name__ == '__main__':
app = QApplication(sys.argv)
widget = StagingWidget()
widget.show()
sys.exit(app.exec_())
Example:
Add 1 item:
Add another item:
Remove item 2:
Add another item(You can see widget of item 1 disappear):
Add another item(Widget of item 1 reappears):
This happens every single time I do the above steps.
I have a simple QTreeWidget :
self.treeWidget = QTreeWidget(self)
col = ("Status", "Name")
self.treeWidget.setColumnCount(2)
self.treeWidget.setHeaderLabels(col)
witch I populate using :
wid = Custom_Widget()
item = QTreeWidgetItem(self.treeWidget)
item.setText(1, "some string")
item.treeWidget().setItemWidget(item, 0, wid)
I can easly acces the text column by using :
root = self.treeWidget.invisibleRootItem()
it = root.child(2) # for example the third item
it.setText(1, "Edited")
what i need is to edit the costum_widget in column 0, so how can i access it or invoke his methods ?
I resolved the issue by keeping a list of all the costum_widgets that i create, my code would be :
from CustomWidgets import Custom_Widget
from PyQt5.QtWidgets import *
import sys
class MyExample(QWidget):
def __init__(self):
super().__init__()
self.treeWidget = QTreeWidget(self)
self.group_wid = [] # my list of widgets
col = ("Status", "Name")
self.treeWidget.setColumnCount(2)
self.treeWidget.setHeaderLabels(col)
self.populate_tree()
self.edit_tree()
self.show()
def populate_tree(self):
for i in range(10):
wid = Custom_Widget()
self.group_wid.append(wid) # each time i instantiate a Custom_Widget i'll add it to my list of widgets
item = QTreeWidgetItem(self.treeWidget)
item.setText(1, "some string")
item.treeWidget().setItemWidget(item, 0, wid)
def edit_tree(self):
root = self.treeWidget.invisibleRootItem()
it = root.child(2) # for example the third item
it.setText(1, "Edited")
self.group_wid[2].my_method() # i can easily edit my widgets that are in the QTreeWidget
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = MyExample()
app.exec_()
Guess the QtreeWidgetItem only hold a reference to the widgets that are contained.
How can I edit the label of a horizontal header in a qtablewidget by double clicking on it?
What I have so far but does not work. So when someone doubleclicks the top header, a linedit pops up allows for text and then resets the label.
import sys
from PyQt4 import QtGui,QtCore
import generate_file
class WebGetMain(QtGui.QMainWindow,generate_file):
def __init__(self,parent=None):
super(WebGetMain,self).__init__(parent)
self.setupUi(self)
#set these values customizable before user populates the table
self.row_count = 20
self.col_count = 20
#setup actual cols,rows
self.web_get_table.setRowCount(self.row_count)
self.web_get_table.setColumnCount(self.col_count)
#allow horizontal header to be altered
#create and initialize linedit
self.linedit = QtGui.QLineEdit(parent=self.web_get_table.viewport())
self.linedit.setAlignment(QtCore.Qt.AlignTop)
self.linedit.setHidden(True)
self.linedit.editingFinished.connect(self.doneEditing)
#connect double click action on header
self.web_get_table.connect(self.web_get_table.horizontalHeader(),QtCore.SIGNAL('sectionDoubleClicked(int)'),self.on_header_doubleClicked)
#setup vertical scrollbars for adding rows
self.vBar = self.web_get_table.verticalScrollBar()
self._vBar_lastVal = self.vBar.value()
#initialize cols,rows
for column in range(0, 2):
for row in range(0, 3):
print row, column
item = QtGui.QTableWidgetItem()
self.web_get_table.setItem(row, column, item)
#scrollbar value signal to detect for scrolling
self.vBar.valueChanged.connect(self.scrollbarChanged)
def scrollbarChanged(self, val):
#initialize scrollbar
bar = self.vBar
minVal, maxVal = bar.minimum(), bar.maximum()
avg = (minVal+maxVal)/2
rowCount = self.web_get_table.rowCount()
# scrolling down
if val > self._vBar_lastVal and val >= avg:
self.web_get_table.insertRow(rowCount)
# scrolling up
elif val < self._vBar_lastVal:
lastRow = rowCount-20
empty = True
for col in xrange(self.web_get_table.columnCount()):
item = self.web_get_table.item(lastRow, col)
if item and item.text():
empty=False
break
if empty:
#remove rows when scrolling up
self.web_get_table.removeRow(lastRow)
self._vBar_lastVal = val
def doneEditing(self):
self.linedit.blockSignals(True)
self.linedit.setHidden(True)
oldname = self.web_get_table.model().dataset.field(self.sectionedit)
newname = str(self.linedit.text())
self.web_get_table.model().dataset.changeFieldName(oldname,newname)
self.linedit.setText('')
self.web_get_table.setCurrentIndex(QtCore.QModelIndex())
def on_header_doubleClicked(self,item):
self.linedit.setText(self.web_get_table.model().field(item).name)
self.linedit.setHidden(False)
self.linedit.blockSignals(False)
self.linedit.setFocus()
self.linedit.selectAll()
self.sectionedit = item
def main():
app = QtGui.QApplication(sys.argv)
app.setStyle(QtGui.QStyleFactory.create("Plastique"))
main_window = WebGetMain()
main_window.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
To be honest, I couldn't figure out what you're trying to do with that QLineEdit. But as far as I can see, you are halfway there. Using sectionDoubleClicked signal of the horizontalHeader() is a good start. But the rest is a big question mark for me.
All you need to do is this: Get the header item with horizontalHeaderItem(index) and use text to get the value or setText to set the new value.
And you might consider QInputDialog.getText to obtain the new value from the user.
Here is a minimal example that shows this:
import sys
from PyQt4 import QtGui
class MyWindow(QtGui.QWidget):
def __init__(self, parent=None):
super(MyWindow, self).__init__(parent)
self.table = QtGui.QTableWidget(5,5)
self.table.setHorizontalHeaderLabels(['1', '2', '3', '4', '5'])
self.table.setVerticalHeaderLabels(['1', '2', '3', '4', '5'])
self.table.horizontalHeader().sectionDoubleClicked.connect(self.changeHorizontalHeader)
layout = QtGui.QHBoxLayout()
layout.addWidget(self.table)
self.setLayout(layout)
def changeHorizontalHeader(self, index):
oldHeader = self.table.horizontalHeaderItem(index).text()
newHeader, ok = QtGui.QInputDialog.getText(self,
'Change header label for column %d' % index,
'Header:',
QtGui.QLineEdit.Normal,
oldHeader)
if ok:
self.table.horizontalHeaderItem(index).setText(newHeader)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
main = MyWindow()
main.show()
sys.exit(app.exec_())
I found this answer from mechsin on QtCentre and it worked for me:
http://www.qtcentre.org/threads/12835-How-to-edit-Horizontal-Header-Item-in-QTableWidget
See last comment in the thread. In summary, it creates a QLineEdit in the viewport of the table header. A slot for double-clicking the header shows the line edit in the proper position and width to cover the header section. A slot for finishing the line edit hides the line edit and captures its text value for the header item.