How to get item selected from QListView in PyQt - python

I'm new to PyQt. So I'm trying to get selected item from QListView, I'm able to get selected items's index, but I'm not able to get the value of the index, can please someone help me.
Here is the code :
import sys
import os
from PyQt4 import QtCore, QtGui
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class asset(QtGui.QDialog):
def __init__(self,parent=None):
super(asset, self).__init__(parent)
self.assetList = QtGui.QListView(self)
self.assetList.clicked.connect(self.on_treeView_clicked)
######################################################################
# ----------------- ADD ITEMS----------------------------------------
######################################################################
list_data = listDirs('D:\\')
dir = listModel(list_data)
self.assetList.setModel(dir)
self.setStyleSheet('''
*{
background-color : rgb(65,65,65);
color : rgb(210,210,210);
alternate-background-color:rgb(55,55,55);
}
QTreeView,QListView,QLineEdit{
background-color : rgb(50,50,50);
color : rgb(210,210,210);
}
'''
)
self.setFocus()
#QtCore.pyqtSlot(QtCore.QModelIndex)
def on_treeView_clicked(self, index):
itms = self.assetList.selectedIndexes()
for it in itms:
print 'selected item index found at %s' % it.row()
class listModel(QAbstractListModel):
def __init__(self, datain, parent=None, *args):
""" datain: a list where each item is a row
"""
QAbstractListModel.__init__(self, parent, *args)
self.listdata = datain
def rowCount(self, parent=QModelIndex()):
return len(self.listdata)
def data(self, index, role):
if index.isValid() and role == Qt.DisplayRole:
return QVariant(self.listdata[index.row()])
else:
return QVariant()
def listDirs(*path):
completePath = os.path.join(*path)
dirs = os.listdir(os.path.abspath(completePath))
outputDir = []
for dir in dirs:
if os.path.isdir(os.path.join(completePath,dir)):
outputDir.append(dir)
return outputDir
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
app.setStyle('plastique')
main = asset()
main.resize(200,200)
main.show()
sys.exit(app.exec_())
Thanks !

You can use the convenience method data of QModelIndex. It returns a QVariant. Just convert it to something you'd use, like a QString with .toString:
print 'selected item index found at %s with data: %s' % (it.row(), it.data().toString())
By the way, QListView.clicked will give you the index. Unless you have multiple selection, or override the default selection behavior, it will be the only selected item. You don't need to loop over selectedIndexes():
#QtCore.pyqtSlot(QtCore.QModelIndex)
def on_treeView_clicked(self, index):
print 'selected item index found at %s with data: %s' % (index.row(), index.data().toString())

Related

PySide6: column of checkboxes for a boolean variable in a data table [duplicate]

How to make QAbstractTableModel 's data checkable
I want to make each cell in the following code can be checked or unchecked by the user ,how to modify the code ?
according to the Qt documentation :Qt::CheckStateRole and set the Qt::ItemIsUserCheckable might be used ,so anyone can give a little sample ?
import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *
class MyModel(QAbstractTableModel):
def __init__(self, parent=None):
super(MyModel, self).__init__(parent)
def rowCount(self, parent = QModelIndex()):
return 2
def columnCount(self,parent = QModelIndex()) :
return 3
def data(self,index, role = Qt.DisplayRole) :
if (role == Qt.DisplayRole):
return "Row{}, Column{}".format(index.row() + 1, index.column() +1)
return None
if __name__ == '__main__':
app =QApplication(sys.argv)
tableView=QTableView()
myModel = MyModel (None);
tableView.setModel( myModel );
tableView.show();
sys.exit(app.exec_())
Override the flags function in MyModel.
def flags(self, index)
return super(MyModel, self).flags(index)|QtCore.Qt.ItemIsUserCheckable
This says that the index in your model is checkable.
Then override the data function.
def data(self,index, role = Qt.DisplayRole) :
if (role == Qt.DisplayRole):
return "Row{}, Column{}".format(index.row() + 1, index.column() +1)
elif (role==Qt.CheckStateRole):
# read from your data and return Qt.Checked or Unchecked
return None
Finally, you need to implement the setData function.
def setData(self, index, value, role = Qt.EditRole):
if (role==Qt.CheckStateRole):
# Modify your data.

Exporting filter results QTableView (Python)

