Есть ли альтернатива QGridLayout, которая поддерживает точное размещение по сетке?

Если использовать QGridLayout и пробовать разместить элементы в разных местах, например так:

button1 = QPushButton('0, 0')
button2 = QPushButton('2, 4')
grid.addWidget(button1, 0, 0)
grid.addWidget(button2, 2, 4)

Тогда они разместятся рядом друг с другом, а не по заданным ячейкам.
Есть ли такой лей-аут, где элементы располагаются по заданным позициям?

Виджет QStackedWidget мне не подходит.


Ответы (2 шт):

Автор решения: Maxim Timakov

Один из вариантов("костылей") - использование setRowMinimumHeight / setColumnMinimumWidth

def insert_widget_to_grid(grid: QGridLayout, widget: QWidget, row: int, col: int)
    c_rows: int = grid.rowCount()
    c_cols: int = grid.columnCount()
    
    # expand table
    DEF_HEIGHT = 42
    DEF_WIDTH = 42
    
    while c_rows <= row:
        grid.setRowMinimumHeight(c_rows, DEF_HEIGHT)
        c_rows += 1
    
    while c_cols <= row:
        grid.setColumnMinimumWidth(c_cols, DEF_WIDTH)
        c_cols += 1
    
    # insert widget
    grid.addWidget(widget, row, col)

qgridLayout as table

Тестовый код на C++

#include "widget.h"
#include <QGridLayout>
#include <QPushButton>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    auto grid = new QGridLayout;

    for(int i = 0; i < 10; ++i)
    {
        grid->setColumnMinimumWidth(i, 30);
        grid->setRowMinimumHeight(i, 30);
    }


    auto b_00 = new QPushButton{"00, 00"};
    auto b_44 = new QPushButton{"04, 04"};
    grid->addWidget(b_00, 0, 0);
    grid->addWidget(b_44, 4, 4);

    setLayout(grid);
}

Widget::~Widget() {}
→ Ссылка
Автор решения: S. Nick

Я увидел вашу задачу так. Поменяйте импорты на свои и попродуйте.

main.py:

import sys
from PyQt5 import QtCore, QtGui, QtWidgets


class Frame(QtWidgets.QFrame):
    def __init__(self, num, size):
        super().__init__()  
        
        self.setMinimumSize(*size)    
        self.layout = QtWidgets.QGridLayout(self)
   

class MainWindow(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        self.setObjectName('mainwidget') 
        many_cells = 15       # хотим создать 15 ячеек
        column = 5            # хотим разместить эти ячееки в 5 колонки
        size = (80, 80)       # размер ячееки, например 80х80 
        self.dict_cells_widgets = {}
 
        grid = QtWidgets.QGridLayout(self)
                
        for step in range(many_cells):
            cell = Frame(step+1, size)           
            row = step // column
            col = step % column
            cell.setObjectName(f'frame_{row}_{col}')
            grid.addWidget(cell, row, col) 
            self.dict_cells_widgets[row, col] = cell 
        
        _list = (0, 0), (2, 4)
        for (row, col) in _list:
            cell = self.dict_cells_widgets[row, col]
            button = QtWidgets.QPushButton(f'{row}, {col}') 
            button.clicked.connect(
                lambda ch, row=row, col=col: print(row, col))
            cell.layout.addWidget(button, 1, 1)


QSS = '''
QPushButton {
    font-size: 12pt;
    background-color: #ccffbd;
}
QFrame {
    background-color: #dbafbd;
}
#mainwidget {
    background-color: #55afbd;
}
#frame_2_0 {
    background-color: translate;
}
#frame_0_4 {
    border-image: url(opencv_color.jpg) 0 0 0 0 stretch stretch;
}
'''


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    app.setStyle(QtWidgets.QStyleFactory.create("Fusion"))
    app.setStyleSheet(QSS) 
    
    w = MainWindow()
    w.resize(400, 280)
    w.show()
    sys.exit(app.exec_())

введите сюда описание изображения

введите сюда описание изображения


opencv_color.jpg

введите сюда описание изображения

→ Ссылка