PyQt: how to create a multiline list widget? [duplicate] - python

how can i create a QListWidgetItem that has 1 image and 2 labels/strings underneath, that have support for css?
this is the last thing i have tried:
class CustomListWidgetItem(QListWidgetItem, QLabel):
def __init__(self, parent=None):
QListWidgetItem.__init__(self, parent)
QLabel.__init__(self, parent)
i'm using PyQt btw

how can i create a QListWidgetItem that has 1 image and 2
labels/strings underneath, that have support for css?
In this case, you can't (it actually has an API for adding icons easily, but two labels/strings is impossible). But, you can create your own custom widget and put it into QtGui.QListWidget.
Create your custom widget.
Create your QtGui.QListWidget in the main application.
Create a custom widget object and set item in QListWidgetItem by QListWidgetItem is in QtGui.QListWidget by using the QListWidget.setItemWidget (self, QListWidgetItem item, QWidget widget) method.
This is an example to explain my solution:
import sys
from PyQt4 import QtGui
class QCustomQWidget (QtGui.QWidget):
def __init__ (self, parent = None):
super(QCustomQWidget, self).__init__(parent)
self.textQVBoxLayout = QtGui.QVBoxLayout()
self.textUpQLabel = QtGui.QLabel()
self.textDownQLabel = QtGui.QLabel()
self.textQVBoxLayout.addWidget(self.textUpQLabel)
self.textQVBoxLayout.addWidget(self.textDownQLabel)
self.allQHBoxLayout = QtGui.QHBoxLayout()
self.iconQLabel = QtGui.QLabel()
self.allQHBoxLayout.addWidget(self.iconQLabel, 0)
self.allQHBoxLayout.addLayout(self.textQVBoxLayout, 1)
self.setLayout(self.allQHBoxLayout)
# setStyleSheet
self.textUpQLabel.setStyleSheet('''
color: rgb(0, 0, 255);
''')
self.textDownQLabel.setStyleSheet('''
color: rgb(255, 0, 0);
''')
def setTextUp (self, text):
self.textUpQLabel.setText(text)
def setTextDown (self, text):
self.textDownQLabel.setText(text)
def setIcon (self, imagePath):
self.iconQLabel.setPixmap(QtGui.QPixmap(imagePath))
class exampleQMainWindow (QtGui.QMainWindow):
def __init__ (self):
super(exampleQMainWindow, self).__init__()
# Create QListWidget
self.myQListWidget = QtGui.QListWidget(self)
for index, name, icon in [
('No.1', 'Meyoko', 'icon.png'),
('No.2', 'Nyaruko', 'icon.png'),
('No.3', 'Louise', 'icon.png')]:
# Create QCustomQWidget
myQCustomQWidget = QCustomQWidget()
myQCustomQWidget.setTextUp(index)
myQCustomQWidget.setTextDown(name)
myQCustomQWidget.setIcon(icon)
# Create QListWidgetItem
myQListWidgetItem = QtGui.QListWidgetItem(self.myQListWidget)
# Set size hint
myQListWidgetItem.setSizeHint(myQCustomQWidget.sizeHint())
# Add QListWidgetItem into QListWidget
self.myQListWidget.addItem(myQListWidgetItem)
self.myQListWidget.setItemWidget(myQListWidgetItem, myQCustomQWidget)
self.setCentralWidget(self.myQListWidget)
app = QtGui.QApplication([])
window = exampleQMainWindow()
window.show()
sys.exit(app.exec_())
Note: I have image file icon.png, size 48 x 48 pixel.
QListWidget.setItemWidget
Experimental result

Related

How to have two widgets in one Main window

