Posts: 78
Threads: 27
Joined: Jan 2017
How can I change the color of a row of QTableView which has as model a QStandardItemModel?
I tried this with no success:
index = self.games_model.index(0, 0)
model.setData(index, QtCore.Qt.red, QtCore.Qt.BackgroundRole)
model.emit(QtCore.SIGNAL('dataChanged(QModelIndex)'), index)
Posts: 78
Threads: 27
Joined: Jan 2017
May-25-2017, 06:44 AM
(This post was last modified: May-25-2017, 06:45 AM by panoss.)
I changed the 'QtCore.Qt.red' to 'QBrush(Qt.red)' and works!
Here is a small working example:
from PyQt4 import QtGui, QtCore
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys
def main():
app = QApplication(sys.argv)
w = MyWindow()
w.show()
sys.exit(app.exec_())
class MyWindow(QTableView):
def __init__(self, *args):
QTableView.__init__(self, *args)
model = QtGui.QStandardItemModel(0, 2)
self.setModel(model)
for i in range(0,6):
newRow = model.rowCount();
model.insertRow(newRow);
# paint first two rows
for i in range(0, 2):
model.setData(model.index(i, 0), QBrush(Qt.red), QtCore.Qt.BackgroundRole)
model.setData(model.index(i, 1), QBrush(Qt.red), QtCore.Qt.BackgroundRole)
if __name__ == "__main__":
main() But I do have a question:
when I comment out the line 'from PyQt4.QtCore import *', I get an error 'Qt unresolved reference' even though I have the line 'from PyQt4 import QtGui, QtCore'.
So, what is the proper way to import QtCore without having to import it twice?
Posts: 7,319
Threads: 123
Joined: Sep 2016
May-25-2017, 01:25 PM
(This post was last modified: May-25-2017, 01:25 PM by snippsat.)
It's good to get rid of import * .
It's annoying that many think that * is okay when using a GUI framework,it's really not
So have to add QtGui, QtCore to all plasses * has taken it away.
Don't like to see main first in code.
from PyQt4 import QtGui, QtCore
import sys
class MyWindow(QtGui.QTableView):
def __init__(self, *args):
QtGui.QTableView.__init__(self, *args)
model = QtGui.QStandardItemModel(0, 2)
self.setModel(model)
for i in range(0, 6):
newRow = model.rowCount()
model.insertRow(newRow)
# paint first two rows
for i in range(0, 2):
model.setData(model.index(i, 0), QtGui.QBrush(
QtCore.Qt.red), QtCore.Qt.BackgroundRole)
model.setData(model.index(i, 1), QtGui.QBrush(
QtCore.Qt.red), QtCore.Qt.BackgroundRole)
def main():
app = QtGui.QApplication(sys.argv)
w = MyWindow()
w.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
Posts: 78
Threads: 27
Joined: Jan 2017
May-29-2017, 08:34 AM
(This post was last modified: May-29-2017, 08:35 AM by panoss.)
I 'm trying to do the same with QSqlQueryModel but it doesn't work!
Here is a compilable code sample:
import sys
from PyQt4 import QtGui, QtCore, QtSql
def main():
app = QtGui.QApplication(sys.argv)
w = MyWindow()
w.show()
sys.exit(app.exec_())
class MyWindow(QtGui.QTableView):
def __init__(self, *args):
QtGui.QTableView.__init__(self, *args)
# connect to db (if doesn't exist, it's auto-created)
self.db = QtSql.QSqlDatabase.addDatabase('QSQLITE')
self.db.setDatabaseName('test.db')
self.db.open()
#create a table in db and add some data
query = QtSql.QSqlQuery()
query.exec_("DROP TABLE IF EXISTS games")
query.exec_("CREATE TABLE games(id INTEGER PRIMARY KEY, hometeam TEXT, visitorteam TEXT) ")
query.exec("INSERT INTO games (hometeam, visitorteam) VALUES ('Star', 'Eagles')")
query.exec("INSERT INTO games (hometeam, visitorteam) VALUES ('Best team', 'Reds');")
# set the model
model = QtSql.QSqlQueryModel(self)#QtGui.QStandardItemModel(0, 2)
self.setModel(model)
model.setQuery("SELECT * FROM games")
# paint first two rows
for i in range(0, 2):
model.setData(model.index(i, 0), QtGui.QBrush(QtCore.Qt.red), QtCore.Qt.BackgroundRole)
model.setData(model.index(i, 1), QtGui.QBrush(QtCore.Qt.red), QtCore.Qt.BackgroundRole)
if __name__ == "__main__":
main() What could be the problem?
Posts: 78
Threads: 27
Joined: Jan 2017
I subclassed it:
class ColorfullSqlQueryModel(QtSql.QSqlQueryModel):
def __init__(self, dbcursor=None):
super(ColorfullSqlQueryModel, self).__init__()
def data(self, QModelIndex, role=None):
v = QtSql.QSqlQueryModel.data(self, QModelIndex, role);
if role == QtCore.Qt.BackgroundRole:
return QtGui.QColor(QtCore.Qt.yellow)
return (v); It works!! Turns all rows to yellow!
But how can I make it paint only the rows I want?
How can I pass the color to function data?
Posts: 78
Threads: 27
Joined: Jan 2017
May-30-2017, 09:24 AM
(This post was last modified: May-30-2017, 09:24 AM by panoss.)
Finally, I ended in a, relatively, good solution:
from PyQt4 import QtGui, QtCore, QtSql
#from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys
def main():
app = QtGui.QApplication(sys.argv)
w = MyWindow()
w.show()
sys.exit(app.exec_())
class MyWindow(QtGui.QTableView):
def __init__(self, *args):
QtGui.QTableView.__init__(self, *args)
# connect to db (if doesn't exist, it's auto-created)
self.db = QtSql.QSqlDatabase.addDatabase('QSQLITE')
self.db.setDatabaseName('test.db')
self.db.open()
#create a table in db and add some data
query = QtSql.QSqlQuery()
query.exec_("DROP TABLE IF EXISTS games")
query.exec_("CREATE TABLE games(id INTEGER PRIMARY KEY, hometeam TEXT, visitorteam TEXT) ")
query.exec("INSERT INTO games (hometeam, visitorteam) VALUES ('Star', 'Eagles')")
query.exec("INSERT INTO games (hometeam, visitorteam) VALUES ('Best team', 'Reds');")
query.exec("INSERT INTO games (hometeam, visitorteam) VALUES ('NonWinners', 'Loosers');")
query.exec("INSERT INTO games (hometeam, visitorteam) VALUES ('North', 'South');")
query.exec("INSERT INTO games (hometeam, visitorteam) VALUES ('East', 'west');")
# set the model
model = ColorfullSqlQueryModel(self)#QtGui.QStandardItemModel(0, 2)
self.setModel(model)
model.setQuery("SELECT * FROM games")
# paint first two rows
model.setRowsToBeColored([0,3])
for i in range(0, 2):
index = QtCore.QModelIndex(model.index(i, 0))
model.setData(index, QtCore.Qt.red, QtCore.Qt.BackgroundRole)
class ColorfullSqlQueryModel(QtSql.QSqlQueryModel):
def __init__(self, dbcursor=None):
super(ColorfullSqlQueryModel, self).__init__()
def setRowsToBeColored(self, rows):
self.rows = rows
def data(self, index, role):
row = index.row()
print("row=", row, " row in self.rows=", row in self.rows)
if role == QtCore.Qt.BackgroundRole and row in self.rows:
return QBrush(QtCore.Qt.red)
return QtSql.QSqlQueryModel.data(self, index, role);
if __name__ == "__main__":
main()
Posts: 78
Threads: 27
Joined: Jan 2017
Jun-07-2017, 12:00 PM
(This post was last modified: Jun-07-2017, 12:00 PM by panoss.)
I 'm trying to 'translate' c++ to python.
With some help from qt forum, I got to this (it's compilable):
from PyQt4 import QtGui, QtCore, QtSql
from PyQt4.QtCore import QModelIndex, QByteArray, QDataStream, QIODevice
from PyQt4.QtGui import *
import sys
QString = type("")
from past.builtins import unicode
def main():
app = QtGui.QApplication(sys.argv)
w = MyWindow()
w.show()
sys.exit(app.exec_())
class MyWindow(QtGui.QTableView):
def __init__(self, *args):
QtGui.QTableView.__init__(self, *args)
# connect to db (if doesn't exist, it's auto-created)
self.db = QtSql.QSqlDatabase.addDatabase('QSQLITE')
self.db.setDatabaseName('test.db')
self.db.open()
#create a table in db and add some data
query = QtSql.QSqlQuery()
query.exec_("DROP TABLE IF EXISTS games")
query.exec_("CREATE TABLE games(id INTEGER PRIMARY KEY, hometeam TEXT, visitorteam TEXT) ")
query.exec("INSERT INTO games (hometeam, visitorteam) VALUES ('Star', 'Eagles')")
query.exec("INSERT INTO games (hometeam, visitorteam) VALUES ('Best team', 'Reds');")
query.exec("INSERT INTO games (hometeam, visitorteam) VALUES ('NonWinners', 'Loosers');")
query.exec("INSERT INTO games (hometeam, visitorteam) VALUES ('North', 'South');")
query.exec("INSERT INTO games (hometeam, visitorteam) VALUES ('East', 'west');")
# set the model
model = QtSql.QSqlQueryModel(self)
model.setQuery("SELECT * FROM games")
# paint first two rows
for i in range(0, 2):
index = QtCore.QModelIndex(model.index(i, 0))
model.setData(index, QtCore.Qt.red, QtCore.Qt.BackgroundRole)
# create the proxy model
proxy_model = ExtraRolesProxyModel(self) # QtGui.QStandardItemModel(0, 2)
# set the proxy 's source
proxy_model.setSourceModel(model)
# set the proxy as TableView 's source
self.setModel(proxy_model)
class ExtraRolesProxyModel(QIdentityProxyModel):
def __init__(self, dbcursor=None):
super(ExtraRolesProxyModel, self).__init__()
self.m_extraRoles = dict()
def data(self, index, role):
if role == QtCore.Qt.BackgroundRole: role_str = "BackgroundRole"
if role == QtCore.Qt.DisplayRole: role_str = "DisplayRole"
print("ExtraRolesProxyModel data was called row=", index.row(), " role=", role)
hashKey = QByteArray()
keyStream = QDataStream(hashKey, QIODevice.WriteOnly)
keyStream.writeInt32(index.row())
keyStream.writeInt32(index.column())
keyStream.writeInt32(role)
#if self.m_extraRoles.has_key(hashKey):
if hashKey in self.m_extraRoles:
hashKey = unicode([QString(u'hashKey')])
return self.m_extraRoles[hashKey]
return QIdentityProxyModel.data(self, index, role)
def setData(self, index, value, role=None):
print("ExtraRolesProxyModel setData was called=")
if not index.isValid():
return False
hashKey = QByteArray()
keyStream = QDataStream(hashKey, QIODevice.WriteOnly)
keyStream.writeInt32(index.row())
keyStream.writeInt32(index.column())
keyStream.writeInt32(role)
print("value=", value)
if value.isValid():
self.m_extraRoles[hashKey] = value
self.dataChanged.emit(index, index)
return True
#if self.m_extraRoles.has_key(hashKey):
if hashKey not in self.m_extraRoles:
del self.m_extraRoles[hashKey]
self.dataChanged.emit(index, index)
return True
return False
if __name__ == "__main__":
main() The original c++ code for the class ExtraRolesProxyModel is this:
Q_OBJECT
Q_DISABLE_COPY(ExtraRolesProxyModel)
public:
explicit ExtraRolesProxyModel(QObject* parent=Q_NULLPTR)
:QIdentityProxyModel(parent)
{}
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE{
const qint64 hashKey = (static_cast<qint64>(index.row()) << 32) | static_cast<qint64>(index.column());
auto tableIter = m_extraRoles.constFind(hashKey);
if(tableIter==m_extraRoles.constEnd())
return QIdentityProxyModel::data(index,role);
auto roleIter = tableIter.value().constFind(role);
if(roleIter==tableIter.value().constEnd())
return QIdentityProxyModel::data(index,role);
return roleIter.value();
}
virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) Q_DECL_OVERRIDE {
if(!index.isValid())
return false;
Q_ASSERT(index.model()==this);
const qint64 hashKey = (static_cast<qint64>(index.row()) << 32) | static_cast<qint64>(index.column());
if(value.isValid()){
m_extraRoles[hashKey][role] = value;
emit dataChanged(index,index,QVector<int>(1,role));
return true;
}
auto tableIter = m_extraRoles.find(hashKey);
if(tableIter==m_extraRoles.end())
return false;
auto roleIter = tableIter.value().find(role);
if(roleIter==tableIter.value().end())
return false;
tableIter.value().erase(roleIter);
if(tableIter.value().isEmpty())
m_extraRoles.erase(tableIter);
emit dataChanged(index,index,QVector<int>(1,role));
return true;
}
private:
QHash<qint64,QHash<qint32,QVariant> > m_extraRoles;
}; Well, python code does not make colored rows.
Can you spot any problems in the 'tranlsation'?
Posts: 1
Threads: 0
Joined: Sep 2017
Hi Panoss,
I saw your post about colouring some rows in your qsqltablemodel. I have managed to colour some my rows using the data() mathod and make them uneditable with the flag method. Before I did this my model was editable and could automatically update my table. However soon as i color some columns, it my edits just disappear soon as I move to next Field. Have u came across this problem before and if so, how did u get around it.
Thanks
|