Align QSlider with an above QLabel that contains a QPixmap The Next CEO of Stack OverflowFinding the index of an item given a list containing it in PythonQLabel: set color of text and backgroundDoes Python have a string 'contains' substring method?Qt: resizing a QLabel containing a QPixmap while keeping its aspect ratioHow to change dynamic QLabel with a Pixmap (QList)QLabel doesn't display QPixmapPython 3.6 | PyQt5 | QLabel doesn't display QPixmapPyQt5 QSlider value is always 0Qt - QLabel won't resize with fixed ratioHow to make QSlider unclickable

Is it OK to decorate a log book cover?

Which one is the true statement?

Airplane gently rocking its wings during whole flight

Man transported from Alternate World into ours by a Neutrino Detector

How do I fit a non linear curve?

Physiological effects of huge anime eyes

Are the names of these months realistic?

Can this note be analyzed as a non-chord tone?

Is it okay to majorly distort historical facts while writing a fiction story?

A question about free fall, velocity, and the height of an object.

Expectation in a stochastic differential equation

Won the lottery - how do I keep the money?

How did Beeri the Hittite come up with naming his daughter Yehudit?

Yu-Gi-Oh cards in Python 3

Decide between Polyglossia and Babel for LuaLaTeX in 2019

Can I board the first leg of the flight without having final country's visa?

Strange use of "whether ... than ..." in official text

Spaces in which all closed sets are regular closed

Does Germany produce more waste than the US?

Is French Guiana a (hard) EU border?

Film where the government was corrupt with aliens, people sent to kill aliens are given rigged visors not showing the right aliens

Is it convenient to ask the journal's editor for two additional days to complete a review?

Traduction de « Life is a roller coaster »

What was Carter Burke's job for "the company" in Aliens?



Align QSlider with an above QLabel that contains a QPixmap



The Next CEO of Stack OverflowFinding the index of an item given a list containing it in PythonQLabel: set color of text and backgroundDoes Python have a string 'contains' substring method?Qt: resizing a QLabel containing a QPixmap while keeping its aspect ratioHow to change dynamic QLabel with a Pixmap (QList)QLabel doesn't display QPixmapPython 3.6 | PyQt5 | QLabel doesn't display QPixmapPyQt5 QSlider value is always 0Qt - QLabel won't resize with fixed ratioHow to make QSlider unclickable










1















I am trying to align a QSlider and a QLabel that I have in a QGridBoxLayout



For reference, this is for viewing frames in a video, which are shown elsewhere. The QLabel here is for showing labelled sections of the video, with green sections being "labelled" and black sections being "not labelled"



My QSLider is initialized as:



self.slider = QSlider(Qt.Horizontal, self)
self.slider.setSingleStep(1)
self.slider.setFocusPolicy(Qt.NoFocus)
self.slider.valueChanged.connect(self.sliderChanged)
self.layout.addWidget(self.slider)


The QLabel contains a QPixmap, which has a QImage created from a numpy array of shape (100,1000,3). Here is how it is initialized:



image = np.zeros((100,1000,3), dtype=np.uint8) #Initialize a black picture
for combo in indices_list:
start, end = combo
start = int(start / self.length * 1000)
end = int(end / self.length * 1000)
image[:,start:end] = [0,255,0] #Label the columns as green
height, width, bytevalue = image.shape
qimage = QImage(image, width, height, bytevalue * width, QImage.Format_RGB888)
pixmap = QPixmap(qimage)
self.label.setPixmap(pixmap)


What the above code does is take a list of start and end indices and then change the columns in that range to green.



The problem I am having is that even though the QSlider and the QLabel are stacked together in a QVBoxLayout, the slider position does not always match up with the corresponding pixel. I believe this is because the leftmost side of the slider "handle" (I am not sure of the correct name) stops at the leftmost side of the slider. They match up directly in the center, and then match up less and less as you move away from the center.



I would like the center of the handle to be directly underneath the corresponding column in the QLabel for the current slider value.



I have tried setting the margins of the slider to 0, but that did not work.



