代码之家  ›  专栏  ›  技术社区  ›  Vesnog

是否可以扩大QSlider周围的可拉伸区域

  •  4
  • Vesnog  · 技术社区  · 6 年前

    我的目标是要有一个习惯 QSlider 并在标签上打勾 单元为此,我在派生类中编辑QSlider类的默认paintEvent。然而,事实证明,可打印区域是有限的,并且我放置的顶部/底部标签被裁剪(参见屏幕截图)。我用于生成这些滑块的代码如下所示:

    import sys
    from PySide2.QtCore import *
    from PySide2.QtWidgets import *
    from PySide2.QtGui import *
    
    slider_x = 150
    slider_y = 450
    slider_step = [0.01, 0.1, 1, 10, 100]  # in microns
    
    
    class MySlider(QSlider):
        def __init__(self, type, parent=None):
            super(MySlider, self).__init__(parent)
            self.Type = type
    
        def paintEvent(self, event):
            super(MySlider, self).paintEvent(event)
            qp = QPainter(self)
            pen = QPen()
            pen.setWidth(2)
            pen.setColor(Qt.red)
    
            qp.setPen(pen)
            font = QFont('Times', 10)
            qp.setFont(font)
            self.setContentsMargins(50, 50, 50, 50)
            # size = self.size()
            # print(size)
            # print("margins", self.getContentsMargins())
            # print(self.getContentsMargins())
            # print(self.contentsRect())
            contents = self.contentsRect()
            self.setFixedSize(QSize(slider_x, slider_y))
            max_slider = self.maximum()
            y_inc = 0
            for i in range(max_slider):
                qp.drawText(contents.x() - font.pointSize(), y_inc + font.pointSize() / 2, '{0:2}'.format(slider_step[i]))
                qp.drawLine(contents.x() + font.pointSize(), y_inc, contents.x() + contents.width(), y_inc)
                y_inc += slider_y/4
    
    
    class Window(QWidget):
        """ Inherits from QWidget """
        def __init__(self):
            super().__init__()
            self.title = 'Control Stages'
            self.left = 10
            self.top = 10
            self.width = 320
            self.height = 100
            self.AxesMapping = [0, 1, 2, 3]
            self.initUI()
    
        def initUI(self):
            """ Initializes the GUI either using the grid layout or the absolute position layout"""
            self.setWindowTitle(self.title)
            self.setGeometry(self.left, self.top, self.width, self.height)
            Comp4 = self.createSlider("step_size")
            Comp5 = self.createSlider("speed")
            windowLayout = QGridLayout()
            windowLayout.setContentsMargins(50, 50, 50, 50)
            HGroupBox = QGroupBox()
            layout = QGridLayout()
            layout.addWidget(Comp4, 0, 0)
            layout.addWidget(Comp5, 0, 1)
            HGroupBox.setLayout(layout)
            HGroupBox.setFixedSize(QSize(740, 480))
            windowLayout.addWidget(HGroupBox, 0, 0)
            self.setLayout(windowLayout)
            self.show()
    
        def createSlider(self, variant):
            Slider = MySlider(Qt.Vertical)
            Slider.Type = variant
            Slider.setMaximum(5)
            Slider.setMinimum(1)
            Slider.setSingleStep(1)
            Slider.setTickInterval(1)
            Slider.valueChanged.connect(lambda: self.sliderChanged(Slider))
            return Slider
    
        @staticmethod
        def sliderChanged(Slider):
            print("Slider value changed to ", Slider.value(), "slider type is ", Slider.Type)
            if Slider.Type == "step_size":
                print("this is a step size slider")
            elif Slider.Type == "speed":
                print("this is a speed slider")
    
    
    if __name__ == '__main__':
        app = QApplication(sys.argv)
        ex = Window()
        sys.exit(app.exec_())
    

    是否有可能扩大QSlider周围的可拉伸区域?如果有,我如何才能实现此效果?您可以在屏幕截图上看到,第一个和最后一个记号旁边的红色标签没有正确显示,并且被裁剪(即在第一个记号标签中,标签0.01缺少1和0的顶部)。

    enter image description here

    编辑: 在尝试了提议的解决方案后,顶部标签的一部分仍被剪掉。下面的第二个版本在64位Windows 10上与PySide2 5.12.0和Python 3.6.6仍然相似。

    我有一个双启动系统,所以我在Ubuntu16.04.3 LTS和Python3.5.2/PySide 5.12.0上试用了它,它完全可以开箱即用。这里有一个屏幕截图,但不幸的是,它必须在Windows上工作。

    enter image description here

    3 回复  |  直到 6 年前
        1
  •  4
  •   cmaureir    6 年前

    如果我没弄错的话,你希望蜱虫在顶部和底部都是可见的,因为它们似乎是由于边缘而被“切割”的。 我认为这是假设widgets的边距被正确设置为零或类似的结果,你可以通过改变数字来观察这种效果。(我尝试移动利润,但没有成功)

    old post ,我注意到实现类似的目标似乎很棘手,你可以根据 minimum maximum QSlider

    由于底部的勾号将位于主窗口小部件下,因此您只需添加一个

    不想粘贴整个代码,但您只需要声明 opt handle y 放在里面,用它代替你的 y_inc

    def paintEvent(self, event):                                                                                                                                                            
        super(MySlider, self).paintEvent(event)                                                     
        qp = QPainter(self)                                                                         
        pen = QPen()                                                                                
        pen.setWidth(2)                                                                             
        pen.setColor(Qt.red)                                                                        
    
        qp.setPen(pen)                                                                              
        font = QFont('Times', 10)                                                                   
        qp.setFont(font)                                                                            
        self.setContentsMargins(50, 50, 50, 50)                                                     
        # size = self.size()                                                                        
        # print(size)                                                                               
        # print("margins", self.getContentsMargins())                                               
        # print(self.getContentsMargins())                                                          
        # print(self.contentsRect())                                                                
        contents = self.contentsRect()                                                              
        self.setFixedSize(QSize(slider_x, slider_y))                                                
    
        # New code                                                                                  
        max_slider = self.maximum()                                                                 
        min_slider = self.minimum()                                                                 
        len_slider = max_slider - min_slider                                                        
        height = self.height()                                                                      
    
        opt = QStyleOptionSlider()                                                                  
        handle = self.style().subControlRect(QStyle.CC_Slider, opt, QStyle.SC_SliderHandle, self)   
        handle_height = handle.height() # Add +10 on windows (workarount)                                                            
        height_diff = height - handle_height                                                        
        point_size = font.pointSize()                                                               
    
        for i in range(max_slider):                                                                 
            y = round(((1 - i / len_slider) * height_diff + (handle_height / 2.0))) - 1             
    
            # Trick for the tick at the bottom                                                      
            if i == 0:                                                                              
                y = self.height() - handle_height/2.0 # To have the tick in the middle              
                #y = height_diff # to shift it a bit                                                
    
            qp.drawText(contents.x() - point_size, y + point_size / 2, '{0:2}'.format(slider_step[len_slider - i]))
            qp.drawLine(contents.x() + point_size, y, contents.x() + contents.width(), y)  
    

    enter image description here

    编辑: 在windows上似乎有一个被忽略的大约10个单元的上边缘,这是Qt中的一个错误。解决方法是替换:

    handle_height = handle.height()
    

    具有

    handle_height = handle.height() + 10
    

    内部 paintEvent

        2
  •  4
  •   Rachel Gallen    6 年前

    triggerAction (SliderTomax值为6),可用于 set the Slider Position action is triggered .

    触发动作的语法是

     QAbstractSlider.triggerAction (self, SliderAction action)
    

    SliderAction的值如下所示:

    QAbstractSlider.SliderSingleStepAdd 1

    QAbstractSlider.SliderPageStepAdd 3

    QAbstractSlider.SliderPageStepSub 4

    QAbstractSlider.SliderToMinimum 5

    QAbstractSlider.SliderToMaximum 6

    QAbstractSlider.SliderMove 7

    source )

    使用 PySide2 ,可以使用调用这些方法

    PySide2.QtWidgets.QAbstractSlider.maximum()  //returns the value of the maximum
    

    PySide2.QtWidgets.QAbstractSlider.setMaximum(arg) // pass your own value
    
        3
  •  2
  •   Vesnog    6 年前

    import sys
    from PySide2.QtCore import *
    from PySide2.QtWidgets import *
    from PySide2.QtGui import *
    
    slider_x = 150
    slider_y = 450
    slider_step = [0.01, 0.1, 1, 10, 100]  # in microns
    groove_y = 400
    handle_height = 10
    
    
    class MySlider(QSlider):
        def __init__(self, type, parent=None):
            # super(MySlider, self).__init__(parent)
            super().__init__()
            self.parent = parent
            self.Type = type
            # self.setFixedHeight(115)
            self.setStyleSheet("""QSlider::groove:vertical {
        border: 1px solid black;
        height: """ + str(groove_y) + """ px;
        width: 10px;
        border-radius: 2px;
        }
    
        QSlider::handle:vertical {
            background: red;
            border: 1px solid red;
            height: """ + str(handle_height) + """ px;
            margin: 2px 0;
            border-radius: 1px;
        }
    
        QSlider::add-page:vertical {
            background: blue;
        }
        QSlider::sub-page:vertical {
            background: red;
    """)
    
        def paintEvent(self, event):
            super(MySlider, self).paintEvent(event)
            qp = QPainter(self)
            pen = QPen()
            pen.setWidth(2)
            pen.setColor(Qt.black)
    
            qp.setPen(pen)
            font = QFont('Times', 10)
            qp.setFont(font)
            self.setContentsMargins(50, 50, 50, 50)
            self.setFixedSize(QSize(slider_x, slider_y))
            contents = self.contentsRect()
            max = self.maximum()
            min = self.minimum()
    
            y_inc = slider_y - (slider_y - groove_y) / 2
            for i in range(len(slider_step)):
                qp.drawText(contents.x() - 2 * font.pointSize(), y_inc + font.pointSize() / 2, '{0:3}'.format(slider_step[i]))
                qp.drawLine(contents.x() + 2 * font.pointSize(), y_inc, contents.x() + contents.width(), y_inc)
                y_inc -= groove_y / (max - min)
    
    
    
    class Window(QWidget):
        """ Inherits from QWidget """
        def __init__(self):
            super().__init__()
            self.title = 'Control Stages'
            self.left = 10
            self.top = 10
            self.width = 320
            self.height = 100
            self.AxesMapping = [0, 1, 2, 3]
            self.initUI()
    
        def initUI(self):
            """ Initializes the GUI either using the grid layout or the absolute position layout"""
            self.setWindowTitle(self.title)
            self.setGeometry(self.left, self.top, self.width, self.height)
            Comp4 = self.createSlider("step_size")
            Comp5 = self.createSlider("speed")
            windowLayout = QGridLayout()
            windowLayout.setContentsMargins(50, 50, 50, 50)
            HGroupBox = QGroupBox()
            layout = QGridLayout()
            layout.addWidget(Comp4, 0, 0)
            layout.addWidget(Comp5, 0, 1)
            HGroupBox.setLayout(layout)
            HGroupBox.setFixedSize(QSize(740, 480))
            windowLayout.addWidget(HGroupBox, 0, 0)
            self.setLayout(windowLayout)
            self.show()
    
        def createSlider(self, variant):
            Slider = MySlider(Qt.Vertical)
            Slider.Type = variant
            Slider.setMaximum(len(slider_step))
            Slider.setMinimum(1)
            Slider.setSingleStep(1)
            Slider.setTickInterval(1)
            Slider.valueChanged.connect(lambda: self.sliderChanged(Slider))
            return Slider
    
        @staticmethod
        def sliderChanged(Slider):
            print("Slider value changed to ", Slider.value(), "slider type is ", Slider.Type)
            if Slider.Type == "step_size":
                print("this is a step size slider")
            elif Slider.Type == "speed":
                print("this is a speed slider")
    
    
    if __name__ == '__main__':
        app = QApplication(sys.argv)
        ex = Window()
        sys.exit(app.exec_())
    
    推荐文章