Совместите QSlider с указанным выше QLabel, который содержит QPixmap - PullRequest
1 голос
/ 07 марта 2019

Я пытаюсь выровнять QSlider и QLabel, которые у меня есть в QGridBoxLayout

Для справки, это для просмотра кадров в видео, которые показаны в другом месте.QLabel здесь для показа помеченных разделов видео, с зелеными участками, которые «помечены», и черными участками, которые «не помечены»

Мой QSLider инициализируется как:

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)

QLabelсодержит QPixmap, который имеет QImage, созданный из массива массива фигуры (100,1000,3).Вот как он инициализируется:

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)

Код, приведенный выше, берет список начальных и конечных индексов, а затем меняет столбцы в этом диапазоне на зеленый.

Проблема Iу меня есть то, что, хотя QSlider и QLabel сложены вместе в QVBoxLayout, положение ползунка не всегда совпадает с соответствующим пикселем.Я полагаю, что это потому, что крайняя левая сторона «ручки» ползунка (я не уверен в правильном названии) останавливается на самой левой стороне ползунка.Они совпадают непосредственно в центре, а затем совпадают все меньше и меньше по мере удаления от центра.

Я бы хотел, чтобы центр ручки находился непосредственно под соответствующим столбцом в QLabel для текущегоЗначение ползунка.

Я попытался установить поля ползунка на 0, но это не сработало.

Спасибо за вашу помощь.

Редактировать:

Фотографии, вероятно, будут полезны:

Вот изображение всего бара:

Entire bar.

Вот его изображение не выравнивается по левому краю:

Not aligned left.

Вот его изображение не выровнено посправа:

Not aligned right.

И, наконец, вот он по центру:

Aligned in the center.

1 Ответ

0 голосов
/ 08 марта 2019

Для получения горизонтального положения необходимо использовать 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_())
...