Thank you for your help.



Edit:



Pictures will probably be helpful:



Here is a picture of the entire bar:



Entire bar.



Here is a picture of it not being aligned on the left:



Not aligned left.



Here is a picture of it not aligned on the right:



Not aligned right.



And finally, Here is it aligned in the center:



Aligned in the center.










share|improve this question
























  • You could show a picture of what you currently get and another picture of what you want to get to understand you better

    – eyllanesc
    Mar 7 at 18:23











  • please provide a Minimal, Complete, and Verifiable example

    – eyllanesc
    Mar 7 at 18:28











  • I guess the images you've shown are what you get now, but it would be great if you put an image of what you want to get.

    – eyllanesc
    Mar 7 at 18:30











  • I suppose that length is the number of frames of the video and suppose that it is 200; and if for example indices_list is [(0, 10), (50, 100)], then the slider will have 200 steps and if it is in step 50 it should be at the left edge of the second green rectangle and if it is at 100 in the right edge, am I right?

    – eyllanesc
    Mar 7 at 18:38











  • @eyllanesc that is correct. The last picture shows alignment with the right edge of the rectangle.

    – pariscraigm
    Mar 7 at 18:53
















1















I am trying to align a QSlider and a QLabel that I have in a QGridBoxLayout



For reference, this is for viewing frames in a video, which are shown elsewhere. The QLabel here is for showing labelled sections of the video, with green sections being "labelled" and black sections being "not labelled"



My QSLider is initialized as:



self.slider = QSlider(Qt.Horizontal, self)
self.slider.setSingleStep(1)
self.slider.setFocusPolicy(Qt.NoFocus)
self.slider.valueChanged.connect(self.sliderChanged)
self.layout.addWidget(self.slider)


The QLabel contains a QPixmap, which has a QImage created from a numpy array of shape (100,1000,3). Here is how it is initialized:



image = np.zeros((100,1000,3), dtype=np.uint8) #Initialize a black picture
for combo in indices_list:
start, end = combo
start = int(start / self.length * 1000)
end = int(end / self.length * 1000)
image[:,start:end] = [0,255,0] #Label the columns as green
height, width, bytevalue = image.shape
qimage = QImage(image, width, height, bytevalue * width, QImage.Format_RGB888)
pixmap = QPixmap(qimage)
self.label.setPixmap(pixmap)


What the above code does is take a list of start and end indices and then change the columns in that range to green.



The problem I am having is that even though the QSlider and the QLabel are stacked together in a QVBoxLayout, the slider position does not always match up with the corresponding pixel. I believe this is because the leftmost side of the slider "handle" (I am not sure of the correct name) stops at the leftmost side of the slider. They match up directly in the center, and then match up less and less as you move away from the center.



I would like the center of the handle to be directly underneath the corresponding column in the QLabel for the current slider value.



I have tried setting the margins of the slider to 0, but that did not work.



Thank you for your help.



Edit:



Pictures will probably be helpful:



Here is a picture of the entire bar:



Entire bar.



Here is a picture of it not being aligned on the left:



Not aligned left.



Here is a picture of it not aligned on the right:



Not aligned right.



And finally, Here is it aligned in the center:



Aligned in the center.










share|improve this question
























  • You could show a picture of what you currently get and another picture of what you want to get to understand you better

    – eyllanesc
    Mar 7 at 18:23











  • please provide a Minimal, Complete, and Verifiable example

    – eyllanesc
    Mar 7 at 18:28











  • I guess the images you've shown are what you get now, but it would be great if you put an image of what you want to get.

    – eyllanesc
    Mar 7 at 18:30











  • I suppose that length is the number of frames of the video and suppose that it is 200; and if for example indices_list is [(0, 10), (50, 100)], then the slider will have 200 steps and if it is in step 50 it should be at the left edge of the second green rectangle and if it is at 100 in the right edge, am I right?

    – eyllanesc
    Mar 7 at 18:38











  • @eyllanesc that is correct. The last picture shows alignment with the right edge of the rectangle.

    – pariscraigm
    Mar 7 at 18:53














