How to add tristate select box to QTreeView in PyQt5/PySide - pyqt5

I am using QTreeView rather than QTreeWidget. I would like to add a checkbox to each top level item to the left of the name (first item in row). When the top item is selected/deselected, all child items should be selected/deselected. When the selection state of a child item is changed to be different from the parent item, the parent item should be changed to tristate. I have found this answer, which is for a QTreeWidget. How is this done in a QTreeView? Current code can be seen below
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
class MyWidget(QWidget):
def __init__(self):
super(MyWidget, self).__init__()
self.tree = QTreeView(self)
self.tree.setAlternatingRowColors(True)
layout = QVBoxLayout(self)
layout.addWidget(self.tree)
self.model = QStandardItemModel()
self.model.setHorizontalHeaderLabels(['Name', 'Height', 'Weight'])
self.tree.header().setDefaultSectionSize(180)
self.tree.setModel(self.model)
self.populate_tree()
self.tree.expandAll()
def populate_tree(self):
self.model.setRowCount(0)
root = self.model.invisibleRootItem()
class1 = QStandardItem('Class 1')
class1.setFlags(class1.flags() | Qt.ItemIsTristate | Qt.ItemIsUserCheckable) #Doesn't work
class2 = QStandardItem('Class 2')
class1.setFlags(class2.flags() | Qt.ItemIsTristate | Qt.ItemIsUserCheckable)
root.appendRow(class1)
root.appendRow(class2)
class1.appendRow([
QStandardItem('Joe'),
QStandardItem('178'),
QStandardItem('76')
])
class1.appendRow([
QStandardItem('Judith'),
QStandardItem('165'),
QStandardItem('55')
])
class2.appendRow([
QStandardItem('Tobias'),
QStandardItem('180'),
QStandardItem('95')
])
if __name__ == '__main__':
app = QApplication(sys.argv)
view = MyWidget()
view.setGeometry(300, 100, 600, 300)
view.setWindowTitle('QTreeview Example')
view.show()
sys.exit(app.exec_())

Related

PyQt5: How to flip QGraphicsItem parent item only