I have a Qtableview with a filter option using QLineEdit. It works ok except:
When i choose an index the filter doesn't look in the index.
Row 0 isn't visible
What i would like is to be able to export the filter results to another dataframe.
This is my code , i'm new at this son feel free to correct ;-)
import timeit
import pandas as pd
from PyQt5 import QtGui
from PyQt5.QtCore import Qt, QSortFilterProxyModel
class PandasTableModel(QtGui.QStandardItemModel):
def __init__(self, data, parent=None):
QtGui.QStandardItemModel.__init__(self, parent)
self._data = data
for col in data.columns:
data_col = [QtGui.QStandardItem("{}".format(x)) for x in data[col].values]
self.appendColumn(data_col)
return
def rowCount(self, parent=None):
return len(self._data.values)
def columnCount(self, parent=None):
return self._data.columns.size
def headerData(self, x, orientation, role):
if orientation == Qt.Horizontal and role == Qt.DisplayRole:
return self._data.columns[x]
if orientation == Qt.Vertical and role == Qt.DisplayRole:
return self._data.index[x]
return None
class Datahandler():
def __init__(self):
pass
def Load_Master_Data(self,tableMasterData,inputFilter):
print('Start Load_Master_Data')
start = timeit.default_timer()
Datafile = pd.read_pickle('modules/ssh/downloads/productsmaster.pkl')
df = pd.DataFrame(Datafile)
# df= df.set_index('Master_key')
self.inputfilter = inputFilter
self.tableMasterData = tableMasterData
self.df = df
self.model = PandasTableModel(df)
self.proxy_model = QSortFilterProxyModel()
self.proxy_model.setFilterKeyColumn(-1) # Search all columns.
self.proxy_model.setSourceModel(self.model)
self.proxy_model.sort(0, Qt.AscendingOrder)
self.proxy_model.setFilterCaseSensitivity(False)
self.tableMasterData.setModel(self.proxy_model)
inputFilter.textChanged.connect(self.proxy_model.setFilterFixedString)
end = timeit.default_timer()
print("Process Time: ",end-start)
Cheers , Johnson

QTableView model crash when calling endInsertRows()

I have been trying to update a QTableViewModel when inserting a new object that represents a row. I did follow the advise of several question in SO, but I cannot get an example to work.
After debugging, I found that the call to self.endInsertRows() produces the crash.
This is a minimal example:
import sys
from PyQt5.QtWidgets import *
from PyQt5 import QtCore, QtGui, QtWidgets
class Wire:
def __init__(self, name, x, y, gmr, r):
self.name = name
self.x = x
self.y = y
self.r = r
self.gmr = gmr
class WiresCollection(QtCore.QAbstractTableModel):
def __init__(self, parent=None):
QtCore.QAbstractTableModel.__init__(self, parent)
self.header = ['Name', 'R (Ohm/km)', 'GMR (m)']
self.index_prop = {0: 'name', 1: 'r', 2: 'gmr'}
self.wires = list()
def add(self, wire: Wire):
"""
Add wire
:param wire:
:return:
"""
row = len(self.wires)
self.beginInsertRows(QtCore.QModelIndex(), row, row)
self.wires.append(wire)
self.endInsertRows()
def delete(self, index):
"""
Delete wire
:param index:
:return:
"""
row = len(self.wires)
self.beginRemoveRows(QtCore.QModelIndex(), row, row)
self.wires.pop(index)
self.endRemoveRows()
def rowCount(self, parent=QtCore.QModelIndex()):
return len(self.wires)
def columnCount(self, parent=QtCore.QModelIndex()):
return len(self.header)
def parent(self, index=None):
return QtCore.QModelIndex()
def data(self, index, role=QtCore.Qt.DisplayRole):
if index.isValid():
if role == QtCore.Qt.DisplayRole:
val = getattr(self.wires[index.row()], self.index_prop(index.column()))
return str(val)
return None
def headerData(self, p_int, orientation, role):
if role == QtCore.Qt.DisplayRole:
if orientation == QtCore.Qt.Horizontal:
return self.header[p_int]
def setData(self, index, value, role=QtCore.Qt.DisplayRole):
"""
Set data by simple editor (whatever text)
:param index:
:param value:
:param role:
"""
wire = self.wires[index.row()]
attr = self.index_prop[index.column()]
setattr(wire, attr, value)
class TowerBuilderGUI(QtWidgets.QDialog):
def __init__(self, parent=None):
"""
Constructor
Args:
parent:
"""
QtWidgets.QDialog.__init__(self, parent)
self.setWindowTitle('Tower builder')
# GUI objects
self.setContextMenuPolicy(QtCore.Qt.NoContextMenu)
self.layout = QVBoxLayout(self)
self.wires_tableView = QTableView()
self.add_wire_pushButton = QPushButton()
self.add_wire_pushButton.setText('Add')
self.delete_wire_pushButton = QPushButton()
self.delete_wire_pushButton.setText('Delete')
self.layout.addWidget(self.wires_tableView)
self.layout.addWidget(self.add_wire_pushButton)
self.layout.addWidget(self.delete_wire_pushButton)
self.setLayout(self.layout)
# Model
self.wire_collection = WiresCollection(self)
# set models
self.wires_tableView.setModel(self.wire_collection)
# button clicks
self.add_wire_pushButton.clicked.connect(self.add_wire_to_collection)
self.delete_wire_pushButton.clicked.connect(self.delete_wire_from_collection)
def msg(self, text, title="Warning"):
"""
Message box
:param text: Text to display
:param title: Name of the window
"""
msg = QMessageBox()
msg.setIcon(QMessageBox.Information)
msg.setText(text)
# msg.setInformativeText("This is additional information")
msg.setWindowTitle(title)
# msg.setDetailedText("The details are as follows:")
msg.setStandardButtons(QMessageBox.Ok)
retval = msg.exec_()
def add_wire_to_collection(self):
"""
Add new wire to collection
:return:
"""
name = 'Wire_' + str(len(self.wire_collection.wires) + 1)
wire = Wire(name, x=0, y=0, gmr=0, r=0.01)
self.wire_collection.add(wire)
def delete_wire_from_collection(self):
"""
Delete wire from the collection
:return:
"""
idx = self.ui.wires_tableView.currentIndex()
sel_idx = idx.row()
if sel_idx > -1:
self.wire_collection.delete(sel_idx)
else:
self.msg('Select a wire in the wires collection')
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
window = TowerBuilderGUI()
window.show()
sys.exit(app.exec_())
As indicated in the comments you have 2 errors:
The first is when you press add because when you add a new item you have to refresh the view and that's why it's called data() method and it's where the error is shown in self.index_prop(index.column()), index_pro is a dictionary so you should use [] instead of ().
val = getattr(self.wires[index.row()], self.index_prop[index.column()])
Another error is generated by the line idx = self.ui.wires_tableView.currentIndex(), the ui does not exist and it is not necessary, sure it is a remnant of a previous code, to access wires_tableView as this is a member of the class not it is necessary to use an intermediary, you must access directly with self: idx = self.wires_tableView.currentIndex()
The above are typos and probably mark it so that the question is closed there is another error that is not, and that is the reason for my answer.
In the line self.beginRemoveRows(...) you must pass the row that you are going to remove but you are passing the row that does not exist:
row = len(self.wires)
self.beginRemoveRows(QtCore.QModelIndex(), row, row) # <---- row does not exist in the table
The solution is simple, change it by index:
def delete(self, index):
"""
Delete wire
:param index:
:return:
"""
self.beginRemoveRows(QtCore.QModelIndex(), index, index)
self.wires.pop(index)
self.endRemoveRows()