1












1








1








I am trying to align a QSlider and a QLabel that I have in a QGridBoxLayout



For reference, this is for viewing frames in a video, which are shown elsewhere. The QLabel here is for showing labelled sections of the video, with green sections being "labelled" and black sections being "not labelled"



My QSLider is initialized as:



self.slider = QSlider(Qt.Horizontal, self)
self.slider.setSingleStep(1)
self.slider.setFocusPolicy(Qt.NoFocus)
self.slider.valueChanged.connect(self.sliderChanged)
self.layout.addWidget(self.slider)


The QLabel contains a QPixmap, which has a QImage created from a numpy array of shape (100,1000,3). Here is how it is initialized:



image = np.zeros((100,1000,3), dtype=np.uint8) #Initialize a black picture
for combo in indices_list:
start, end = combo
start = int(start / self.length * 1000)
end = int(end / self.length * 1000)
image[:,start:end] = [0,255,0] #Label the columns as green
height, width, bytevalue = image.shape
qimage = QImage(image, width, height, bytevalue * width, QImage.Format_RGB888)
pixmap = QPixmap(qimage)
self.label.setPixmap(pixmap)


What the above code does is take a list of start and end indices and then change the columns in that range to green.



The problem I am having is that even though the QSlider and the QLabel are stacked together in a QVBoxLayout, the slider position does not always match up with the corresponding pixel. I believe this is because the leftmost side of the slider "handle" (I am not sure of the correct name) stops at the leftmost side of the slider. They match up directly in the center, and then match up less and less as you move away from the center.



I would like the center of the handle to be directly underneath the corresponding column in the QLabel for the current slider value.



I have tried setting the margins of the slider to 0, but that did not work.



Thank you for your help.



Edit:



Pictures will probably be helpful:



Here is a picture of the entire bar:



Entire bar.



Here is a picture of it not being aligned on the left:



Not aligned left.



Here is a picture of it not aligned on the right:



Not aligned right.



And finally, Here is it aligned in the center:



Aligned in the center.










share|improve this question
















I am trying to align a QSlider and a QLabel that I have in a QGridBoxLayout



For reference, this is for viewing frames in a video, which are shown elsewhere. The QLabel here is for showing labelled sections of the video, with green sections being "labelled" and black sections being "not labelled"



My QSLider is initialized as:



self.slider = QSlider(Qt.Horizontal, self)
self.slider.setSingleStep(1)
self.slider.setFocusPolicy(Qt.NoFocus)
self.slider.valueChanged.connect(self.sliderChanged)
self.layout.addWidget(self.slider)


The QLabel contains a QPixmap, which has a QImage created from a numpy array of shape (100,1000,3). Here is how it is initialized:



image = np.zeros((100,1000,3), dtype=np.uint8) #Initialize a black picture
for combo in indices_list:
start, end = combo
start = int(start / self.length * 1000)
end = int(end / self.length * 1000)
image[:,start:end] = [0,255,0] #Label the columns as green
height, width, bytevalue = image.shape
qimage = QImage(image, width, height, bytevalue * width, QImage.Format_RGB888)
pixmap = QPixmap(qimage)
self.label.setPixmap(pixmap)


What the above code does is take a list of start and end indices and then change the columns in that range to green.



The problem I am having is that even though the QSlider and the QLabel are stacked together in a QVBoxLayout, the slider position does not always match up with the corresponding pixel. I believe this is because the leftmost side of the slider "handle" (I am not sure of the correct name) stops at the leftmost side of the slider. They match up directly in the center, and then match up less and less as you move away from the center.



I would like the center of the handle to be directly underneath the corresponding column in the QLabel for the current slider value.



I have tried setting the margins of the slider to 0, but that did not work.



Thank you for your help.



Edit:



Pictures will probably be helpful:



Here is a picture of the entire bar:



Entire bar.



Here is a picture of it not being aligned on the left:



Not aligned left.



Here is a picture of it not aligned on the right:



