如何修改此PyQt5当前设置以在布局之间启用拖动调整大小

问题描述 投票:0回答:2

如何修改此当前设置以在以下所示的布局之间(水平和垂直)调整大小?假设我要通过使用鼠标拖动来调整列表在右侧向左的大小,我希望图像缩小并且列表在扩大,并且在两个列表之间同样适用。

window

这是代码:

from PyQt5.QtWidgets import (QMainWindow, QApplication, QDesktopWidget, QHBoxLayout, QVBoxLayout, QWidget,
                             QLabel, QListWidget)
from PyQt5.QtGui import QPixmap
from PyQt5.QtCore import Qt
import sys


class TestWindow(QMainWindow):
    def __init__(self, left_ratio, right_ratio, window_title):
        super().__init__()
        self.left_ratio = left_ratio
        self.right_ratio = right_ratio
        self.current_image = None
        self.window_title = window_title
        self.setWindowTitle(self.window_title)
        win_rectangle = self.frameGeometry()
        center_point = QDesktopWidget().availableGeometry().center()
        win_rectangle.moveCenter(center_point)
        self.move(win_rectangle.topLeft())
        self.tools = self.addToolBar('Tools')
        self.left_widgets = {'Image': QLabel()}
        self.right_widgets = {'List1t': QLabel('List1'), 'List1l': QListWidget(),
                              'List2t': QLabel('List2'), 'List2l': QListWidget()}
        self.central_widget = QWidget(self)
        self.main_layout = QHBoxLayout()
        self.left_layout = QVBoxLayout()
        self.right_layout = QVBoxLayout()
        self.adjust_widgets()
        self.adjust_layouts()
        self.show()

    def adjust_layouts(self):
        self.main_layout.addLayout(self.left_layout, self.left_ratio)
        self.main_layout.addLayout(self.right_layout, self.right_ratio)
        self.central_widget.setLayout(self.main_layout)
        self.setCentralWidget(self.central_widget)

    def adjust_widgets(self):
        self.left_layout.addWidget(self.left_widgets['Image'])
        self.left_widgets['Image'].setPixmap(QPixmap('test.jpg').scaled(500, 400, Qt.IgnoreAspectRatio,
                                                                        Qt.SmoothTransformation))
        for widget in self.right_widgets.values():
            self.right_layout.addWidget(widget)


if __name__ == '__main__':
    test = QApplication(sys.argv)
    test_window = TestWindow(6, 4, 'Test')
    sys.exit(test.exec_())
python-3.x user-interface pyqt pyqt5
2个回答
0
投票

将图像重新缩放为任意尺寸并保持其纵横比的一种方法是,将QWidget子类化,并覆盖sizeHintpaintEvent,并用它代替QLabel来显示图像,例如