qtableview add rows from a query and edit them in python

i use Python 2.7, MariaDB and Qt4. I have a table in which i want to insert rows from a query. I tried self.model = QtSql.QSqlQueryModel() but i found that this is only read only. Then i moved to something else.
My Model() class looks like this:
class Model(QAbstractTableModel):
def __init__(self, parent=None, *args):
QAbstractTableModel.__init__(self, parent, *args)
query = QtSql.QSqlQuery()
query.prepare("SELECT denumire,pret_in,pret_out,cantitate,unitate_masura,tax FROM produse WHERE denumire='"+str(self.run_denumire())+"';")
query.exec_()
while(query.next()):
nume_produs = str(query.value(0).toString())
pret_in = str(query.value(1).toString())
pret_out = str(query.value(2).toString())
cantitate = str(query.value(3).toString())
unitate_masura = str(query.value(4).toString())
tax_tva = str(query.value(5).toString())
self.items = [nume_produs,pret_in,pret_out,cantitate,unitate_masura]
def rowCount(self, parent=QModelIndex()):
return 1
def columnCount(self, parent=QModelIndex()):
return len(self.items)
def data(self, index, role):
if not index.isValid(): return QVariant()
elif role != Qt.DisplayRole:
return QVariant()
column=index.column()
if column<len(self.items):
return QVariant(self.items[column])
else:
return QVariant()
def flags(self, index):
return Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsEditable
I am new to Qt and i don't know how to insert rows one by one to appear on table. What you see here is a code found by me here on stackoverflow and i modified it with a query . I need some help on this .
My main code is like this:
import time,os.path, os,module
from PyQt4 import QtGui, uic,QtSql,QtCore
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class dialog_receptie(QtGui.QDialog):
def __init__(self):
QtGui.QDialog.__init__(self)
file_path = os.path.abspath("ui/receptie.ui")
uic.loadUi(file_path, self)
self.move(QtGui.QApplication.desktop().screen().rect().center() - self.rect().center())
My ui file is:file
The file was made by Qt Designer.
Thank you.
UPDATE 1:
I inserted in class dialog_receptie a function. It looks like this:
def show_lista_receptie(self):
# self.model = QtSql.QSqlQueryModel()
# self.model.setQuery("SELECT den_produs,concat(pret_in,' Lei'),concat(pret_out,' Lei'),val_tva,cantitate,um FROM receptie_temp;")
self.model = QtSql.QSqlTableModel()
self.model.setTable("produse")
self.model.setQuery("SELECT * FROM receptie_temp;")
self.model.setHeaderData(1, QtCore.Qt.Horizontal, self.tr("Produs "))
self.model.setHeaderData(4, QtCore.Qt.Horizontal, self.tr("Pret cumparare "))
self.model.setHeaderData(5, QtCore.Qt.Horizontal, self.tr("Pret vanzare "))
self.model.setHeaderData(6, QtCore.Qt.Horizontal, self.tr("TVA Produs "))
self.model.setHeaderData(7, QtCore.Qt.Horizontal, self.tr("Cantitate "))
self.model.setHeaderData(11, QtCore.Qt.Horizontal, self.tr("UM "))
self.produse_view.setModel(self.model)
self.produse_view.hideColumn(0) # hide id column
self.produse_view.hideColumn(2)
self.produse_view.hideColumn(3)
self.produse_view.hideColumn(8)
self.produse_view.hideColumn(9)
self.produse_view.hideColumn(10)
self.produse_view.hideColumn(12)
If i use this line self.model.setQuery("SELECT * FROM receptie_temp;") i get an error message:
File "E:\onedrive\Documents\optimpos\module\receptie.py", line 64, in show_lista_receptie
self.model.setQuery("SELECT * FROM receptie_temp;")
TypeError: setQuery(self, QSqlQuery): argument 1 has unexpected type 'str'
How can query data from receptie_temp table without using an array? And how are the edited values in the table updated to the sql table?
Thank You.
I recommend using the QSqlTableModel class:
The QSqlTableModel class provides an editable data model for a single
database table.
In your case:
import os
import sys
from PyQt4 import QtGui, uic, QtSql
from PyQt4.QtGui import *
class dialog_receptie(QtGui.QDialog):
def __init__(self):
QtGui.QDialog.__init__(self)
file_path = os.path.abspath("ui/receptie.ui")
uic.loadUi(file_path, self)
# self.move(QtGui.QApplication.desktop().screen().rect().center() - self.rect().center())
db = QtSql.QSqlDatabase.addDatabase('QMYSQL')
db.setHostName(HOSTNAME);
db.setDatabaseName(DATABASE);
db.setUserName(USER);
db.setPassword(PASSWORD)
self.model = QtSql.QSqlTableModel()
self.model.setTable("produse")
self.produse_view.setModel(self.model)
self.produse_view.hideColumn(0) # hide id column
self.addData(["a", "b", "c", "d", "e", "f"])
def addData(self, data):
rec = self.model.record()
for i in range(6):
rec.setValue(rec.field(i+1).name(), data[i])
self.model.insertRecord(-1, rec)
if __name__ == '__main__':
app = QApplication(sys.argv)
w = dialog_receptie()
w.show()
sys.exit(app.exec_())

