Layout with frames

Soundwave picture Soundwave · Jan 5, 2017 · Viewed 17.2k times · Source

Currently working on a graphical user interface. I am trying to make the layout out of 3 QFrames.

As seen in the screenshot below, the yellow frame is on the right side. I would like that frame to be on top of the right frame. (On top of the numpad, taking the whole horizontal space)

Also, for the numpad buttons on the right frame. I would like them to be as close to each other as they can be, like a numpad on a keyboard. How would I adjust the grid to do that?

enter image description here

EDITED

This is how I want the outcome to be. Where the red frame is the rightTopFrame (Yellow frame in first picture).

enter image description here

Code:

def layoutUI(self):
        
        ### Right Top Frame
        self.rightTopFrame = QFrame()
        self.rightTopFrame.resize(1,1)
        self.rightTopFrame.setStyleSheet("background-color: yellow")
        
        
        ### Left Grid
        self.leftGrid = QGridLayout()
        self.leftGrid.setColumnMinimumWidth(10, 10)
        self.leftGrid.setRowMinimumHeight(1, 1) 
        
        # Run, Stop, Speed layout   
        self.leftGrid.addWidget(self.b1, 0, 0)
        self.leftGrid.addWidget(self.b2, 0, 2)
        
        self.leftGrid.addWidget(self.b3, 1, 0)
        self.leftGrid.addWidget(self.l1, 1, 1)
        self.leftGrid.addWidget(self.b4, 1, 2)  
        
        # pl (Pieces and Length) layout     
        self.leftGrid.addWidget(self.b5, 2, 0)
        self.leftGrid.addWidget(self.l2, 2, 1)
        self.leftGrid.addWidget(self.b6, 2, 2)
        
        self.leftGrid.addWidget(self.b7, 3, 0)
        self.leftGrid.addWidget(self.l3, 3, 1)
        self.leftGrid.addWidget(self.b8, 3, 2)
        
        # Manual
        self.leftGrid.addWidget(self.l4, 4, 1)
        
        self.leftGrid.addWidget(self.b9, 5, 0)
        self.leftGrid.addWidget(self.b10, 5, 1)
        self.leftGrid.addWidget(self.b11, 5, 2)



        
        ### Right Grid
        self.rightGrid = QGridLayout()
        self.rightGrid.setColumnMinimumWidth(0, 0)
        self.rightGrid.setRowMinimumHeight(1, 1)    
        
        
        
        self.rightGrid.addWidget(self.np1, 2, 0)
        self.rightGrid.addWidget(self.np2, 2, 1)
        self.rightGrid.addWidget(self.np3, 2, 2)
        self.rightGrid.addWidget(self.np4, 3, 0)
        self.rightGrid.addWidget(self.np5, 3, 1)
        self.rightGrid.addWidget(self.np6, 3, 2)
        self.rightGrid.addWidget(self.np7, 4, 0)
        self.rightGrid.addWidget(self.np8, 4, 1)
        self.rightGrid.addWidget(self.np9, 4, 2)
        self.rightGrid.addWidget(self.np0, 5, 1)
        self.rightGrid.addWidget(self.npCl, 5, 0)
        
        #self.rightGrid.addWidget(self.bExit, 0, 2)
        
        
        
                
        ### Left Frame
        self.leftFrame = QFrame()
        self.leftFrame.resize(150,550)
        #self.leftFrame.setStyleSheet("background-color: red")
        self.leftFrame.setLayout(self.leftGrid)
        
        ### Right Frame
        self.rightFrame = QFrame()
        self.rightFrame.resize(15,50)
        #self.rightFrame.setStyleSheet("background-color: green")
        self.rightFrame.setLayout(self.rightGrid)
        
        
        
        
        
        ### Main Grid
        self.mainGrid = QGridLayout()
        self.mainGrid.setColumnMinimumWidth(10, 0)
        self.mainGrid.addWidget(self.leftFrame)
        self.mainGrid.addWidget(self.rightFrame)
        self.mainGrid.addWidget(self.rightTopFrame)
        
        
        ### Main Interface
        self.setGeometry(300, 200, 850, 450)
        self.setLayout(self.mainGrid)
        self.setStyleSheet("background-color: %s" % backgroundColor)    
        self.setWindowTitle('Signal & slot')
        self.show()

Answer

eyllanesc picture eyllanesc · Jan 5, 2017

In order for the frame to be underneath the numpad you must place them as a base. For the buttons to be together you must zero the space in the QGridLayout that contains them({your layout}.setSpacing(0)), in addition to adding QSpacerItem around the QGridLayout. If you have any questions, I'll leave you the complete code.

