0

I have a Python PyQt5 interface with a QSvgWidget holding an SVG image and 2 text labels that I want to sit on top of it (I'm using a QGridLayout). The SVG and label are dynamic; that is to say, they will change as a slider is moved. (I'm editing the SVG and saving it with the lxml library.)

To get the labels to position properly with respect to each other and the SVG graphic, I'm wrapping them in a QVBoxLayout, which is then added as a sub-layout to the QGridLayout. And the positioning works well. I'm adding the QSvgWidget first, then the QGridLayout, and the labels show up on top of the SVG.

My simplified code:

from PyQt5.QtWidgets import QWidget, QPushButton, QGridLayout, QVBoxLayout, QLabel, QSlider
from PyQt5.QtSvg import QSvgWidget
from PyQt5.QtCore import Qt

NUM_ROWS = 5
NUM_COLUMNS = 14

class Ui(QWidget):
    def __init__(self, svg_lxml, parent=None):
        super(Ui, self).__init__(parent)

        self.svg_lxml = svg_lxml
        self.slider = QSlider(Qt.Horizontal)
        self.svg_image = QSvgWidget("image_initial.svg")
        self.labelLine1Text = QLabel('text1')
        self.labelLine2Text = QLabel('text2')

        # define sub-layout for 2-line text
        self.text_layout = QVBoxLayout()
        self.text_layout.addWidget(self.labelLine1Text)
        self.text_layout.addWidget(self.labelLine2Text)

        # define main layout; where the widgets go in the window
        self.temp_layout = QGridLayout()
        self.temp_layout.addWidget(self.svg_image, 1, 0, NUM_ROWS-2, NUM_COLUMNS)
        self.temp_layout.setRowMinimumHeight(1,155)  # to position 2-line text
        self.temp_layout.setColumnMinimumWidth(1,35)  # to position 2-line text
        self.temp_layout.addLayout(self.text_layout, 2, 2)  # add sub-layout for 2-line text
        self.temp_layout.addWidget(self.slider, NUM_ROWS, 1, 1, NUM_COLUMNS-2)

        self.slider.setMinimum(0)
        self.slider.setMaximum(60)
        self.slider.setValue(60)
        self.slider.sliderReleased.connect(self.update_pressure)

        # apply layout
        self.setLayout(self.temp_layout)

    def update_pressure(self):
        global pressure
        pressure = self.slider.value()
        # update widgets for 2-line text
        if pressure < 15:
            self.labelLine1Text.setText('LOW AIR')
            self.labelLine2Text.setText('PRESSURE')
        else:
            self.labelLine1Text.setText('(blank1)')
            self.labelLine2Text.setText('(blank2')
        text_layout_temp = QVBoxLayout()
        text_layout_temp.addWidget(self.labelLine1Text)
        text_layout_temp.addWidget(self.labelLine2Text)
        self.text_layout = text_layout_temp

        # call class function to update the SVG file with new pressure
        self.svg_lxml.update(pressure)
        # update widget with updated SVG file
        self.svg_image = QSvgWidget("image.svg")
        # add updated widget to main layout
        self.temp_layout.addWidget(self.svg_image, 1, 0, NUM_ROWS-2, NUM_COLUMNS)
        # add updated 2-line text widgets to sublayout
        # self.text_layout.addWidget(self.labelLine1Text)
        # self.text_layout.addWidget(self.labelLine2Text)

        # add sublayout for 2-line text to layout
        self.temp_layout.addLayout(text_layout_temp, 3, 2)  # add sub-layout for 2-line text
        # reapply main layout
        self.setLayout(self.temp_layout)

My understanding was that widgets are associated by reference to layouts, so just updating widgets will "refresh" the screen. But as you can see by the "update_pressure" method, I've had to duplicate a bunch of code to get even the SVG file to reload. And when it does, it places the SVG on top of the labels, so the labels are hidden. (Whereas on the initial drawing, the labels are placed on top of the SVG.)

Any guidance would be appreciated! (Also, I've modified my code to remove confidential info, and for the same reason, I can't show a screenshot. However let me know if I need to provide additional info. This is my first stackoverflow question)!

j.c.
  • 1
  • Look at [`QWidget::raise`](https://doc.qt.io/qt-6/qwidget.html#raise) and [`QWidget::lower`](https://doc.qt.io/qt-6/qwidget.html#lower) etc. – G.M. Apr 04 '22 at 04:27
  • Awesome, that worked perfect, thanks! Note that I also had to add a line: self.svg_image.deleteLater() to the update routine, because it turns out I was just adding more and more SVG images to the layout, and "lower"ing the latest one just exposed the previous ones. Also, I'd like to mark your comment as the "answer", but I don't know how to do that... – j.c. Apr 05 '22 at 19:18

0 Answers0