Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Rendering SVG inside QTableView



  • Hi,

    I want to render animated SVG inside QTableView cell.

    Basically something like this:

    void TableViewDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option,
    const QModelIndex& index) const
    {
    	if (index.column() == 0) {
    		if (condition) {
    			auto svg = QSvgWidget();
    			svg.load(QString{ ":/res/img/spinning_icon.svg" });
    			svg.setBaseSize(QSize{ 28, 28 });
    			svg.setAutoFillBackground(false);
    			m_view->setIndexWidget(index, &svg);
    		}
    	}
    	
    	QStyledItemDelegate::paint(painter, option, index);
    }
    

    But this solution creates multiple widgets, and I only need one SVG instance so the animation is nicely synchronized.
    Also QWidget::setAutoFillBackground(false) doesn't change the background transparency and the widgets are stretched.

    I'm sure there's a better way of doing this.


  • Lifetime Qt Champion

    Hi
    What about QSvgRenderer `?
    It allows to paint to random Painter.
    https://doc.qt.io/qt-5/qsvgrenderer.html#render
    So you could have it as member of the delegate and use it to render
    to the rows.
    However, im not sure that works better in term of synchronization.


  • Lifetime Qt Champion

    Hi
    What about QSvgRenderer `?
    It allows to paint to random Painter.
    https://doc.qt.io/qt-5/qsvgrenderer.html#render
    So you could have it as member of the delegate and use it to render
    to the rows.
    However, im not sure that works better in term of synchronization.



  • @krzysieklfc said in Rendering SVG inside QTableView:

    But this solution creates multiple widgets

    You are doing this for a whole column.



  • @mrjj I wasn't sure which API is the way to go, but I did the following and it works perfectly. Thanks!

    	TableViewDelegate::TableViewDelegate(TableView* view, QObject* parent)
    		: QStyledItemDelegate(parent), m_view(view)
    	{
    		svg_renderer = new QSvgRenderer(QString{ ":/res/img/spinning_icon.svg" }, m_view);
    
    		connect(svg_renderer, &QSvgRenderer::repaintNeeded,
    			[this] {
    			m_view->viewport()->update();
    		});
    	}
    
    
    	void TableViewDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option,
    		const QModelIndex& index) const
    	{
    		QStyleOptionViewItem opt{ option };
    		initStyleOption(&opt, index);
    
    		if (index.column() == 0) {
    			if (condition)
    			{
    				// transform rect, otherwise renders in whole cell
    				auto bounds = opt.rect;
    				bounds.setWidth(28);
    				bounds.moveTo(opt.rect.center().x() - bounds.width() / 2,
    					opt.rect.center().y() - bounds.height() / 2);
    
    				svg_renderer->render(painter, bounds);
    				QStyledItemDelegate::paint(painter, opt, index);
    			}
    		}
    	}
    
    	TableView::TableView(QWidget* parent) : QTableView(parent)
    	{
    		m_delegate = new TableViewDelegate(this);
    		setItemDelegate(m_delegate);
    	}
    
    

Log in to reply