@KenAppleby-0
I have an extremely stupid proof of concept that sort of does what I describe in the initial message, it's extremely rough and should not be considered a good idea by anybody, but here goes:
from PyQt6.QtWidgets import QWidget, QPushButton, QGridLayout, QSizePolicy, QApplication
from PyQt6.QtGui import QColor, QPalette
from PyQt6.QtCore import Qt
class BorderWidget(QWidget):
def __init__(self, widget_id, side, layout=None, row=None, column=None):
super(BorderWidget, self).__init__()
self.widget_id = widget_id
self.side = side
self.layout = layout
self.row = row
self.column = column
pal = self.palette()
pal.setColor(QPalette.ColorRole.Window, QColor('white'))
self.setAutoFillBackground(True)
self.setPalette(pal)
self.pressed = False
def mousePressEvent(self, event):
super(BorderWidget, self).mousePressEvent(event)
print(f"Clicked on {self.side} border of widget {self.widget_id}")
print(f"self.press is {self.pressed}")
self.pressed = True
self.last_x = event.globalPosition().x()
self.last_y = event.globalPosition().y()
def mouseReleaseEvent(self, event):
self.pressed = False
def mouseMoveEvent(self, event):
if self.pressed and self.layout is not None:
dx = event.globalPosition().x() - self.last_x
self.last_x = event.globalPosition().x()
dy = event.globalPosition().y() - self.last_y
self.last_y = event.globalPosition().y()
if dx != 0:
if self.side in ['right', 'left']:
new_stretch = max(1, self.layout.columnStretch(self.column) - dx)
self.layout.setColumnStretch(self.column, int(new_stretch))
elif self.side in ['bottom', 'top']:
new_stretch = max(1, self.layout.rowStretch(self.row) - dy)
self.layout.setRowStretch(self.row, int(new_stretch))
class DraggableWrapper(QWidget):
def __init__(self, widget, widget_id, main_layout, row, column):
super(DraggableWrapper, self).__init__()
self.layout = QGridLayout(self)
self.layout.setSpacing(0)
self.layout.setContentsMargins(0, 0, 0, 0)
self.border_top = BorderWidget(widget_id, 'top', main_layout, row, column)
self.border_bottom = BorderWidget(widget_id, 'bottom', main_layout, row + 1, column)
self.border_left = BorderWidget(widget_id, 'left', main_layout, row, column)
self.border_right = BorderWidget(widget_id, 'right', main_layout, row, column + 1)
self.border_top_left_horizontal = BorderWidget(widget_id, 'topleft', main_layout, column)
self.border_top_right_horizontal = BorderWidget(widget_id, 'topright', main_layout, column)
self.border_bottom_left_horizontal = BorderWidget(widget_id, 'bottomleft', main_layout, column)
self.border_bottom_right_horizontal = BorderWidget(widget_id, 'bottomright', main_layout, column)
self.layout.addWidget(widget, 1, 1)
self.layout.addWidget(self.border_top, 0, 1)
self.layout.addWidget(self.border_bottom, 2, 1)
self.layout.addWidget(self.border_left, 0, 0, 3, 1) # cover the corners
self.layout.addWidget(self.border_right, 0, 2, 3, 1) # cover the corners
self.layout.addWidget(self.border_top_left_horizontal, 0, 0)
self.layout.addWidget(self.border_top_right_horizontal, 0, 2)
self.layout.addWidget(self.border_bottom_left_horizontal, 2, 0)
self.layout.addWidget(self.border_bottom_right_horizontal, 2, 2)
border_width = 10
self.border_top.setFixedHeight(border_width)
self.border_bottom.setFixedHeight(border_width)
self.border_left.setFixedWidth(border_width)
self.border_right.setFixedWidth(border_width)
# apply size restrictions to corner border widgets to form L-shaped corners
self.border_top_left_horizontal.setFixedSize(border_width, border_width)
self.border_top_right_horizontal.setFixedSize(border_width, border_width)
self.border_bottom_left_horizontal.setFixedSize(border_width, border_width)
self.border_bottom_right_horizontal.setFixedSize(border_width, border_width)
# Apply size policies
self.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
widget.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
class MainWindow(QWidget):
def __init__(self):
super().__init__()
layout = QGridLayout(self)
layout.setSpacing(0)
default_stretch = 300
layout.setRowStretch(0, default_stretch)
layout.setRowStretch(1, default_stretch)
layout.setColumnStretch(0, default_stretch)
layout.setColumnStretch(1, default_stretch)
widget1 = QPushButton("Button 1")
wrapper1 = DraggableWrapper(widget1, '1', layout, 0, 0)
widget2 = QPushButton("Button 2")
wrapper2 = DraggableWrapper(widget2, '2', layout, 0, 1)
widget3 = QPushButton("Button 3")
wrapper3 = DraggableWrapper(widget3, '3', layout, 1, 0)
widget4 = QPushButton("Button 4")
wrapper4 = DraggableWrapper(widget4, '4', layout, 1, 1)
layout.setContentsMargins(0, 0, 0, 0)
layout.addWidget(wrapper1, 0, 0)
layout.addWidget(wrapper2, 0, 1)
layout.addWidget(wrapper3, 1, 0)
layout.addWidget(wrapper4, 1, 1)
if __name__ == '__main__':
app = QApplication([])
mainWin = MainWindow()
mainWin.setMinimumSize(800, 800)
mainWin.show()
app.exec()