I am trying to perform flipping on a QGraphicsItem that has child and grandchild QGraphicsItem.
The original item looks like this:
(The blue rectangle and text are child and the number inside it is grandchild
I apply the following transformation to the parent item:
parentItem.setTransformOriginPoint(parentItem.boundingRect().center())
parentItem.setTransform(QTransform.fromScale(-1, 1))
Result after flipping parent item:
Since I want to reflip the text and number to be readable, I attempt to re-flip them after the parent's transformation as followed:
# For the child text
child.setTransformOriginPoint(child.boundingRect().center())
child.setTransform(QTransform.fromScale(-1, 1), True)
...
# For the grandchild number
grandchild.setTransformOriginPoint(grandchild.boundingRect().center())
grandchild.setTransform(QTransform.fromScale(-1, 1), True)
Here is the result after re-flipped the child and grandchild item:
.
It seems that the translation is not correct. Can someone advice?
Thanks!
Minimal reproducible example below:
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
class ParentItem(QGraphicsRectItem):
def __init__(self, pos, name, parent=None):
w, h = 550, 220
super().__init__(-w/2, -h/2, w, h)
self.setPos(pos)
self.name = ChildText(self.boundingRect().topLeft() - QPointF(0, 100), f">NAME{name}", self)
self.value = ChildText(self.boundingRect().topLeft()- QPointF(0, 50), f">VALUE_{name}", self)
self.ChildPad1 = ChildPad(QPointF(-150, 0), "1", self)
self.ChildPad2 = ChildPad(QPointF(+150, 0), "2", self)
self.color = QColor(192, 192, 192)
self.setPen(QPen(self.color, 5))
self.setFlag(self.ItemIsMovable, True)
def flipParent(self):
self.setTransformOriginPoint(self.boundingRect().center())
self.setTransform(QTransform.fromScale(-1, 1))
def reflipChilds(self):
# Child Texts
self.name.setTransformOriginPoint(self.name.boundingRect().center())
self.name.setTransform(QTransform.fromScale(-1, 1))
self.value.setTransformOriginPoint(self.value.boundingRect().center())
self.value.setTransform(QTransform.fromScale(-1, 1))
# GrandChild Numbers
for child in self.childItems():
if isinstance(child, ChildPad):
child.Number.setTransformOriginPoint(child.Number.boundingRect().center())
child.Number.setTransform(QTransform.fromScale(-1, 1))
class ChildText(QGraphicsTextItem):
def __init__(self, pos, text=">Text", parent=None):
super().__init__(parent)
self.setPos(pos)
self.parent = parent
self.text = text
self.color = QColor(255, 0, 0)
self.setDefaultTextColor(self.color)
self.setFlag(self.ItemIsMovable, True)
f = QFont()
f.setPointSizeF(min(self.parent.boundingRect().width()/8, self.parent.boundingRect().height()/8))
self.setFont(f)
self.setHtml(f"<p><center>{self.text}</center></p>")
class ChildPad(QGraphicsRectItem):
def __init__(self, pos, pinNumber, parent=None):
w, h = 200, 100
super().__init__(-w/2, -h/2, w, h, parent)
self.setPos(pos)
self.parent = parent
self.color = QColor(255, 0, 0)
self.setPen(QPen(self.color, Qt.MiterJoin, 1))
self.setBrush(QBrush(self.color))
self.Number = GrandChildNumber(pinNumber, self)
class GrandChildNumber(QGraphicsTextItem):
def __init__(self, pinNumber, parent=None):
super().__init__(parent)
self.parent = parent
self.color = QColor(32, 32, 32)
self.setHtml(f"{pinNumber}")
self.moveToParentCenter()
def moveToParentCenter(self):
f = QFont()
f.setPointSizeF(min(self.parent.boundingRect().width()/4, self.parent.boundingRect().height()/4))
self.setFont(f)
rect = self.boundingRect()
rect.moveCenter(self.parent.boundingRect().center())
self.setPos(rect.topLeft())
self.adjustSize()
def main():
import sys
app = QtWidgets.QApplication(sys.argv)
scene = QGraphicsScene()
# No Transformation applied
originalItem = ParentItem(QPointF(300, 100), "ORIGINAL", scene)
scene.addItem(originalItem)
# Flipped the whole parent item
flipParentItem = ParentItem(QPointF(300, 500), "FLIPP_PARENT", scene)
flipParentItem.flipParent()
scene.addItem(flipParentItem)
# Flipped the whole parent item, then reflip the Text and Number
reflipChildItem = ParentItem(QPointF(300, 900), "REFLIP_CHILDS", scene)
flipParentItem.flipParent()
reflipChildItem.reflipChilds()
scene.addItem(reflipChildItem)
view = QtWidgets.QGraphicsView(scene)
view.setRenderHints(QtGui.QPainter.Antialiasing)
view.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
If you want to ignore transformations, you should use the ItemIgnoresTransformations flag.
Then, be aware that setTransformation() doesn't apply the transformation "on top" of the existing one, but completely sets a new transformation on the item (transforms inherited from the parent are not considered).
A proper flip() function should toggle the transformation, so it must consider the current transform() and flip it.
Now, the problem with text items is that they always use the origin point as the top left of their contents. While the basic repositioning might work for generic usage, it will not whenever any parent has a transformation.
The problem you're seeing is because you are just mapping the position based on the parent, but since the parent is "flipped", the top left corner of the resulting rect is on the opposite side (relative to the center) in parent coordinates.
To properly get the actual position relative to the parent, you must always use the cumulative transformations, which means map coordinates to the scene and map them back to the parent.
In order to make the code simpler to understand, I moved the repositioning function to the parent of the text item.
class ParentItem(QGraphicsRectItem):
# ...
def flip(self):
self.setTransformOriginPoint(self.boundingRect().center())
self.setTransform(self.transform().scale(-1, 1))
for child in self.childItems():
if isinstance(child, ChildPad):
child.updateNumber()
class ChildPad(QGraphicsRectItem):
def __init__(self, pos, pinNumber, parent=None):
w, h = 200, 100
super().__init__(-w/2, -h/2, w, h, parent)
self.setPos(pos)
self.parent = parent
self.color = QColor(255, 0, 0)
self.setPen(QPen(self.color, Qt.MiterJoin, 1))
self.setBrush(QBrush(self.color))
self.number = GrandChildNumber(pinNumber, self)
self.updateNumber()
def updateNumber(self):
br = self.boundingRect()
f = QFont()
f.setPointSizeF(min(br.width() / 4, br.height() / 4))
self.number.setFont(f)
# get the "visual" rect of the parent in scene coordinates
parentRect = self.mapToScene(br).boundingRect()
rect = self.number.boundingRect()
rect.moveCenter(parentRect.center())
# map the new rect position *from* the scene in local coordinates
topLeft = self.mapFromScene(rect.topLeft())
self.number.setPos(topLeft)
class GrandChildNumber(QGraphicsTextItem):
def __init__(self, pinNumber, parent=None):
super().__init__(parent)
self.parent = parent
self.setFlag(self.ItemIgnoresTransformations)
self.color = QColor(32, 32, 32)
self.setHtml(str(pinNumber))

Tkinter: How can I check if any of the widgets of a specific frame have changed?

What is the best way to check if any widget (or variable linked to it) of a given frame(frm1) has changed and take an action. For example activate a button.
I would like that when something was typed in the entries or changed the combobox or checkbox, the 'changed_content' function would be executed
from tkinter import *
from tkinter import ttk
from tkinter.messagebox import showinfo
class Defaultframe(Tk):
def __init__(self):
Tk.__init__(self)
self.geometry('500x300')
self.title('Tkinter')
self.text1 = StringVar()
self.text2 = StringVar()
self.text3 = StringVar()
self.var1 = IntVar()
self.var2 = IntVar()
self.set_widgets()
return
def changed_content(self):
showinfo('Information', 'The content has been changed')
self.btn2.configure(state='normal')
return
def set_widgets(self):
#Frame1
self.frm1 = ttk.Frame(self).pack(side=TOP)
self.lbl = ttk.Label(self.frm1, text='Text1').pack(pady=5)
self.ent1 = ttk.Entry(self.frm1, textvariable=self.text1).pack(pady=5)
self.lbl = ttk.Label(self.frm1, text='Text2').pack(pady=5)
self.my_ent = ttk.Entry(self.frm1, textvariable=self.text2).pack(pady=5)
self.cbb = ttk.Combobox(self.frm1,
values=[0, 30, 60, 90, 120, 150, 180],
state='readonly',
textvariable=self.var2)
self.cbb.pack(pady=5)
self.cbb.current(3)
self.ckb = ttk.Checkbutton(self.frm1, text='Hello', variable=self.var1, onvalue=1, offvalue=0).pack(pady=5)
#---
#Frame2
self.frm2 = ttk.Frame(self).pack(side=BOTTOM, fill=X)
ttk.Separator(self.frm2, orient=HORIZONTAL).pack(side=TOP, expand=1, fill=X)
self.my_ent3 = ttk.Entry(self.frm2, textvariable=self.text3).pack(side=LEFT, padx=1)
self.btn1 = ttk.Button(self.frm2, text='Cancel').pack(side=RIGHT, padx=1)
self.btn2 = ttk.Button(self.frm2, text='Save')
self.btn2.pack(side=RIGHT, padx=1)
self.btn2.configure(state=DISABLED)
#---
if __name__== '__main__':
app = Defaultframe()
app.mainloop()
Solving for any widget is tough - you'll have to write code specifically for a canvas or a scrollbar or any other widget that isn't associated with a tkinter variable.
For widgets that are associated with a tkinter variable you can apply a trace that will call a function whenever the value changes.
In your code it might look something like this:
class Defaultframe(Tk):
def __init__(self):
...
self._watch_variables(self.text1, self.text2, self.text3, self.var1, self.var2)
def _watch_variables(self, *vars):
for var in vars:
var.trace_add("write", self._handle_trace)
def _handle_trace(self, *args):
self.changed_content()

Pyqt5 synchronization between two tabwidget which are in different window

I want to make new window by double click tabwidget.
and copy tabwidget's (child which is tablewidget) to new window.
and finally, changing item of new window's tablewidget needs to change mainwindow's tablewidget.
would it be possible?
I have seen this, that answer does copy tabwidget to new window
but remove mainwindow tabwidget.
here is I worked so far.
I managed to make new dialog by double click, but other things.. I dont' have any clues. can anyone can help?
#!/usr/bin/python
# -*- coding: utf8 -*-
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
import sys
class DetachableTabWidget(QTabWidget):
def __init__(self, parent=None):
QTabWidget.__init__(self)
self.tabBar = self.TabBar(self)
self.tabBar.onDetachTabSignal.connect(self.detachTab)
self.setTabBar(self.tabBar)
print("DetachableTabWidget")
#pyqtSlot(int, QPoint)
def detachTab(self, index, point):
print("detachTab")
all_list = []
list1 = []
list2 = []
name = self.tabText(index)
icon = self.tabIcon(index)
if icon.isNull():
icon = self.window().windowIcon()
contentWidget = self.widget(index)
contentWidgetRect = contentWidget.frameGeometry()
tablewidgetA = contentWidget.findChild(QTableWidget)
for i in range(tablewidgetA.rowCount()):
list1.append(tablewidgetA.item(i, 0).text())
list2.append(tablewidgetA.item(i, 1).text())
all_list.append(list1)
all_list.append(list2)
detachedTab = self.DetachedTab(all_list)
detachedTab.setWindowModality(Qt.NonModal)
detachedTab.setWindowTitle(name)
detachedTab.setWindowIcon(icon)
detachedTab.setObjectName(name)
detachedTab.setGeometry(contentWidgetRect)
detachedTab.move(point)
detachedTab.exec_()
class DetachedTab(QDialog) :
onCloseSignal = pyqtSignal(QWidget,type(''), QIcon)
# def __init__(self, contentWidget, parent=None):
def __init__(self, all_list, parent=None) :
print("DetachedTab")
super().__init__()
layout = QVBoxLayout(self)
table = QTableWidget()
table.setColumnCount(len(all_list))
table.setRowCount(len(all_list[0]))
for col in range(len(all_list)) :
for row in range(len(all_list[col])) :
item = QTableWidgetItem(all_list[col][row])
table.setItem(row, col, item)
layout.addWidget(table)
table.show()
class TabBar(QTabBar):
onDetachTabSignal = pyqtSignal(int, QPoint)
onMoveTabSignal = pyqtSignal(int, int)
def __init__(self, parent=None):
QTabBar.__init__(self, parent)
self.setAcceptDrops(True)
self.setElideMode(Qt.ElideRight)
self.setSelectionBehaviorOnRemove(QTabBar.SelectLeftTab)
self.dragStartPos = QPoint()
self.dragDropedPos = QPoint()
self.mouseCursor = QCursor()
self.dragInitiated = False
def mouseDoubleClickEvent(self, event) :
event.accept()
self.onDetachTabSignal.emit(self.tabAt(event.pos()), self.mouseCursor.pos())
class SurfViewer(QMainWindow):
def __init__(self, parent=None):
super(SurfViewer, self).__init__()
self.parent = parent
self.centralTabs = DetachableTabWidget()
self.setCentralWidget(self.centralTabs)
self.setFixedWidth(600)
self.setFixedHeight(600)
#tab 1
self.tab_1 = QWidget()
self.centralTabs.addTab(self.tab_1,"Tab 1")
vbox = QVBoxLayout()
Table = QTableWidget(2, 2)
vbox.addWidget(Table)
item = QTableWidgetItem("table 1 content")
Table.setItem( 0, 0, item)
item = QTableWidgetItem("table 2 content")
Table.setItem( 0, 1, item)
item = QTableWidgetItem("table 3 content")
Table.setItem( 1, 0, item)
item = QTableWidgetItem("table 4 content")
Table.setItem( 1, 1, item)
vbox.setAlignment(Qt.AlignTop)
self.tab_1.setLayout(vbox)
#tab 2
self.tab_2 = QWidget()
self.centralTabs.addTab(self.tab_2,"Tab 2")
vbox = QVBoxLayout()
Table = QTableWidget(2, 2)
item = QTableWidgetItem("table 2 content")
Table.setItem( 0, 0, item)
item = QTableWidgetItem("table 3 content")
Table.setItem( 0, 1, item)
item = QTableWidgetItem("table 4 content")
Table.setItem( 1, 0, item)
item = QTableWidgetItem("table 5 content")
Table.setItem( 1, 1, item)
vbox.addWidget(Table)
vbox.setAlignment(Qt.AlignTop)
self.tab_2.setLayout(vbox)
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = SurfViewer(app)
ex.setWindowTitle('window')
ex.show()
sys.exit(app.exec_( ))
If you want to synchronize data between item views, you have to use a common model. Since you're using a QTableWidget (which has an internal, private model, and a higher level item view) you can create a new window using a QTableView instead, and set its model to the source. In that case, you don't need to "copy" row/column/data, you only need to use the source model.
Here's a modified version of your script:
class DetachableTabWidget(QTabWidget):
# ...
#pyqtSlot(int, QPoint)
def detachTab(self, index, point):
print("detachTab")
name = self.tabText(index)
icon = self.tabIcon(index)
if icon.isNull():
icon = self.window().windowIcon()
contentWidget = self.widget(index)
contentWidgetRect = contentWidget.frameGeometry()
tablewidgetA = contentWidget.findChild(QTableWidget)
detachedTab = self.DetachedTab(tablewidgetA.model())
detachedTab.setWindowTitle(name)
detachedTab.setWindowIcon(icon)
detachedTab.setObjectName(name)
detachedTab.setGeometry(contentWidgetRect)
detachedTab.move(point)
detachedTab.exec_()
class DetachedTab(QDialog) :
onCloseSignal = pyqtSignal(QWidget,type(''), QIcon)
def __init__(self, model, parent=None) :
print("DetachedTab")
super().__init__()
layout = QVBoxLayout(self)
table = QTableView()
table.setModel(model)
layout.addWidget(table)
table.show()
With this code you can modify the "child" window table data, and it will always synchronize the source table widget.

PyQt5: detect a new inserted tab with QTabWidget::tabInserted(int index)

I'm new in PyQt5. I made a tabWidget where I was able to connect a button to add tabs dynamically and remove/close them. Before inserting tabs with button.Clicked, there's one open (already inserted) tab saying "no tabs are open". I would like to close this tab after inserting a new tab and reopen the tab after closing all new tabs (when no tabs are open). I couldn't find any example on how to use QTabWidget::tabInserted(int index) from http://doc.qt.io/qt-5/qtabwidget.html. Does anyone know how to use tabInserted and tabRemoved to detect when triggered. I would like to increment each time a tab is inserted and decrement when removed, to know when there are open tabs and no open tabs. Thanks
self.toolButton.clicked.connect(self.button_addtab)
self.tabWidget.tabCloseRequested.connect(self.close_tab)
def button_addtab(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
self.tab_2 = QtWidgets.QWidget()
self.tab_2.setObjectName("tab_2")
self.tabWidget.addTab(self.tab_2, "")
self.tabWidget.setCurrentIndex(pages-0)
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), _translate("MainWindow", "Second_tab"))
def close_tab(self, index):
self.tabWidget.removeTab(index)
I tried this:
if self.tabWidget.count() <= 0:
#Add the "no tab open" tab
self.tab_3 = QtWidgets.QWidget()
self.tab_3.setObjectName("tab_3")
self.tabWidget.addTab(self.tab_3, "")
_translate = QtCore.QCoreApplication.translate
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_3), _translate("MainWindow", "Info"))
elif self.tabWidget.count() > 0:
self.tabWidget.removeTab(self.tabWidget.indexOf(self.tab_3))
This work, but it doesn't add after closing and it reopens after one more tab is added. That's why I would like to use tabInserted
See class TabWidget
import sys
from PyQt5.QtCore import Qt, QRect
from PyQt5.QtGui import QColor, QPainter
from PyQt5.QtWidgets import (QApplication, QWidget, QMainWindow, QAction,
QVBoxLayout, QTabWidget, QFileDialog, QPlainTextEdit, QHBoxLayout)
lineBarColor = QColor(53, 53, 53)
lineHighlightColor = QColor('#00FF04')
class TabWidget(QTabWidget):
def __init__(self, parent=None):
super(TabWidget, self).__init__(parent)
# This virtual handler is called after a tab was removed from position index.
def tabRemoved(self, index):
print("\n tab was removed from position index -> {}".format(index))
# This virtual handler is called after a new tab was added or inserted at position index.
def tabInserted(self, index):
print("\n New tab was added or inserted at position index -> {}".format(index))
class NumberBar(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.editor = parent
layout = QVBoxLayout(self)
self.editor.blockCountChanged.connect(self.update_width)
self.editor.updateRequest.connect(self.update_on_scroll)
self.update_width('001')
def mousePressEvent(self, QMouseEvent):
print("\n - class NumberBar(QWidget): \n\tdef mousePressEvent(self, QMouseEvent):")
def update_on_scroll(self, rect, scroll):
if self.isVisible():
if scroll:
self.scroll(0, scroll)
else:
self.update()
def update_width(self, string):
width = self.fontMetrics().width(str(string)) + 10
if self.width() != width:
self.setFixedWidth(width)
def paintEvent(self, event):
if self.isVisible():
block = self.editor.firstVisibleBlock()
height = self.fontMetrics().height()
number = block.blockNumber()
painter = QPainter(self)
painter.fillRect(event.rect(), lineBarColor)
painter.setPen(Qt.white)
painter.drawRect(0, 0, event.rect().width() - 1, event.rect().height() - 1)
font = painter.font()
current_block = self.editor.textCursor().block().blockNumber() + 1
while block.isValid():
block_geometry = self.editor.blockBoundingGeometry(block)
offset = self.editor.contentOffset()
block_top = block_geometry.translated(offset).top()
number += 1
rect = QRect(0, block_top, self.width() - 5, height)
if number == current_block:
font.setBold(True)
else:
font.setBold(False)
painter.setFont(font)
painter.drawText(rect, Qt.AlignRight, '%i' % number)
if block_top > event.rect().bottom():
break
block = block.next()
painter.end()
class Content(QWidget):
def __init__(self, text):
super(Content, self).__init__()
self.editor = QPlainTextEdit()
self.editor.setPlainText(text)
# Create a layout for the line numbers
self.hbox = QHBoxLayout(self)
self.numbers = NumberBar(self.editor)
self.hbox.addWidget(self.numbers)
self.hbox.addWidget(self.editor)
class MyTableWidget(QWidget):
def __init__(self, parent=None):
super(QWidget, self).__init__(parent)
self.layout = QVBoxLayout(self)
# Initialize tab screen
self.tabs = TabWidget() #QTabWidget()
self.tabs.resize(300, 200)
# Add tabs
self.tabs.setTabsClosable(True)
self.tabs.tabCloseRequested.connect(self.closeTab)
# Add tabs to widget
self.layout.addWidget(self.tabs)
self.setLayout(self.layout)
def closeTab(self, index):
tab = self.tabs.widget(index)
tab.deleteLater()
self.tabs.removeTab(index)
def addtab(self, content, fileName):
self.tabs.addTab(Content(str(content)), str(fileName))
class Main(QMainWindow):
def __init__(self, parent=None):
super(Main, self).__init__(parent)
self.open()
self.tabs = MyTableWidget()
self.setCentralWidget(self.tabs)
self.initUI()
self.show()
def initUI(self):
self.statusBar()
menu = self.menuBar()
fileMenu = menu.addMenu('File')
fileMenu.addAction(self.openAct)
self.resize(800, 600)
def closeTab(self, index):
tab = self.tabs.widget(index)
tab.deleteLater()
self.tabs.removeTab(index)
def buttonClicked(self):
self.tabs.addTab(Content("smalltext2"), "sadsad")
def open(self):
self.openAct = QAction('Open...', self)
self.openAct.setShortcut('Ctrl+O')
self.openAct.setStatusTip('Open a file')
self.is_opened = False
self.openAct.triggered.connect(self.openFile)
def openFile(self):
options = QFileDialog.Options()
filenames, _ = QFileDialog.getOpenFileNames(
self, 'Open a file', '',
'Python Files (*.py);;Text Files (*.txt)',
options=options
)
if filenames:
for filename in filenames:
with open(filename, 'r+') as file_o:
try:
text = file_o.read()
self.tabs.addtab(text, filename)
except Exception as e:
print("Error: filename=`{}`, `{}` ".format( filename, str(e)))
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Main()
sys.exit(app.exec_())

Set different background color in specific rows in QTableview

Hello, how i can change the background color in specific rows in QTableview?
I would like to know which method to use to make.
I have the method seleckRow but click another the color is not maintained in the selected row.
__author__ = 'jordiponsisala'
import sys
from PyQt5.QtWidgets import QDialog, QApplication
from PyQt5.QtSql import *
from PyQt5 import QtWidgets
from Llistats import modificarLineal
def crearConeccio():
db = QSqlDatabase.addDatabase("QMYSQL")
db.setHostName("localhost")
db.setDatabaseName("ProvaDB")
db.setUserName("root")
db.setPassword("password")
db.open()
print (db.lastError().text())
return True
class clasArticles(QDialog, modificarLineal.Ui_Dialog):
def __init__(self, parent=None):
super(clasArticles, self).__init__(parent)
self.setupUi(self)
self.setWindowTitle('Posu el nom que vulgui')
self.model= QSqlRelationalTableModel(self)
self.model.setTable('preu')
#self.model.setEditStrategy(QSqlRelationalTableModel.OnFieldChange)
self.model.setEditStrategy(QSqlTableModel.OnFieldChange)
self.model.setRelation(2,QSqlRelation("probeedors", "id", "nomProbeedor"))
self.model.select()
self.tableView.setModel(self.model)
self.tableView.setItemDelegate(QSqlRelationalDelegate(self.model))
self.tableView.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
self.tableView.selectRow(1)
self.filtrarLineal.clicked.connect(self.filtrarRecords)
self.cancelarLineal.clicked.connect(self.cancelRecords)
self.afegirLineal.clicked.connect(self.insertRecords)
self.eliminarLineal.clicked.connect(self.deleteRecords)
self.seleccionar.clicked.connect(self.seleccionarCodi)
self.tableView.doubleClicked.connect(self.probes_index)
self.tableView.activated.connect(self.actualitzarRecords)# Pres intro method
def probes_index(self):# metod for print index in row
indexes = self.tableView.selectionModel().selectedRows()
for index in sorted(indexes):
self.lblnomSeleccionat.setText(str(index.row()))
def seleccionarCodi(self):
index = self.tableView.selectedIndexes()[0]
id_seleccionat = str(self.tableView.model().data(index))
print ("index : " + str(id_seleccionat))
self.lblnomSeleccionat.setText(str(id_seleccionat))
def actualitzarRecords(self):
index_0 = self.tableView.selectedIndexes()[0]
index_id = str(self.tableView.model().data(index_0))
index_2 = self.tableView.selectedIndexes()[1]
index_probeedor_id = str(self.tableView.model().data(index_2))
index_3 = self.tableView.selectedIndexes()[3]
index_preuTarifa = str(self.tableView.model().data(index_3))
self.model = QSqlQueryModel(self)
self.model.setQuery("UPDATE `ProvaDB`.`preu` SET `preuTarifa`="+index_preuTarifa+" WHERE `id`="+index_id+" and`probeedors_id`="+index_probeedor_id+"")
def cancelRecords(self):
self.model.revertAll()
def insertRecords(self):
self.model.insertRow(self.tableView.currentIndex().row())
def deleteRecords(self):
self.model.removeRow(self.tableView.currentIndex().row())
self.model.submitAll()
def filtrarRecords(self):
self.model.setFilter("preu.id = '"+self.txtEditFiltre.text()+"%'")
if __name__ == '__main__':
app = QApplication(sys.argv)
if not crearConeccio():
sys.exit(1)
formMod = clasArticles()
formMod.show()
sys.exit(app.exec_())