How do I get the Checked items in a Qlistview?

I've populated a Qlistview from a file, each line in the file becomes a row. Now, I'd like to have another function that creates another file from all the checked items in the qlistview. My listview goes as follows.
def show_list(self, file_in):
QListView.__init__(self)
QListView.setWindowFlags(self, QtCore.Qt.WindowStaysOnTopHint)
QListView.setWindowTitle(self, "ListView")
self.buttonBox = QtGui.QDialogButtonBox(self)
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok)
list_view = QListView(self)
list_view.setMinimumSize(350,350)
self.verticalLayout = QtGui.QVBoxLayout(self)
self.verticalLayout.addWidget(list_view)
self.verticalLayout.addWidget(self.buttonBox)
self.buttonBox.accepted.connect(self.close)
self.buttonBox.rejected.connect(self.close)
model = QStandardItemModel(list_view)
with open(file_in) as f:
if f is not None:
item = f.readlines()
for line in item:
item = QStandardItem(line)
item.setCheckable(True)
item.setCheckState(QtCore.Qt.Unchecked)
model.appendRow(item)
list_view.setModel(model)
list_view.show()
This is my attempt so far to get my desired result. Unfortunately, It doesn't print my checked items. When called like this self.print_checked_items(model) I'm wondering what could be wrong?
def print_checked_items(self, model):
path = "/home/test1/checked.txt"
for index in range(model.rowCount()):
item = model.item(index)
if item.isCheckable() and item.checkState() == QtCore.Qt.Checked:
with open(path, "a") as f_out:
print ('%s\n' % item.text())
f_out.write('%s\n' % item.text()
When I run this in Python 3.5 and PyQt5, it works fine, it prints the correct modes and checkmarked items. I removed the file reading/writing lines for testing. For PyQt4 and Python 2.7, you should just have to fix a couple of imports and the print statement. Run it, checkmark a couple items, and after 5 seconds what do you see in console?
from PyQt5 import QtCore
from PyQt5 import QtGui
from PyQt5.QtCore import QTimer
from PyQt5.QtWidgets import QApplication, QWizardPage, QListView
class AppRemovalPage(QWizardPage):
def __init__( self, parent ):
super(AppRemovalPage, self).__init__(parent)
self.setTitle('Apps to Remove')
self.setSubTitle('Listview')
self.list_view = QListView(self)
self.list_view.setMinimumSize(465, 200)
self.isWritten = False
loo = "/home/test1/file.txt"
self.model = QtGui.QStandardItemModel(self.list_view)
for line in ('a', 'b', 'c', 'd', 'e'):
self.item = QtGui.QStandardItem(line)
self.item.setCheckable(True)
self.item.setCheckState(QtCore.Qt.Unchecked)
self.model.appendRow(self.item)
self.list_view.setModel(self.model)
self.list_view.show()
def print_checked_items(self):
for index in range(self.model.rowCount()):
item = self.model.item(index)
if item.checkState() == QtCore.Qt.Checked:
if self.isWritten:
mode = "a"
else:
mode = "w"
self.isWritten = True
print ('%s' % item.text())
print("print checked items executed")
app = QApplication([])
listview = AppRemovalPage(None)
listview.show()
QTimer.singleShot(5000, listview.print_checked_items)
app.exec_()
If I checkmark a, c and d I see this:
a w
c a
d a
print checked items executed
Update to show how Python file object also works (and is in fact better code because it supports use of context management):
def print_checked_items(self):
path = "checked.txt"
mode = 'a' if self.isWritten else 'w'
if len(self.items) > 0:
with open(path, mode) as file:
for item in self.items:
print('%s' % item.text())
file.write(item.text() + "\n")
file.close()
print("print checked items executed")
The connection can be written wizard.button(QWizard.NextButton).clicked.connect(appremoval.print_checked_items)
import sys
from PyQt4 import QtGui
from PyQt4 import QtCore
class AppRemovalPage(QtGui.QWizardPage):
def __init__(self, parent=None):
super(AppRemovalPage, self).__init__(parent=parent)
self.setTitle('Apps to Remove')
self.setSubTitle('Listview')
self.list_view = QtGui.QListView(self)
self.list_view.setMinimumSize(465, 200)
layout = QtGui.QVBoxLayout(self)
layout.addWidget(self.list_view)
self.setLayout(layout)
self.items = []
self.isWritten = False
loo = "/home/test1/file.txt"
self.model = QtGui.QStandardItemModel(self.list_view)
self.model.itemChanged.connect(self.setItems)
file = QtCore.QFile(loo)
if file.open(QtCore.QFile.ReadOnly | QtCore.QFile.Text):
while not file.atEnd():
line = bytearray(file.readLine()).decode().strip()
item = QtGui.QStandardItem(line)
item.setCheckable(True)
item.setCheckState(QtCore.Qt.Unchecked)
self.model.appendRow(item)
self.list_view.setModel(self.model)
self.list_view.show()
def setItems(self, item):
if item.checkState() == QtCore.Qt.Checked:
self.items.append(item)
if item.checkState() == QtCore.Qt.Unchecked:
self.items.remove(item)
def print_checked_items(self):
path = "/home/test1/checked.txt"
mode = QtCore.QFile.Append if self.isWritten else QtCore.QFile.WriteOnly
if len(self.items) > 0:
file = QtCore.QFile(path)
if file.open(mode):
for item in self.items:
print('%s' % item.text())
file.write(item.text() + "\n")
file.close()
print("print checked items executed")
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
wizard = QtGui.QWizard()
appremoval = AppRemovalPage()
wizard.addPage(appremoval)
wizard.addPage(QtGui.QWizardPage())
wizard.button(QtGui.QWizard.NextButton).clicked.connect(appremoval.print_checked_items)
wizard.show()
sys.exit(app.exec_())
Output:
a
d
e
print checked items executed

Categories