2

I am trying to figure out how to add a populated QVBoxLayout into a QFrame.

enter image description here

In the image you see 4 sliders, each with two labels, and a pushbutton. I've been messing around with QIcon and stylesheets which is why they look a bit odd at the moment. Each of these objects is created in my own custom class that produces all 4 objects together in a QVBoxLayout.

I would like to put a border around each QVBoxLayout. I've reeled through pages and pages of guides and other peoples code but i just can't work out what i'm doing wrong here. I've managed to create a QFrame with just a black border that is appearing behind the QVBoxLayout but its not tied to it in anyway, so its off-center. I could probably bodge something together using the geometery but that seems like something i'll regret later on.

enter image description here

You can see in the second image what i'm trying to get at, but everything i'm doing just isn't working. I've only just started learning to code, so i'm a bit out of my depth at the moment - i've read and read and read the QT documentation and hundreds of message board questions similar to this but none of it makes sense and none of it works.

Its going to be something very simple i know, but right now i'm ready to throw the computer out the window.

Here is my code - apologies as it is a bit messy as i've been experimenting with a lot of different things:

    #!/usr/bin/env python3

import sys

from PySide2.QtWidgets import *
from PySide2.QtGui import *
from PySide2.QtCore import *

ON_BTN = 0
ON_PRESS_BTN = 1
OFF_BTN = 2
OFF_PRESS_BTN = 3

MUTE_ICONS = {
    ON_BTN: "./images/onbtn.png",
    ON_PRESS_BTN: "./images/onpressbtn",
    OFF_BTN: "./images/offbtn.png",
    OFF_PRESS_BTN: "./images/offpressbtn.png"
}

slider_enabled = """
    QSlider::groove:vertical {
        height: 300px;
        width: 7px;
        border-radius: 3px;
    }
    QSlider::handle:vertical {
        background: #8d8d8d;
        border: 2px solid #444;
        height: 30px;
        margin: 0 -30px; /* expand outside the groove */
        border-radius: 10px;               
    }

    QSlider::add-page:vertical {
        background: #31b0c3;
        border-radius: 3px;
    }

    QSlider::sub-page:vertical {
        background: black;
        border-radius: 3px;
    } 

    QSlider::handle:vertical:pressed {
        background: #565656;
    }"""

slider_disabled = """ 
    QSlider::groove:vertical {
        height: 300px;
        width: 7px;
        border-radius: 3px;
    }
    QSlider::handle:vertical {
        background: #8d8d8d;
        border: 2px solid #444;
        height: 30px;
        margin: 0 -30px; /* expand outside the groove */
        border-radius: 10px;               
    }

    QSlider::add-page:vertical {
        background: #3d6166;
        border-radius: 3px;
    }

    QSlider::sub-page:vertical {
        background: black;
        border-radius: 3px;
    } 

    QSlider::handle:vertical:pressed {
        background: #565656;
    }"""

class StyleSheets():
    def __init__(self, style):
        self.style = style

    def sliderstyle(self):
        self.style.setStyleSheet