Not aligned right.



And finally, Here is it aligned in the center:



Aligned in the center.







python pyqt5 qlabel qslider qvboxlayout






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Mar 7 at 18:25







pariscraigm

















asked Mar 7 at 18:13









pariscraigmpariscraigm

214




214












  • You could show a picture of what you currently get and another picture of what you want to get to understand you better

    – eyllanesc
    Mar 7 at 18:23











  • please provide a Minimal, Complete, and Verifiable example

    – eyllanesc
    Mar 7 at 18:28











  • I guess the images you've shown are what you get now, but it would be great if you put an image of what you want to get.

    – eyllanesc
    Mar 7 at 18:30











  • I suppose that length is the number of frames of the video and suppose that it is 200; and if for example indices_list is [(0, 10), (50, 100)], then the slider will have 200 steps and if it is in step 50 it should be at the left edge of the second green rectangle and if it is at 100 in the right edge, am I right?

    – eyllanesc
    Mar 7 at 18:38











  • @eyllanesc that is correct. The last picture shows alignment with the right edge of the rectangle.

    – pariscraigm
    Mar 7 at 18:53


















  • You could show a picture of what you currently get and another picture of what you want to get to understand you better

    – eyllanesc
    Mar 7 at 18:23











  • please provide a Minimal, Complete, and Verifiable example

    – eyllanesc
    Mar 7 at 18:28











  • I guess the images you've shown are what you get now, but it would be great if you put an image of what you want to get.

    – eyllanesc
    Mar 7 at 18:30











  • I suppose that length is the number of frames of the video and suppose that it is 200; and if for example indices_list is [(0, 10), (50, 100)], then the slider will have 200 steps and if it is in step 50 it should be at the left edge of the second green rectangle and if it is at 100 in the right edge, am I right?

    – eyllanesc
    Mar 7 at 18:38











  • @eyllanesc that is correct. The last picture shows alignment with the right edge of the rectangle.

    – pariscraigm
    Mar 7 at 18:53

















You could show a picture of what you currently get and another picture of what you want to get to understand you better

– eyllanesc
Mar 7 at 18:23





You could show a picture of what you currently get and another picture of what you want to get to understand you better

– eyllanesc
Mar 7 at 18:23













please provide a Minimal, Complete, and Verifiable example

– eyllanesc
Mar 7 at 18:28





please provide a Minimal, Complete, and Verifiable example

– eyllanesc
Mar 7 at 18:28













I guess the images you've shown are what you get now, but it would be great if you put an image of what you want to get.

– eyllanesc
Mar 7 at 18:30





I guess the images you've shown are what you get now, but it would be great if you put an image of what you want to get.

– eyllanesc
Mar 7 at 18:30













I suppose that length is the number of frames of the video and suppose that it is 200; and if for example indices_list is [(0, 10), (50, 100)], then the slider will have 200 steps and if it is in step 50 it should be at the left edge of the second green rectangle and if it is at 100 in the right edge, am I right?

– eyllanesc
Mar 7 at 18:38





I suppose that length is the number of frames of the video and suppose that it is 200; and if for example indices_list is [(0, 10), (50, 100)], then the slider will have 200 steps and if it is in step 50 it should be at the left edge of the second green rectangle and if it is at 100 in the right edge, am I right?

– eyllanesc
Mar 7 at 18:38













@eyllanesc that is correct. The last picture shows alignment with the right edge of the rectangle.

– pariscraigm
Mar 7 at 18:53






@eyllanesc that is correct. The last picture shows alignment with the right edge of the rectangle.

– pariscraigm
Mar 7 at 18:53













1 Answer
1






active

oldest

votes


















0














To obtain the horizontal position you must use QStyle::subControlRect():



from PyQt5 import QtCore, QtGui, QtWidgets

class Label(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Label, self).__init__(parent)
self._slider = None
self._values = []

def setSlider(self, slider):
self._slider = slider
self.update()

def set_values(self, values):
self._values = values
self.update()

