The below code uses .ui from QtDesigner. If you run it with REPLACE_LISTVIEW_CLASS = False
, you get the "original" layout - so if you click the button, you get something like this:
However, I did not like the dotted selection line around the last selected item, once you click on an empty area in the list view to clear any selection.
So, I implemented the class from Clear selection when clicking on blank area of Item View - and since I want to keep the .ui, I have to change the list view class in the __init__
by replacing the widget. That works in principle, and can be seen if you run the code with REPLACE_LISTVIEW_CLASS = True
:
... however, as it is clear from the above screenshot - all the settings that were set on the list view widget in Qt designer are now lost: not just the font, but also the ExtendedSelection setting (the widget reverts to SingleSelection).
So my question is - is there an easy way to copy all of the settings from the original widget to the subclassed widget, before the original widget is deleted?
test.py
:
import sys
from PyQt5 import QtCore, QtWidgets, QtGui, uic
from PyQt5.QtCore import pyqtSlot
REPLACE_LISTVIEW_CLASS = True # False # True
class MyListView(QtWidgets.QListView): # https://stackoverflow.com/q/8516163
def keyPressEvent(self, event):
if (event.key() == QtCore.Qt.Key_Escape and
event.modifiers() == QtCore.Qt.NoModifier):
self.selectionModel().clear()
else:
super(MyListView, self).keyPressEvent(event)
def mousePressEvent(self, event):
if not self.indexAt(event.pos()).isValid():
self.selectionModel().clear()
super(MyListView, self).mousePressEvent(event)
class MyMainWindow(QtWidgets.QMainWindow):
def __init__(self):
super(MyMainWindow, self).__init__()
uic.loadUi('test.ui', self)
self.listview_model = QtGui.QStandardItemModel()
self.listView.setModel(self.listview_model)
self.pushButton.clicked.connect(self.on_pushButton_click)
if REPLACE_LISTVIEW_CLASS:
# to change widget class - replace the widget:
list_view_real = MyListView()
listView_parent_layout = self.listView.parent().layout()
listView_parent_layout.replaceWidget(self.listView, list_view_real)
self.listView.deleteLater() # must delete the old manually, else it still shows after replaceWidget!
# nice - reassignment like this works, but all old styling is lost!
self.listView = list_view_real
self.listView.setModel(self.listview_model)
self.show()
@pyqtSlot()
def on_pushButton_click(self):
self.listview_model.appendRow( QtGui.QStandardItem("Lorem ipsum") )
self.listview_model.appendRow( QtGui.QStandardItem("dolor sit amet,") )
self.listview_model.appendRow( QtGui.QStandardItem("consectetur ") )
self.listview_model.appendRow( QtGui.QStandardItem("adipiscing elit, ...") )
def main():
app = QtWidgets.QApplication(sys.argv)
window = MyMainWindow()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
test.ui
:
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QListView" name="listView">
<property name="font">
<font>
<family>Palatino Linotype</family>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::ExtendedSelection</enum>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton">
<property name="text">
<string>Hello!</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>21</height>
</rect>
</property>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources/>
<connections/>
</ui>