import sys
from itertools import product

from PyQt5.QtWidgets import QApplication, QFrame, QGridLayout, QHBoxLayout, QPushButton, QSizePolicy, QSpacerItem, QToolButton, QVBoxLayout, QWidget


class Widget(QWidget):
    def __init__(self, parent=None):
        super(Widget, self).__init__(parent=parent)
        self.layoutUI()

    def layoutUI(self):
        self.setStyleSheet("background-color: brown;")

        self.principalLayout = QHBoxLayout(self)

        self.rightFrame = QFrame(self)
        self.rightFrame.setFrameShape(QFrame.StyledPanel)
        self.rightFrame.setFrameShadow(QFrame.Raised)
        self.verticalLayout = QVBoxLayout(self.rightFrame)
        self.gridLayout = QGridLayout()

        btns = {(0, 0): "start", (0, 2): "Stop",
                (1, 0): "Speed-", (1, 1): "1", (1, 2): "Speed+",
                (2, 0): "Pieces", (2, 1): "0", (2, 2): "Clear",
                (3, 0): "Length", (3, 1): "0", (3, 2): "Clear",
                (4, 1): "Manual",
                (5, 0): "Cut", (5, 1): "Feed", (5, 2): "Clear"}
        for pos, name in btns.items():
            x, y = pos
            btn = QPushButton(self.rightFrame)
            btn.setText(name)
            self.gridLayout.addWidget(btn, x, y)

        self.verticalLayout.addLayout(self.gridLayout)
        self.principalLayout.addWidget(self.rightFrame)

        self.verticalLayoutR = QVBoxLayout()
        self.verticalLayoutR.setSpacing(0)
        self.exitFrame = QFrame(self)
        self.exitFrame.setStyleSheet("background-color: red;")
        self.exitFrame.setFrameShape(QFrame.StyledPanel)
        self.exitFrame.setFrameShadow(QFrame.Raised)
        self.exitverticalLayout = QVBoxLayout(self.exitFrame)
        self.exitBtn = QPushButton("Exit", self.exitFrame)
        self.exitverticalLayout.addWidget(self.exitBtn)
        self.verticalLayoutR.addWidget(self.exitFrame)

        self.numpadFrame = QFrame(self)
        self.numpadFrame.setStyleSheet("background-color: yellow;")
        self.numpadFrame.setFrameShape(QFrame.StyledPanel)
        self.numpadFrame.setFrameShadow(QFrame.Raised)
        self.horizontalLayout = QHBoxLayout(self.numpadFrame)
        spacerItem = QSpacerItem(2, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
        self.horizontalLayout.addItem(spacerItem)
        self.verticalLayout = QVBoxLayout()
        spacerItem1 = QSpacerItem(20, 57, QSizePolicy.Minimum, QSizePolicy.Expanding)
        self.verticalLayout.addItem(spacerItem1)
        self.gridLayout = QGridLayout()
        self.gridLayout.setSpacing(0)

        x = (0, 1, 2)

        coords = list(product(x, x))
        coords.append((3, 1))

        for coord in coords:
            x, y = coord
            button = QPushButton(self.numpadFrame)
            button.setFixedSize(60, 60)
            button.setText(str(x + 3 * y + 1))
            button.setStyleSheet("background-color: white;")
            self.gridLayout.addWidget(button, x, y)
        button.setText("0")

        self.verticalLayout.addLayout(self.gridLayout)
        spacerItem2 = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)
        self.verticalLayout.addItem(spacerItem2)
        self.horizontalLayout.addLayout(self.verticalLayout)
        spacerItem3 = QSpacerItem(2, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
        self.horizontalLayout.addItem(spacerItem3)

        self.verticalLayoutR.addWidget(self.numpadFrame)

        self.adminFrame = QFrame(self)
        self.adminFrame.setStyleSheet("background-color: blue;")
        self.adminFrame.setFrameShape(QFrame.StyledPanel)
        self.adminFrame.setFrameShadow(QFrame.Raised)
        self.horizontalLayout = QHBoxLayout(self.adminFrame)
        spacerItem = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
        self.horizontalLayout.addItem(spacerItem)
        self.adminBtn = QPushButton("Admin", self.adminFrame)
        self.horizontalLayout.addWidget(self.adminBtn)
        self.verticalLayoutR.addWidget(self.adminFrame)
        self.principalLayout.addLayout(self.verticalLayoutR)

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

Output:

enter image description here