class PixmapWidget(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self._pixmap = None

    def sizeHint(self):
        if self._pixmap:
            return self._pixmap.size()
        else:
            return QSize()

    def setPixmap(self, pixmap):
        self._pixmap = pixmap
        self.update()

    def paintEvent(self, event):
        painter = QPainter(self)
        super().paintEvent(event)
        if self._pixmap:
            size = self._pixmap.size().scaled(self.size(), Qt.KeepAspectRatio)
            offset = (self.size() - size)/2
            rect = QRect(offset.width(), offset.height(), size.width(), size.height())
            painter.drawPixmap(rect, self._pixmap)

由于您是QMainWindow的子类,您可以使用DockWidget来显示列表,而不是将它们添加到中央窗口小部件的布局中,例如

class TestWindow(QMainWindow):
    def __init__(self, left_ratio, right_ratio, window_title):
        super().__init__()
        #self.left_ratio = left_ratio    <--- not needed since image and lists
        #self.right_ratio = right_ratio  <--- are not sharing a layout anymore

        ...

        # use PixmapWidget instead of QLabel for showing image
        # refactor dictionary for storing lists to make adding DockWidgets easier
        self.left_widgets = {'Image': PixmapWidget()}
        self.right_widgets = {'List1': QListWidget(),
                              'List2': QListWidget()}
        self.central_widget = QWidget(self)
        # self.main_layout = QHBoxLayout()  <-- not needed anymore
        self.left_layout = QVBoxLayout()

        self.adjust_widgets()
        self.adjust_layouts()
        self.show()

    def adjust_layouts(self):
        self.central_widget.setLayout(self.left_layout)
        self.setCentralWidget(self.central_widget)

    def adjust_widgets(self):
        self.left_layout.addWidget(self.left_widgets['Image'])
        self.left_widgets['Image'].setPixmap(QPixmap('test.jpg').scaled(500, 400, Qt.IgnoreAspectRatio, Qt.SmoothTransformation))

        self.dock_widgets = []
        for text, widget in self.right_widgets.items():
            dock_widget = QDockWidget(text)
            dock_widget.setFeatures(QDockWidget.NoDockWidgetFeatures)
            dock_widget.setWidget(widget)
            self.addDockWidget(Qt.RightDockWidgetArea, dock_widget)
            self.dock_widgets.append(dock_widget)

屏幕截图


0
投票

您需要使用QSplitter

它的行为几乎类似于盒子的布局,但是具有允许调整每个项目大小的句柄。

请注意,您只能将小部件添加到QSplitter,而不能将其添加到布局,因此,如果需要添加可以调整其内容大小的“节”(标签和小部件),则必须创建容器具有自己布局的小部件。

还要注意,强烈建议不要将字典用于这类事情。对于3.7之前的Python版本,字典顺序是完全任意的,虽然有时可能是一致的(例如,当键是整数时),但通常不是这样:在您的代码中有时放置了标签在一起,有时将小部件反转,等等,因此,如果有人在<= 3.6的情况下使用您的程序,则界面将不一致。考虑到这一点,虽然python 3.6将于2022年寿终正寝,但即使在那之后,仍有很多人仍会使用以前的版本。如果您需要一种将对象分组的方法,则最好使用列表或元组,就像我在以下示例中所做的那样。

如果您really “ need”]]使用基于密钥的组,则可以使用OrderedDict,但是最有可能的逻辑背后存在一些问题,因此需要从头开始。

class TestWindow(QMainWindow):
    def __init__(self, left_ratio, right_ratio, window_title):
        super().__init__()
        self.left_ratio = left_ratio
        self.right_ratio = right_ratio
        self.current_image = None
        self.window_title = window_title
        self.setWindowTitle(self.window_title)
        win_rectangle = self.frameGeometry()
        center_point = QDesktopWidget().availableGeometry().center()
        win_rectangle.moveCenter(center_point)
        self.move(win_rectangle.topLeft())
        self.tools = self.addToolBar('Tools')
        self.left_widgets = {'Image': QLabel()}
        self.right_widgets = [(QLabel('List1'), QListWidget()),
                              (QLabel('List2'), QListWidget())]
        self.central_widget = QSplitter(Qt.Horizontal, self)
        self.setCentralWidget(self.central_widget)
        self.right_splitter = QSplitter(Qt.Vertical, self)
        self.adjust_widgets()
        self.central_widget.setStretchFactor(0, left_ratio)
        self.central_widget.setStretchFactor(1, right_ratio)
        self.show()

    def adjust_widgets(self):
        self.central_widget.addWidget(self.left_widgets['Image'])
        self.left_widgets['Image'].setPixmap(QPixmap('test.jpg').scaled(500, 400, Qt.IgnoreAspectRatio,
                                                                        Qt.SmoothTransformation))
        self.left_widgets['Image'].setScaledContents(True)
        self.central_widget.addWidget(self.right_splitter)
        for label, widget in self.right_widgets:
            container = QWidget()
            layout = QVBoxLayout(container)
            layout.addWidget(label)
            layout.addWidget(widget)
            self.right_splitter.addWidget(container)
© www.soinside.com 2019 - 2024. All rights reserved.