def paintEvent(self, event):
if self._slider is None: return
painter = QtGui.QPainter(self)
X1 = self.get_pos_by_value(self._slider.minimum())
X2 = self.get_pos_by_value(self._slider.maximum())
R = QtCore.QRect(QtCore.QPoint(X1, 0), QtCore.QPoint(X2, self.height()))
painter.fillRect(R, QtGui.QColor("#000000"))
for start, end in self._values:
x1 = self.get_pos_by_value(start)
x2 = self.get_pos_by_value(end)
r = QtCore.QRect(QtCore.QPoint(x1, 0), QtCore.QPoint(x2, self.height()))
painter.fillRect(r, QtGui.QColor("#00ff00"))

def get_pos_by_value(self, value):
opt = QtWidgets.QStyleOptionSlider()
self._slider.initStyleOption(opt)
opt.sliderPosition = value
r = self._slider.style().subControlRect(
QtWidgets.QStyle.CC_Slider,
opt,
QtWidgets.QStyle.SC_SliderHandle,
self._slider
)
return r.center().x()

class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
length = 1000
indices_list = [(100, 200), (400, 500), (700, 900)]
self.label = Label()
self.slider = QtWidgets.QSlider(
orientation=QtCore.Qt.Horizontal,
minimum = 0,
maximum=length,
singleStep=1,
pageStep=1
)
self.label.setSlider(self.slider)
self.label.set_values(indices_list)
label_value = QtWidgets.QLabel(alignment=QtCore.Qt.AlignCenter)
self.slider.valueChanged.connect(label_value.setNum)
label_value.setNum(self.slider.value())

lay = QtWidgets.QVBoxLayout(self)
lay.addWidget(self.label, 1)
lay.addWidget(self.slider)
lay.addWidget(label_value)
self.resize(600, 300)

if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
app.setStyle('fusion')
w = Widget()
w.show()
sys.exit(app.exec_())





share|improve this answer

























  • This is great! Thank you!

    – pariscraigm
    Mar 7 at 23:46











Your Answer






StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);













draft saved

draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55050332%2falign-qslider-with-an-above-qlabel-that-contains-a-qpixmap%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









0














To obtain the horizontal position you must use QStyle::subControlRect():



from PyQt5 import QtCore, QtGui, QtWidgets

class Label(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Label, self).__init__(parent)
self._slider = None
self._values = []

def setSlider(self, slider):
self._slider = slider
self.update()

def set_values(self, values):
self._values = values
self.update()

def paintEvent(self, event):
if self._slider is None: return
painter = QtGui.QPainter(self)
X1 = self.get_pos_by_value(self._slider.minimum())
X2 = self.get_pos_by_value(self._slider.maximum())
R = QtCore.QRect(QtCore.QPoint(X1, 0), QtCore.QPoint(X2, self.height()))
painter.fillRect(R, QtGui.QColor("#000000"))
for start, end in self._values:
x1 = self.get_pos_by_value(start)
x2 = self.get_pos_by_value(end)
r = QtCore.QRect(QtCore.QPoint(x1, 0), QtCore.QPoint(x2, self.height()))
painter.fillRect(r, QtGui.QColor("#00ff00"))

def get_pos_by_value(self, value):
opt = QtWidgets.QStyleOptionSlider()
self._slider.initStyleOption(opt)
opt.sliderPosition = value
r = self._slider.style().subControlRect(
QtWidgets.QStyle.CC_Slider,
opt,
QtWidgets.QStyle.SC_SliderHandle,
self._slider
)
return r.center().x()

class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
length = 1000
indices_list = [(100, 200), (400, 500), (700, 900)]
self.label = Label()
self.slider = QtWidgets.QSlider(
orientation=QtCore.Qt.Horizontal,
minimum = 0,
maximum=length,
singleStep=1,
pageStep=1
)
self.label.setSlider(self.slider)
self.label.set_values(indices_list)
label_value = QtWidgets.QLabel(alignment=QtCore.Qt.AlignCenter)
self.slider.valueChanged.connect(label_value.setNum)
label_value.setNum(self.slider.value())