class MySlider(QWidget):
    def __init__(self, number):
        #Defining various items that make up the object
        QWidget.__init__(self)
        self.number = number #Channel number

        #Slider creation and functions that set its value called
        self.slider = QSlider(Qt.Vertical)
        self.slider.setMaximum(100)

        self.send_slider_startup_values()
        self.slider.valueChanged.connect(self.slider_value_change)
        self.slider.setFixedHeight(300)
        self.slider.setFixedWidth(80)
        self.setStyleSheet("background: white;")

        self.MyStylesheet = """
            QSlider::groove:vertical {
                height: 300px;
                width: 7px;
                border-radius: 3px;
            }
            QSlider::handle:vertical {
                background: #8d8d8d;
                border: 2px solid #444;
                height: 30px;
                margin: 0 -30px; /* expand outside the groove */
                border-radius: 10px;               
            }

            QSlider::add-page:vertical {
                background: #00ddff;
                border-radius: 3px;
            }

            QSlider::sub-page:vertical {
                background: black;
                border-radius: 3px;
            } 

            QSlider::handle:vertical:pressed {
                background: #565656;
            }
                """

        self.slider.setStyleSheet(self.MyStylesheet)

        #Defining the channel number label & volume level label
        self.numberlabel = QLabel(str(number))
        self.numberlabel.setAlignment(Qt.AlignCenter)
        self.volumelabel = QLabel("0")
        self.volumelabel.setAlignment(Qt.AlignCenter)
        self.volumelabel.setStyleSheet("border-style: solid; border-color: rgba(0,50,100,255);")

        #Creating the mute button
        self.mutebutton = QPushButton()

        #self.mutebutton.setAlignment(Qt.AlignCenter)
        self.mutebutton.setFixedSize(QSize(int (77), int (45)))
        self.mutebutton.setIconSize(QSize( int(80), int(48)))
        self.mutebutton.setFlat(True)
        self.mutebutton.pressed.connect(self.button_pressed)
        self.mutebutton.released.connect(self.button_released)
        self.update_status(OFF_BTN)

        #Making the Layout and adding each item

        self.sliderframe = QFrame(self)
        self.sliderframe.setFixedHeight(450)
        self.sliderframe.setFixedWidth(90)
        self.sliderframe.setStyleSheet("border: 2px solid black; background: 0%;")
        self.setGeometry(50, 50, 450, 90)



        #sliderflayout = QVBoxLayout()
        #sliderflayout.setAlignment(Qt.AlignCenter)

        sliderlayout = QVBoxLayout()
        sliderlayout.setAlignment(Qt.AlignCenter)

        sliderlayout.addWidget(self.slider, 0, Qt.AlignCenter)
        sliderlayout.addWidget(self.numberlabel, Qt.AlignCenter)
        sliderlayout.addWidget(self.volumelabel, Qt.AlignCenter)
        sliderlayout.addWidget(self.mutebutton, Qt.AlignCenter)
        #sliderlayout.addWidget(self.sliderframe, Qt.AlignCenter)

        #self.sliderframe = QFrame(sliderlayout)
        #self.sliderframe.setFixedHeight(450)
        #self.sliderframe.setFixedWidth(100)
        #self.sliderframe.setStyleSheet("border: 5px solid black;")
        #self.setGeometry(50, 50, 50, 50)
        # self.sliderframe.setVisible(False)

        self.setLayout(sliderlayout)

        #self.setAutoFillBackground(True)


    def slider_value_change(self):
        value = int(self.slider.value() / 10)
        self.volumelabel.setText(str(value))

    def send_slider_startup_values(self):
        self.slider.setValue(0)

    def update_status(self, status):
        self.status = status
        self.mutebutton.setIcon(QIcon(MUTE_ICONS[self.status]))

    def button_pressed(self):
        if self.status == ON_BTN:
            self.update_status(ON_PRESS_BTN)

        elif self.status == OFF_BTN:
            self.update_status(OFF_PRESS_BTN)

    def button_released(self):
        if self.status == ON_PRESS_BTN:
            self.send_mute()
            self.slider.setStyleSheet(slider_disabled)
            self.update_status(OFF_BTN)

        elif self.status == OFF_PRESS_BTN:
            self.send_mute()
            self.slider.setStyleSheet(slider_enabled)
            self.update_status(ON_BTN)

    def send_mute(self):
        pass


