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)!