lay = QtWidgets.QVBoxLayout(self)
lay.addWidget(self.label, 1)
lay.addWidget(self.slider)
lay.addWidget(label_value)
self.resize(600, 300)

if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
app.setStyle('fusion')
w = Widget()
w.show()
sys.exit(app.exec_())





share|improve this answer

























  • This is great! Thank you!

    – pariscraigm
    Mar 7 at 23:46















0














To obtain the horizontal position you must use QStyle::subControlRect():



from PyQt5 import QtCore, QtGui, QtWidgets

class Label(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Label, self).__init__(parent)
self._slider = None
self._values = []

def setSlider(self, slider):
self._slider = slider
self.update()

def set_values(self, values):
self._values = values
self.update()

def paintEvent(self, event):
if self._slider is None: return
painter = QtGui.QPainter(self)
X1 = self.get_pos_by_value(self._slider.minimum())
X2 = self.get_pos_by_value(self._slider.maximum())
R = QtCore.QRect(QtCore.QPoint(X1, 0), QtCore.QPoint(X2, self.height()))
painter.fillRect(R, QtGui.QColor("#000000"))
for start, end in self._values:
x1 = self.get_pos_by_value(start)
x2 = self.get_pos_by_value(end)
r = QtCore.QRect(QtCore.QPoint(x1, 0), QtCore.QPoint(x2, self.height()))
painter.fillRect(r, QtGui.QColor("#00ff00"))

def get_pos_by_value(self, value):
opt = QtWidgets.QStyleOptionSlider()
self._slider.initStyleOption(opt)
opt.sliderPosition = value
r = self._slider.style().subControlRect(
QtWidgets.QStyle.CC_Slider,
opt,
QtWidgets.QStyle.SC_SliderHandle,
self._slider
)
return r.center().x()

class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
length = 1000
indices_list = [(100, 200), (400, 500), (700, 900)]
self.label = Label()
self.slider = QtWidgets.QSlider(
orientation=QtCore.Qt.Horizontal,
minimum = 0,
maximum=length,
singleStep=1,
pageStep=1
)
self.label.setSlider(self.slider)
self.label.set_values(indices_list)
label_value = QtWidgets.QLabel(alignment=QtCore.Qt.AlignCenter)
self.slider.valueChanged.connect(label_value.setNum)
label_value.setNum(self.slider.value())

lay = QtWidgets.QVBoxLayout(self)
lay.addWidget(self.label, 1)
lay.addWidget(self.slider)
lay.addWidget(label_value)
self.resize(600, 300)

if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
app.setStyle('fusion')
w = Widget()
w.show()
sys.exit(app.exec_())





share|improve this answer

























  • This is great! Thank you!

    – pariscraigm
    Mar 7 at 23:46













0












0








0







To obtain the horizontal position you must use QStyle::subControlRect():



from PyQt5 import QtCore, QtGui, QtWidgets

class Label(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Label, self).__init__(parent)
self._slider = None
self._values = []

def setSlider(self, slider):
self._slider = slider
self.update()

def set_values(self, values):
self._values = values
self.update()

def paintEvent(self, event):
if self._slider is None: return
painter = QtGui.QPainter(self)
X1 = self.get_pos_by_value(self._slider.minimum())
X2 = self.get_pos_by_value(self._slider.maximum())
R = QtCore.QRect(QtCore.QPoint(X1, 0), QtCore.QPoint(X2, self.height()))
painter.fillRect(R, QtGui.QColor("#000000"))
for start, end in self._values:
x1 = self.get_pos_by_value(start)
x2 = self.get_pos_by_value(end)
r = QtCore.QRect(QtCore.QPoint(x1, 0), QtCore.QPoint(x2, self.height()))
painter.fillRect(r, QtGui.QColor("#00ff00"))