class Window2(QWidget):
    def __init__(self):
        QWidget.__init__(self)
        self.setWindowTitle("Hello")
        self.setMinimumHeight(480)
        self.setMinimumWidth(800)
        self.setAutoFillBackground(True)
        self.setStyleSheet("""QWidget{background-color: grey;}""")

        self.labeltest = QLabel("test")

        label = QLabel("Test 1")
        label2 = QLabel("Test 2")
        label3 = QLabel("Test 3")
        label4 = QLabel("Test 4")
        label5 = QLabel("Test 5")

        radiobutton = QRadioButton("MUTE")
        radiobutton.setText("hello")

        #self.label5 = QLabel("HELLO!!!!!")
        #frame = QFrame()
        #frame.setLayout(QVBoxLayout)


        self.channel1 = MySlider(1)
        self.channel2 = MySlider(2)
        self.channel3 = MySlider(3)
        self.channel4 = MySlider(4)

        #self.sliderframe = QFrame(self.channel1)
        #self.sliderframe.setFixedHeight(500)
        #self.sliderframe.setFixedWidth(150)
        #self.sliderframe.setStyleSheet("border: 2px solid black; background: 0%;")


        self.channel2.setDisabled(True)

        layout = QHBoxLayout()
        layout.setAlignment(Qt.AlignLeft)

        layout.addWidget(self.channel1)
        layout.addWidget(self.channel2)
        layout.addWidget(self.channel3)
        layout.addWidget(self.channel4)

        self.setLayout(layout)



    def password_timeout(self):
        pass

    #def frame_object(self, channel):
        #frame = QFrame()
        #frame.setStyleSheet("""
        #QFrame::active: {
        #    background: white;
        #}""")
        #channelstrip = MySlider(channel)
        #frame.setLayout(channelstrip)
        #return frame




class PasswordWindow(QWidget):
    def __init__(self):
        QWidget.__init__(self)
        self.setWindowTitle("Password Test")
        self.showFullScreen()

        layout = QGridLayout()
        self.setLayout(layout)
        label = QLabel("Please enter password: ")
        layout.addWidget(label, 0, 0)

        button = QPushButton("Press me!")
        button.clicked.connect(self.button_pushed)
        layout.addWidget(button, 1, 0)

    def button_pushed(self):
        self.close()



app = QApplication(sys.argv)

mainwindow = Window2()
mainwindow.show()

sys.exit(app.exec_())

EDIT: Slight update, i've managed to frame the object by creating a seperate class that inherits Qframe and has the MySlider object passed into it. I need to find a way to get it tighter around the objects but its progress somewhat.

Updated Sliders

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Welshhobo
  • 115
  • 11

1 Answers1

1

I've figured it out. I'm writing a response in case someone else comes across the same problem (as it seems pretty common). Layouts come automatically with a margin and padding. The command to set both the padding and margin to what you want it to be is:

layoutname.setContentsMargins(0, 0, 0, 0)
layoutname.setSpacing(0)

So i thought i was doing this with QFrames, but i didn't and accidently made it work anyway. You can do this by creating a class of widget that you pass a custom made object into, and using a stylesheet to border the entire thing. You also get the benefit of the stylesheet not affecting objects passed into it, as its only concerned with the class its written in. So in my case, i made an object class called "MySlider" that produces 4 objects - a QSlider, 2 QLabels, and a QPushbutton. This is considered a single object as it was made in a class. I then created a second class that requires an argument. I pass that newly made object into the second class as that argument and add that to another QVBoxLayout. Using self.setStyleSheet i can then edit the entire widgets elements. The widget will automatically size to the smallest it can go without cropping its contents. Here is the code, its pretty simple but man did it twist my melon:

class SliderFrame(QFrame):
def __init__(self, myslider):
    QFrame.__init__(self)

    self.setStyleSheet("border: 1px solid black; margin: 0px; padding: 0px;")

    self.layout = QVBoxLayout()
    self.layout.addWidget(myslider)
    self.layout.setContentsMargins(0, 0, 0, 0)

    self.setLayout(self.layout)

And when creating the object on your main window:

self.channel1 = SliderFrame(MySlider(1))

You can see that i pass an argument into SliderFrame, and in turn pass an argument into MySlider.

Done!

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Welshhobo
  • 115
  • 11