I am trying the whole morning already to fix that.
So I have a PyQt Main Window where I want to display two widgets.
In the first widget there are articles listed (which works so far).
When I click on them until now a QMessageBox is opening, but I want that
a second widget is opening where I can read the RSS Feed.
But this is not working. See Code below:
class ArticleWidgets(QWidget):
def __init__(self, *args):
super().__init__(*args)
self.setGeometry(610, 610, 600, 600)
self.initUi()
def initUi(self):
self.box = QHBoxLayout(self)
def show(self, feed=None):
self.title = QLabel()
self.summary = QLabel()
self.link = QLabel()
if feed:
self.title.setText(feed[0])
self.summary.setText(feed[1])
self.link.setText(feed[2])
self.box.addWidget(self.title)
self.box.addWidget(self.summary)
self.box.addWidget(self.link)
self.setLayout(self.box)
class TitleWidgets(QWidget):
def __init__(self, *args):
super().__init__(*args)
self.setGeometry(10, 10, 600, 600)
self.initUi()
def initUi(self):
vbox = QHBoxLayout(self)
self.titleList = QListWidget()
self.titleList.itemDoubleClicked.connect(self.onClicked)
self.titleList.setGeometry(0, 0, 400, 400)
self.news = ANFFeed()
for item in self.news.all_feeds:
self.titleList.addItem(item[0])
vbox.addWidget(self.titleList)
def onClicked(self, item):
feeds = self.news.all_feeds
id = 0
for elem in range(len(feeds)):
if feeds[elem][0] == item.text():
id = elem
summary = feeds[id][1] + '\n\n'
link = feeds[id][2]
if feeds and id:
#ANFApp(self).show_articles(feeds[id])
show = ANFApp()
show.show_articles(feed=feeds[id])
QMessageBox.information(self, 'Details', summary + link)
class ANFApp(QMainWindow):
def __init__(self, *args):
super().__init__(*args)
self.setWindowState(Qt.WindowMaximized)
self.setWindowIcon(QIcon('anf.png'))
self.setAutoFillBackground(True)
self.anfInit()
self.show()
def anfInit(self):
self.setWindowTitle('ANF RSS Reader')
TitleWidgets(self)
#article_box = ArticleWidgets(self)
exitBtn = QPushButton(self)
exitBtn.setGeometry(600, 600, 100, 50)
exitBtn.setText('Exit')
exitBtn.setStyleSheet("background-color: red")
exitBtn.clicked.connect(self.exit)
def show_articles(self, feed=None):
present = ArticleWidgets()
present.show(feed)
def exit(self):
QCoreApplication.instance().quit()
Solution using Pyqtgraph's Docks and QTextBrowser
Here is a code trying to reproduce your sketch. I used the Pyqtgraph module (Documentation here: Pyqtgraph's Documentation and Pyqtgraph's Web Page) because its Dock widget is easier to use and implement from my perspective.
You must install the pyqtgraph module before trying this code:
import sys
from PyQt5 import QtGui, QtCore
from pyqtgraph.dockarea import *
class DockArea(DockArea):
## This is to prevent the Dock from being resized to te point of disappear
def makeContainer(self, typ):
new = super(DockArea, self).makeContainer(typ)
new.setChildrenCollapsible(False)
return new
class MyApp(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
central_widget = QtGui.QWidget()
layout = QtGui.QVBoxLayout()
central_widget.setLayout(layout)
self.setCentralWidget(central_widget)
label = QtGui.QLabel('This is a label, The widgets will be below')
label.setMaximumHeight(15)
## The DockArea as its name says, is the are where we place the Docks
dock_area = DockArea(self)
## Create the Docks and change some esthetic of them
self.dock1 = Dock('Widget 1', size=(300, 500))
self.dock2 = Dock('Widget 2', size=(400, 500))
self.dock1.hideTitleBar()
self.dock2.hideTitleBar()
self.dock1.nStyle = """
Dock > QWidget {
border: 0px solid #000;
border-radius: 0px;
}"""
self.dock2.nStyle = """
Dock > QWidget {
border: 0px solid #000;
border-radius: 0px;
}"""
self.button = QtGui.QPushButton('Exit')
self.widget_one = WidgetOne()
self.widget_two = WidgetTwo()
## Place the Docks inside the DockArea
dock_area.addDock(self.dock1)
dock_area.addDock(self.dock2, 'right', self.dock1)
## The statment above means that dock2 will be placed at the right of dock 1
layout.addWidget(label)
layout.addWidget(dock_area)
layout.addWidget(self.button)
## Add the Widgets inside each dock
self.dock1.addWidget(self.widget_one)
self.dock2.addWidget(self.widget_two)
## This is for set the initial size and posotion of the main window
self.setGeometry(100, 100, 600, 400)
## Connect the actions to functions, there is a default function called close()
self.widget_one.TitleClicked.connect(self.dob_click)
self.button.clicked.connect(self.close)
def dob_click(self, feed):
self.widget_two.text_box.clear()
## May look messy but wat i am doing is somethin like this:
## 'Title : ' + feed[0] + '\n\n' + 'Summary : ' + feed[1]
self.widget_two.text_box.setText(
'Title : ' + feed[0]\
+ '\n\n' +\
'Summary : ' + feed[1]
)
class WidgetOne(QtGui.QWidget):
## This signal is created to pass a "list" when it (the signal) is emited
TitleClicked = QtCore.pyqtSignal([list])
def __init__(self):
QtGui.QWidget.__init__(self)
self.layout = QtGui.QVBoxLayout()
self.setLayout(self.layout)
self.titleList = QtGui.QListWidget()
self.label = QtGui.QLabel('Here is my list:')
self.layout.addWidget(self.label)
self.layout.addWidget(self.titleList)
self.titleList.addItem(QtGui.QListWidgetItem('Title 1'))
self.titleList.addItem(QtGui.QListWidgetItem('Title 2'))
self.titleList.itemDoubleClicked.connect(self.onClicked)
def onClicked(self, item):
## Just test values
title = item.text()
summary = "Here you will put the summary of {}. ".format(title)*50
## Pass the values as a list in the signal. You can pass as much values
## as you want, remember that all of them have to be inside one list
self.TitleClicked.emit([title, summary])
class WidgetTwo(QtGui.QWidget):
def __init__(self):
QtGui.QWidget.__init__(self)
self.layout = QtGui.QVBoxLayout()
self.setLayout(self.layout)
self.label2 = QtGui.QLabel('Here we show results?:')
self.text_box = QtGui.QTextBrowser()
self.layout.addWidget(self.label2)
self.layout.addWidget(self.text_box)
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
window = MyApp()
window.show()
sys.exit(app.exec_())
Again, there are comments inside the code to help you understand what I did.
Here is how it looks:
If you pass the mouse between the two widgets you will see the mouse icon will change, with that you can readjust on the run the size of both widgets.
Final Words
This is another approach, more "interactive" and more esthetic than my previous answer. As you said, using a QSplitter works too.
Problems
The way you are building your GUI is, in my opinion, messy and it may lead to errors. I suggest the use of Layouts for a more organized GUI.
The other problem is that each widget is an independent class so if you want to connect an action in one widget to do something in the other widget through the Main Window, you must use Signals.
Edit : Another suggestion, use other name for the close function instead of exit and try using self.close() instead of QCoreApplication.instance().quit()
Solution
Trying to emulate what you want to do I made this GUI:
import sys
from PyQt5 import QtGui, QtCore
class MyWindow(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
## Generate the structure parts of the MainWindow
self.central_widget = QtGui.QWidget() # A QWidget to work as Central Widget
self.layout1 = QtGui.QVBoxLayout() # Vertical Layout
self.layout2 = QtGui.QHBoxLayout() # Horizontal Layout
self.widget_one = WidgetOne()
self.widget_two = WidgetTwo()
self.exitBtn = QtGui.QPushButton('Exit')
## Build the structure
# Insert a QWidget as a central widget for the MainWindow
self.setCentralWidget(self.central_widget)
# Add a principal layout for the widgets/layouts you want to add
self.central_widget.setLayout(self.layout1)
# Add widgets/layuts, as many as you want, remember they are in a Vertical
# layout: they will be added one below of the other
self.layout1.addLayout(self.layout2)
self.layout1.addWidget(self.exitBtn)
# Here we add the widgets to the horizontal layout: one next to the other
self.layout2.addWidget(self.widget_one)
self.layout2.addWidget(self.widget_two)
## Connect the signal
self.widget_one.TitleClicked.connect(self.dob_click)
def dob_click(self, feed):
## Change the properties of the elements in the second widget
self.widget_two.title.setText('Title : '+feed[0])
self.widget_two.summary.setText('Summary : '+feed[1])
## Build your widgets same as the Main Window, with the excepton that here you don't
## need a central widget, because it is already a widget.
class WidgetOne(QtGui.QWidget):
TitleClicked = QtCore.pyqtSignal([list]) # Signal Created
def __init__(self):
QtGui.QWidget.__init__(self)
##
self.layout = QtGui.QVBoxLayout() # Vertical Layout
self.setLayout(self.layout)
self.titleList = QtGui.QListWidget()
self.label = QtGui.QLabel('Here is my list:')
self.layout.addWidget(self.label)
self.layout.addWidget(self.titleList)
self.titleList.addItem(QtGui.QListWidgetItem('Title 1'))
self.titleList.addItem(QtGui.QListWidgetItem('Title 2'))
self.titleList.itemDoubleClicked.connect(self.onClicked)
def onClicked(self, item):
## Just test parameters and signal emited
self.TitleClicked.emit([item.text(), item.text()+item.text()])
class WidgetTwo(QtGui.QWidget):
def __init__(self):
QtGui.QWidget.__init__(self)
self.layout = QtGui.QVBoxLayout()
self.setLayout(self.layout)
self.title = QtGui.QLabel('Title : ---')
self.summary = QtGui.QLabel('Summary : ---')
self.link = QtGui.QLabel('Link : ---')
self.layout.addWidget(self.title)
self.layout.addWidget(self.summary)
self.layout.addWidget(self.link)
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
window = MyWindow()
window.show()
sys.exit(app.exec_())
Inside the code, there are comments to help you understand why I did to build an organized GUI. There is also an example of a Signal being used to connect the action of itemDoubleClicked from the first widget to the second one. Here is how the MainWindow looks:
It is not very clear how the layouts work just from seeing the result, so I did a little paint over to a better understanding:
The blue box is the vertical layout (QVBoxLayout) and the red one is the horizontal layout (QHBoxLayout). Inside the blue layout, are located the red layout (above) and the exit button (below); and inside the red layout, are located the widget_1 (left) and the widget_2 (right).
Other Solution
An "easier" solution will be building the widgets inside the MainWindow instead of creating separate classes. With this you will avoid the use of signals, but the code will become a little more confusing because all the code will be cramped in one class.

PyQt5: How to Resize mainwindow to fit a Stackedwidget or Stackedlayout

I have a MainWindow with a Dockwidget attached to it for the sole purpose of switching between multiple Stackedwidget/StackedLayout
The Issue i am having is that the StackedLayout holds a particular widget that displays a large image which resizes the MainWindow as expected but when switching from that Widget to another using the docked widget the MainWindow still uses the SizeHint from the large widget even after calling a MainWindow.Resize(stackedwidget) which leaves the window larger than necessary for the current widget in view
Here's the code:
from PyQt5 import QtCore, QtGui, QtWidgets
class Mainwindow(QtWidgets.QMainWindow):
def __init__(self):
super(Mainwindow, self).__init__()
# window setting
self.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
# window central widget
self.centerwidget = QtWidgets.QWidget()
self.setCentralWidget(self.centerwidget)
# stack for page/widget management
self.stack = QtWidgets.QStackedLayout(self.centerwidget)
# widgets or page management
self.widgeta = None
self.dockWidget = None
self.widgetb= None
def pageManager(self, widget):
# switching stack widgets
self.stack.setCurrentWidget(widget)
widget.updateGeometry()
widget.layout.update()
self.centerwidget.updateGeometry()
self.updateGeometry()
self.resize(widget.layout.totalSizeHint())
def load(self):
# basically startup
# stack settings
self.widgeta= Widgeta()
self.widgetb= Widgetb()
self.stack.addWidget(self.widgeta)
self.stack.addWidget(self.widgetb)
self.stack.setStackingMode(QtWidgets.QStackedLayout.StackOne)
self.stack.setCurrentWidget(self.widgeta)
# dock widget
self.dockWidget = Duck()
self.addDockWidget(QtCore.Qt.TopDockWidgetArea, self.dockWidget)
# show mainwindow
self.show()
class Duck(QtWidgets.QDockWidget):
def __init__(self, parent=None):
super(Duck, self).__init__(parent)
# create subwidget assign layout to subwidget
self.dockCentralWidget = QtWidgets.QWidget()
self.dockCentralWidgetlayout = QtWidgets.QHBoxLayout()
self.dockCentralWidgetlayout.setContentsMargins(QtCore.QMargins(1,1,1,1))
self.dockCentralWidgetlayout.setSpacing(1)
self.dockCentralWidget.setLayout(self.dockCentralWidgetlayout)
self.dockCentralWidget.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
self.setStyleSheet("background-color: #354465;")
# subwidget elements
self.Ui()
# add subwidget and elements
self.setWidget(self.dockCentralWidget)
self.dockCentralWidgetlayout.addWidget(self.widgetAButton)
self.dockCentralWidgetlayout.addWidget(self.widgetBButton)
def Ui(self):
# first button
self.widgetAButton = QtWidgets.QPushButton('aaaa')
self.widgetAButton.clicked.connect(lambda : self.clicker((self.widgetAButton, Window.widgeta)))
# second button
self.widgetBButton = QtWidgets.QPushButton('bbbb')
self.widgetBButton.clicked.connect(lambda : self.clicker((self.widgetBButton, Window.widgetb)))
def clicker(self, arg):
Window.pageManager(arg[1])
class Widgeta(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Widgeta, self).__init__(parent)
# sizing and layout
self.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
self.layout = QtWidgets.QVBoxLayout()
self.setLayout(self.layout)
# widgets
self.ui()
def ui(self):
# a check button
self.goButton = QtWidgets.QPushButton()
self.goButton.setObjectName('gobutton')
self.goButton.setText('ccc')
self.goButton.setMinimumSize(QtCore.QSize(400, 150))
self.goButton.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
self.goButton.setStyleSheet(goButtonCSS)
# label
self.infoLabel = QtWidgets.QLabel()
self.infoLabel.setObjectName('infolabel')
self.infoLabel.setMinimumSize(QtCore.QSize(400, 250))
self.infoLabel.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
self.infoLabel.setText('jjjj')
self.infoLabel.setStyleSheet(topDisplayCSS)
# add widgets to layout
self.layout.addWidget(self.infoLabel)
self.layout.addWidget(self.goButton, QtCore.Qt.AlignVCenter, QtCore.Qt.AlignHCenter)
self.layout.setContentsMargins(QtCore.QMargins(0,0,0,0))
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
Window = Mainwindow()
Window.load()
sys.exit(app.exec_())
i Have also tried using a StackedWidget as the central widget and switching, same thing.
The QStackedLayout always uses its minimum size based on the largest minimum size of all its widgets. This also means that all widgets using a stacked layout behave in the same way: QStackedWidget and QTabWidget.
This is done by design, and it's the correct approach (otherwise the parent widget would always try to resize itself whenever a new "page" is set with a different minimum size)
The solution is to subclass the QStackedLayout (or the QStackedWidget) and override its minimumSize(); if needed, sizeHint() could be overridden in the same fashion, but I wouldn't suggest it.
class StackedLayout(QtWidgets.QStackedLayout):
def minimumSize(self):
if self.currentWidget():
s = self.currentWidget().minimumSize()
if s.isEmpty():
s = self.currentWidget().minimumSizeHint()
return s
return super().minimumSize()
Note that if you want to resize the main window to the minimum possible size you should use mainWindow.resize(mainWindow.minimumSizeHint()), since a QMainWindow also has minimum size requirements depending on its extra widgets, like toolbars or, as in your case, dock widgets.

How to change icon of item by using QStyledItemDelegate for custom QItemlist depends on condition?

I build a QListwidget with custom itemwidget this list. The idea I want to change the icon of the item depends on condition. I read about the MVC model, but I couldn't know how to built QStyledItemDelegate to update them.
Now, I delete all items in the list and read them, that works if the list small but when I have a lot of item it takes time.
This code of CostmItemWidget:
class CustomQWidget(QWidget):
def __init__(self, file, parent=None):
super(CustomQWidget, self).__init__(parent)
if file["l_file"]:
pathname = os.path.join(parent.parent.main_script_path, "icons/correct.png")
else:
pathname = os.path.join(parent.parent.main_script_path, "icons/wrong.png")
pixmap = QtGui.QPixmap(pathname)
button = QPushButton()
button.setStyleSheet("padding: 0px;")
button.setFixedSize(16, 16)
# resize pixmap
pixmap = pixmap.scaled(button.size(), QtCore.Qt.KeepAspectRatioByExpanding, QtCore.Qt.SmoothTransformation)
cropOffsetX = (pixmap.width() - button.size().width()) / 2
pixmap = pixmap.copy(cropOffsetX, 0, button.size().width(), button.size().height())
button.setIcon(QtGui.QIcon(pixmap))
button.setIconSize(button.size())
button.setFlat(True)
label = QLabel(file["n_file"])
layout = QHBoxLayout()
layout.addWidget(button, 0)
layout.addWidget(label, 0)
layout.setContentsMargins(0, 0, 0, 0)
self.setLayout(layout)
And this code of widget content list:
class FileListWidget(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self, parent)
loadUi(os.path.join(".", "UIFiles", 'filelist_widget.ui'), self)
self.parent = parent
self.refresh_list()
self.list_view.setCurrentRow(0)
self.list_view.itemClicked.connect(self.selected_file)
self.list_view.setStyleSheet("QListWidget::item { padding: 0px; }")
def refresh_list(self):
self.list_view.clear()
if len(self.parent.files) == 0:
return
for index, file in self.parent.files.iterrows():
self.add_item_list(file)
self.parent.image_deleted = False
def add_item_list(self, file):
item = QListWidgetItem(self.list_view)
item.setSizeHint(QSize(item.sizeHint().width(), 20))
item_widget2 = CustomQWidget(file, self)
self.list_view.addItem(item)
self.list_view.setItemWidget(item, item_widget2)
I looking to find a way of applying QStyledItemDelegate and change the icon by a certain signal. The icon of the button in the CustomQWidget and I want to change it when the value of "l_file" from the dictionary is True.
This image of the list I have
I created this delegate to handle put icon inside the custom Widget of the QListItemWidget.
class FileListDelegate(QStyledItemDelegate):
def __init__(self, parent, list_view):
super(FileListDelegate, self).__init__(parent)
# pointer to list
self.list_view = list_view
def paint(self, painter: QtGui.QPainter, option: QStyleOptionViewItem, index: QtCore.QModelIndex) -> None:
painter.save()
item = self.list_view.itemFromIndex(index)
widget = self.list_view.itemWidget(item)
layout = widget.layout()
button = layout.itemAt(0).widget()
if self.list_view.parent().parent().parent.files.loc[widget.index, 'l_file']:
pathname = os.path.join(widget.main_script_path, "icons/correct.png")
else:
pathname = os.path.join(widget.main_script_path, "icons/wrong.png")
pixmap = QtGui.QPixmap(pathname)
button.setIcon(QtGui.QIcon(pixmap))
button.setIconSize(button.size())
painter.restore()

Cannot get ListItems with custom widgets to display

I'm having issues getting items with custom widgets to show up in a list widget. The items show up blank in the example below...
from PySide2 import QtWidgets
class ItemWidget(QtWidgets.QWidget):
def __init__(self,parent = None):
super(ItemWidget, self).__init__(parent)
layout = QtWidgets.QHBoxLayout()
self.setLayout(layout)
self.checkBox = QtWidgets.QCheckBox()
self.label = QtWidgets.QLabel('test')
layout.addWidget(self.checkBox)
layout.addWidget(self.label)
class ListWidget(QtWidgets.QListWidget):
def __init__(self,parent = None):
super(ListWidget,self).__init__(parent)
self.initUI()
def initUI(self):
for i in range(10):
item = QtWidgets.QListWidgetItem()
self.addItem(item)
widget = ItemWidget(self)
self.setItemWidget(item,widget)
self.show()
lister = ListWidget()
It looks like QlistWidget won't do what you want, so you'll need to approach it from a lower level.
PySide.QtGui.QListWidget.setItemWidget(item, widget)
This function should only be used to display static content in the place of a list widget item. If you want to display custom dynamic content or implement a custom editor widget, use PySide.QtGui.QListView and subclass PySide.QtGui.QItemDelegate instead.

PyQt QListWidget custom items

how can i create a QListWidgetItem that has 1 image and 2 labels/strings underneath, that have support for css?
this is the last thing i have tried:
class CustomListWidgetItem(QListWidgetItem, QLabel):
def __init__(self, parent=None):
QListWidgetItem.__init__(self, parent)
QLabel.__init__(self, parent)
i'm using PyQt btw
how can i create a QListWidgetItem that has 1 image and 2
labels/strings underneath, that have support for css?
In this case, you can't (it actually has an API for adding icons easily, but two labels/strings is impossible). But, you can create your own custom widget and put it into QtGui.QListWidget.
Create your custom widget.
Create your QtGui.QListWidget in the main application.
Create a custom widget object and set item in QListWidgetItem by QListWidgetItem is in QtGui.QListWidget by using the QListWidget.setItemWidget (self, QListWidgetItem item, QWidget widget) method.
This is an example to explain my solution:
import sys
from PyQt4 import QtGui
class QCustomQWidget (QtGui.QWidget):
def __init__ (self, parent = None):
super(QCustomQWidget, self).__init__(parent)
self.textQVBoxLayout = QtGui.QVBoxLayout()
self.textUpQLabel = QtGui.QLabel()
self.textDownQLabel = QtGui.QLabel()
self.textQVBoxLayout.addWidget(self.textUpQLabel)
self.textQVBoxLayout.addWidget(self.textDownQLabel)
self.allQHBoxLayout = QtGui.QHBoxLayout()
self.iconQLabel = QtGui.QLabel()
self.allQHBoxLayout.addWidget(self.iconQLabel, 0)
self.allQHBoxLayout.addLayout(self.textQVBoxLayout, 1)
self.setLayout(self.allQHBoxLayout)
# setStyleSheet
self.textUpQLabel.setStyleSheet('''
color: rgb(0, 0, 255);
''')
self.textDownQLabel.setStyleSheet('''
color: rgb(255, 0, 0);
''')
def setTextUp (self, text):
self.textUpQLabel.setText(text)
def setTextDown (self, text):
self.textDownQLabel.setText(text)
def setIcon (self, imagePath):
self.iconQLabel.setPixmap(QtGui.QPixmap(imagePath))
class exampleQMainWindow (QtGui.QMainWindow):
def __init__ (self):
super(exampleQMainWindow, self).__init__()
# Create QListWidget
self.myQListWidget = QtGui.QListWidget(self)
for index, name, icon in [
('No.1', 'Meyoko', 'icon.png'),
('No.2', 'Nyaruko', 'icon.png'),
('No.3', 'Louise', 'icon.png')]:
# Create QCustomQWidget
myQCustomQWidget = QCustomQWidget()
myQCustomQWidget.setTextUp(index)
myQCustomQWidget.setTextDown(name)
myQCustomQWidget.setIcon(icon)
# Create QListWidgetItem
myQListWidgetItem = QtGui.QListWidgetItem(self.myQListWidget)
# Set size hint
myQListWidgetItem.setSizeHint(myQCustomQWidget.sizeHint())
# Add QListWidgetItem into QListWidget
self.myQListWidget.addItem(myQListWidgetItem)
self.myQListWidget.setItemWidget(myQListWidgetItem, myQCustomQWidget)
self.setCentralWidget(self.myQListWidget)
app = QtGui.QApplication([])
window = exampleQMainWindow()
window.show()
sys.exit(app.exec_())
Note: I have image file icon.png, size 48 x 48 pixel.
QListWidget.setItemWidget
Experimental result

Categories