def get_pos_by_value(self, value):
opt = QtWidgets.QStyleOptionSlider()
self._slider.initStyleOption(opt)
opt.sliderPosition = value
r = self._slider.style().subControlRect(
QtWidgets.QStyle.CC_Slider,
opt,
QtWidgets.QStyle.SC_SliderHandle,
self._slider
)
return r.center().x()

class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
length = 1000
indices_list = [(100, 200), (400, 500), (700, 900)]
self.label = Label()
self.slider = QtWidgets.QSlider(
orientation=QtCore.Qt.Horizontal,
minimum = 0,
maximum=length,
singleStep=1,
pageStep=1
)
self.label.setSlider(self.slider)
self.label.set_values(indices_list)
label_value = QtWidgets.QLabel(alignment=QtCore.Qt.AlignCenter)
self.slider.valueChanged.connect(label_value.setNum)
label_value.setNum(self.slider.value())

lay = QtWidgets.QVBoxLayout(self)
lay.addWidget(self.label, 1)
lay.addWidget(self.slider)
lay.addWidget(label_value)
self.resize(600, 300)

if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
app.setStyle('fusion')
w = Widget()
w.show()
sys.exit(app.exec_())





share|improve this answer















To obtain the horizontal position you must use QStyle::subControlRect():



from PyQt5 import QtCore, QtGui, QtWidgets

class Label(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Label, self).__init__(parent)
self._slider = None
self._values = []

def setSlider(self, slider):
self._slider = slider
self.update()

def set_values(self, values):
self._values = values
self.update()

def paintEvent(self, event):
if self._slider is None: return
painter = QtGui.QPainter(self)
X1 = self.get_pos_by_value(self._slider.minimum())
X2 = self.get_pos_by_value(self._slider.maximum())
R = QtCore.QRect(QtCore.QPoint(X1, 0), QtCore.QPoint(X2, self.height()))
painter.fillRect(R, QtGui.QColor("#000000"))
for start, end in self._values:
x1 = self.get_pos_by_value(start)
x2 = self.get_pos_by_value(end)
r = QtCore.QRect(QtCore.QPoint(x1, 0), QtCore.QPoint(x2, self.height()))
painter.fillRect(r, QtGui.QColor("#00ff00"))

def get_pos_by_value(self, value):
opt = QtWidgets.QStyleOptionSlider()
self._slider.initStyleOption(opt)
opt.sliderPosition = value
r = self._slider.style().subControlRect(
QtWidgets.QStyle.CC_Slider,
opt,
QtWidgets.QStyle.SC_SliderHandle,
self._slider
)
return r.center().x()

class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
length = 1000
indices_list = [(100, 200), (400, 500), (700, 900)]
self.label = Label()
self.slider = QtWidgets.QSlider(
orientation=QtCore.Qt.Horizontal,
minimum = 0,
maximum=length,
singleStep=1,
pageStep=1
)
self.label.setSlider(self.slider)
self.label.set_values(indices_list)
label_value = QtWidgets.QLabel(alignment=QtCore.Qt.AlignCenter)
self.slider.valueChanged.connect(label_value.setNum)
label_value.setNum(self.slider.value())

lay = QtWidgets.QVBoxLayout(self)
lay.addWidget(self.label, 1)
lay.addWidget(self.slider)
lay.addWidget(label_value)
self.resize(600, 300)

if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
app.setStyle('fusion')
w = Widget()
w.show()
sys.exit(app.exec_())






share|improve this answer














share|improve this answer



share|improve this answer








edited Mar 7 at 21:46

























answered Mar 7 at 21:39









eyllanesceyllanesc

85.4k103564




85.4k103564












  • This is great! Thank you!

    – pariscraigm
    Mar 7 at 23:46

















  • This is great! Thank you!

    – pariscraigm
    Mar 7 at 23:46
















This is great! Thank you!

– pariscraigm
Mar 7 at 23:46





This is great! Thank you!

– pariscraigm
Mar 7 at 23:46



















draft saved

draft discarded
















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55050332%2falign-qslider-with-an-above-qlabel-that-contains-a-qpixmap%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

1928 у кіно

Захаров Федір Захарович

Ель Греко