天道酬勤,学无止境

QScrollArea with FlowLayout widgets not resizing properly

I want to create a widget similar to the KDE (or Gnome or MacOS) system settings (e.g., like this picture)

I already implemented a FlowLayout from the Qt docs exampe.

If I put some FlowLayout widgets (wrapped in a container widget with a QVBoxLayout) into a QScrollArea and resize the QSrollArea, everything flows and re-layouts as it shoulds.

However, if I increase the scroll area’s width so that it needs less height, the scroll area’s still thinks that its widgets require the orginal height for their minimumWidth:

0_1507630989642_flow_layout_in_scrollarea.gif

How can I can I update the scroll area with the actual height of its child so that the vertical scroll bar disappears when it’s no longer needed?

Below, you’ll find the (Python) implementation of the FlowLayout and in the __main__ block the actual example.

Cheers, Stefan

"""
PyQt5 port of the `layouts/flowlayout
<https://doc.qt.io/qt-5/qtwidgets-layouts-flowlayout-example.html>`_ example
from Qt5.

Usage:

    python3 -m pip install pyqt5
    python3 flow_layout.py

"""
from PyQt5.QtCore import pyqtSignal, QPoint, QRect, QSize, Qt
from PyQt5.QtWidgets import QLayout, QSizePolicy, QSpacerItem


class FlowLayout(QLayout):
    """A ``QLayout`` that aranges its child widgets horizontally and
    vertically.

    If enough horizontal space is available, it looks like an ``HBoxLayout``,
    but if enough space is lacking, it automatically wraps its children into
    multiple rows.

    """
    heightChanged = pyqtSignal(int)

    def __init__(self, parent=None, margin=0, spacing=-1):
        super().__init__(parent)
        if parent is not None:
            self.setContentsMargins(margin, margin, margin, margin)
        self.setSpacing(spacing)

        self._item_list = []

    def __del__(self):
        while self.count():
            self.takeAt(0)

    def addItem(self, item):  # pylint: disable=invalid-name
        self._item_list.append(item)

    def addSpacing(self, size):  # pylint: disable=invalid-name
        self.addItem(QSpacerItem(size, 0, QSizePolicy.Fixed, QSizePolicy.Minimum))

    def count(self):
        return len(self._item_list)

    def itemAt(self, index):  # pylint: disable=invalid-name
        if 0 <= index < len(self._item_list):
            return self._item_list[index]
        return None

    def takeAt(self, index):  # pylint: disable=invalid-name
        if 0 <= index < len(self._item_list):
            return self._item_list.pop(index)
        return None

    def expandingDirections(self):  # pylint: disable=invalid-name,no-self-use
        return Qt.Orientations(Qt.Orientation(0))

    def hasHeightForWidth(self):  # pylint: disable=invalid-name,no-self-use
        return True

    def heightForWidth(self, width):  # pylint: disable=invalid-name
        height = self._do_layout(QRect(0, 0, width, 0), True)
        return height

    def setGeometry(self, rect):  # pylint: disable=invalid-name
        super().setGeometry(rect)
        self._do_layout(rect, False)

    def sizeHint(self):  # pylint: disable=invalid-name
        return self.minimumSize()

    def minimumSize(self):  # pylint: disable=invalid-name
        size = QSize()

        for item in self._item_list:
            minsize = item.minimumSize()
            extent = item.geometry().bottomRight()
            size = size.expandedTo(QSize(minsize.width(), extent.y()))

        margin = self.contentsMargins().left()
        size += QSize(2 * margin, 2 * margin)
        return size

    def _do_layout(self, rect, test_only=False):
        m = self.contentsMargins()
        effective_rect = rect.adjusted(+m.left(), +m.top(), -m.right(), -m.bottom())
        x = effective_rect.x()
        y = effective_rect.y()
        line_height = 0

        for item in self._item_list:
            wid = item.widget()

            space_x = self.spacing()
            space_y = self.spacing()
            if wid is not None:
                space_x += wid.style().layoutSpacing(
                    QSizePolicy.PushButton, QSizePolicy.PushButton, Qt.Horizontal)
                space_y += wid.style().layoutSpacing(
                    QSizePolicy.PushButton, QSizePolicy.PushButton, Qt.Vertical)

            next_x = x + item.sizeHint().width() + space_x
            if next_x - space_x > effective_rect.right() and line_height > 0:
                x = effective_rect.x()
                y = y + line_height + space_y
                next_x = x + item.sizeHint().width() + space_x
                line_height = 0

            if not test_only:
                item.setGeometry(QRect(QPoint(x, y), item.sizeHint()))

            x = next_x
            line_height = max(line_height, item.sizeHint().height())

        new_height = y + line_height - rect.y()
        self.heightChanged.emit(new_height)
        return new_height


if __name__ == '__main__':
    import sys
    from PyQt5.QtWidgets import QApplication, QPushButton, QScrollArea, QVBoxLayout, QWidget


    class Container(QWidget):
        def __init__(self):
            super().__init__()
            self.setLayout(QVBoxLayout())
            self._widgets = []

        def sizeHint(self):
            w = self.size().width()
            h = 0
            for widget in self._widgets:
                h += widget.layout().heightForWidth(w)

            sh = super().sizeHint()
            print(sh)
            print(w, h)
            return sh

        def add_widget(self, widget):
            self._widgets.append(widget)
            self.layout().addWidget(widget)

        def add_stretch(self):
            self.layout().addStretch()


    app = QApplication(sys.argv)  # pylint: disable=invalid-name
    container = Container()
    for i in range(2):
        w = QWidget()
        w.setWindowTitle('Flow Layout')
        l = FlowLayout(w, 10)
        w.setLayout(l)
        l.addWidget(QPushButton('Short'))
        l.addWidget(QPushButton('Longer'))
        l.addWidget(QPushButton('Different text'))
        l.addWidget(QPushButton('More text'))
        l.addWidget(QPushButton('Even longer button text'))
        container.add_widget(w)
    container.add_stretch()

    sa = QScrollArea()
    sa.setWidgetResizable(True)
    sa.setWidget(container)
    sa.show()

    sys.exit(app.exec_())
标签

评论

The solution was (surprisingly) simple: Use the FlowLayout’s heightChanged signal to update the minimum height of the container (the ScrollArea’s widget).

Here is a working example:

"""
PyQt5 port of the `layouts/flowlayout
<https://doc.qt.io/qt-5/qtwidgets-layouts-flowlayout-example.html>`_ example
from Qt5.

"""
from PyQt5.QtCore import pyqtSignal, QPoint, QRect, QSize, Qt
from PyQt5.QtWidgets import QLayout, QSizePolicy, QSpacerItem


class FlowLayout(QLayout):
    """A ``QLayout`` that aranges its child widgets horizontally and
    vertically.

    If enough horizontal space is available, it looks like an ``HBoxLayout``,
    but if enough space is lacking, it automatically wraps its children into
    multiple rows.

    """
    heightChanged = pyqtSignal(int)

    def __init__(self, parent=None, margin=0, spacing=-1):
        super().__init__(parent)
        if parent is not None:
            self.setContentsMargins(margin, margin, margin, margin)
        self.setSpacing(spacing)

        self._item_list = []

    def __del__(self):
        while self.count():
            self.takeAt(0)

    def addItem(self, item):  # pylint: disable=invalid-name
        self._item_list.append(item)

    def addSpacing(self, size):  # pylint: disable=invalid-name
        self.addItem(QSpacerItem(size, 0, QSizePolicy.Fixed, QSizePolicy.Minimum))

    def count(self):
        return len(self._item_list)

    def itemAt(self, index):  # pylint: disable=invalid-name
        if 0 <= index < len(self._item_list):
            return self._item_list[index]
        return None

    def takeAt(self, index):  # pylint: disable=invalid-name
        if 0 <= index < len(self._item_list):
            return self._item_list.pop(index)
        return None

    def expandingDirections(self):  # pylint: disable=invalid-name,no-self-use
        return Qt.Orientations(Qt.Orientation(0))

    def hasHeightForWidth(self):  # pylint: disable=invalid-name,no-self-use
        return True

    def heightForWidth(self, width):  # pylint: disable=invalid-name
        height = self._do_layout(QRect(0, 0, width, 0), True)
        return height

    def setGeometry(self, rect):  # pylint: disable=invalid-name
        super().setGeometry(rect)
        self._do_layout(rect, False)

    def sizeHint(self):  # pylint: disable=invalid-name
        return self.minimumSize()

    def minimumSize(self):  # pylint: disable=invalid-name
        size = QSize()

        for item in self._item_list:
            minsize = item.minimumSize()
            extent = item.geometry().bottomRight()
            size = size.expandedTo(QSize(minsize.width(), extent.y()))

        margin = self.contentsMargins().left()
        size += QSize(2 * margin, 2 * margin)
        return size

    def _do_layout(self, rect, test_only=False):
        m = self.contentsMargins()
        effective_rect = rect.adjusted(+m.left(), +m.top(), -m.right(), -m.bottom())
        x = effective_rect.x()
        y = effective_rect.y()
        line_height = 0

        for item in self._item_list:
            wid = item.widget()

            space_x = self.spacing()
            space_y = self.spacing()
            if wid is not None:
                space_x += wid.style().layoutSpacing(
                    QSizePolicy.PushButton, QSizePolicy.PushButton, Qt.Horizontal)
                space_y += wid.style().layoutSpacing(
                    QSizePolicy.PushButton, QSizePolicy.PushButton, Qt.Vertical)

            next_x = x + item.sizeHint().width() + space_x
            if next_x - space_x > effective_rect.right() and line_height > 0:
                x = effective_rect.x()
                y = y + line_height + space_y
                next_x = x + item.sizeHint().width() + space_x
                line_height = 0

            if not test_only:
                item.setGeometry(QRect(QPoint(x, y), item.sizeHint()))

            x = next_x
            line_height = max(line_height, item.sizeHint().height())

        new_height = y + line_height - rect.y()
        self.heightChanged.emit(new_height)
        return new_height


if __name__ == '__main__':
    import sys
    from PyQt5.QtWidgets import QApplication, QPushButton, QScrollArea, QVBoxLayout, QWidget, QGroupBox

    app = QApplication(sys.argv)

    container = QWidget()
    container_layout = QVBoxLayout()
    for i in range(2):
        g = QGroupBox(f'Group {i}')
        l = FlowLayout(margin=10)
        l.heightChanged.connect(container.setMinimumHeight)
        g.setLayout(l)
        l.addWidget(QPushButton('Short'))
        l.addWidget(QPushButton('Longer'))
        l.addWidget(QPushButton('Different text'))
        l.addWidget(QPushButton('More text'))
        l.addWidget(QPushButton('Even longer button text'))
        container_layout.addWidget(g)
    container_layout.addStretch()
    container.setLayout(container_layout)

    w = QScrollArea()
    w.setWindowTitle('Flow Layout')
    w.setWidgetResizable(True)
    w.setWidget(container)
    w.show()

    sys.exit(app.exec_())

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • 随着更多的小部件放在其中,我如何调整QScrollArea内容的大小(How do i resize the contents of a QScrollArea as more widgets are placed inside)
    问题 我有一个QScrollArea窗口小部件,它开始为空; 它具有一个垂直布局,一个QGridLayout和一个垂直间隔器,以使其位于顶部,并防止其在整个滚动区域上拉伸; 在程序的其他地方,有一个QTextEdit,当对其进行更改时,将对其内容进行扫描以查找“ species”元素,然后将它们添加到QGridLayout中。 任何已删除的物种元素也将被删除。 这个位有效; 我一直都在打开垂直滚动条,因此当它出现时,它不会位于其中的其他内容之上。 请注意,尽管不需要,滚动条已经大于滚动框。 这就是问题。 滚动区域似乎是预设的,我无法更改。 如果我向QGridLayout添加更多行,则滚动区域的大小不会增加。 取而代之的是,它保持相同的大小,并挤压QGridLayout,使其看上去很丑(一开始)。 然后添加更多的东西就变得不可用了。 再次注意,滚动条的大小仍与之前的图像相同。 前两个图像来自Qt Designer,后三个图像来自程序运行。 如果我调整窗口大小以使QScrollArea增大,那么我会看到以下内容: 指示滚动区域内部存在某些布局,无法正确调整其大小。 我的问题是; 添加和从QGridLayout中删除时,我该怎么做才能使窗口小部件的可滚动区域动态调整大小? 回答1 该文档提供了一个答案: widgetResizable:布尔此属性保存滚动区域是否应调整视图窗口小部件的大小
  • PyQt:QScrollArea 内小部件的环绕式布局(PyQt: wrap-around layout of widgets inside a QScrollArea)
    问题 我正在开发一个使用 PyQt4 记忆文本的应用程序。 我想在气泡中显示所有单词,以便您查看单词的长度。 但是当我在QScrollArea拥有所有气泡时,它们将一个排列在另一个下方。 我想让它们并排对齐,但使用自动换行。 我使用带圆角边框的QLabel使气泡工作。 但是现在我在QLabel's有单词,PyQt 不将它们视为单词 - 而是作为小部件。 所以 PyQt 把一个小部件放在另一个小部件下面。 我希望小部件并排对齐,直到它们到达行尾,然后它们应该环绕到下一行 - 这意味着QLabel's应该像文本文档中的单词一样。 到目前为止,这是我的代码: f = open(r'myFile.txt') class Bubble(QtGui.QLabel): def __init__(self, text): super(Bubble, self).__init__(text) self.word = text self.setContentsMargins(5, 5, 5, 5) def paintEvent(self, e): p = QtGui.QPainter(self) p.setRenderHint(QtGui.QPainter.Antialiasing,True) p.drawRoundedRect(0,0,self.width()-1,self.height()-1,5
  • How do i resize the contents of a QScrollArea as more widgets are placed inside
    I have a QScrollArea Widget, which starts empty; It has a vertical layout, with a QGridLayout, and a vertical spacer to keep it at the top, and prevent it from stretching over the whole scroll area; Elsewhere in the program, there is a QTextEdit, which when changed, has its contents scanned for "species" elements, and then they are added to the QGridLayout. Any species elements which have been removed are removed too. This bit works; I have turned the vertical scrollbar on all the time, so that when it appears it does not sit on top of the other stuff in there. Note that the scroll bar is
  • QScrollArea具有动态更改的内容(QScrollArea with dynamically changing contents)
    问题 我有一个QScrollArea,其中带有一些按钮,如图所示。 布局的想法是:1.左右按钮过宽时,应使用左右按钮进行滚动 2.滚动区域中的按钮数量可以动态更改。3.应该使用任何可用空间来尽可能扩大滚动区域。 如果不存在此类空间,则应使用导航按钮进行滚动。 在我当前的实现中,当我增加按钮时,我有以下内容: 但是右边有可用空间,因此应如下所示: 例如,如果我再次增加到10,则应该出现滚动条(因为布局由小部件包含)。 我想知道除了手动调整小部件的大小以外是否还有其他方法(因为ui可以翻译,按钮可以更改大小提示,所以实际设计也更复杂:( 这是我对ScrollAreaTest小部件的实现: #include "MainWidget.h" #include <QLineEdit> #include <QVBoxLayout> #include <QHBoxLayout> #include <QScrollArea> #include <QPushButton> #include <QDebug> #include "ButtonWidget.h" #include "CheckableButtonGroup.h" MainWidget::MainWidget(QWidget *parent) : QWidget(parent), m_scrollArea( 0 ), m_lineEdit(
  • 为什么 QScrollArea 的大小受到限制?(Why is the QScrollArea restricted in size?)
    问题 对于从QWidget继承的自定义小部件,我添加了一个QScrollArea,如下所示: MainWindow::MainWindow(QWidget *parent) : QWidget(parent)//MainWindow is a QWidget { auto *scrollArea = new QScrollArea(this); auto *widget = new QWidget(this); widget->setStyleSheet("background-color:green"); scrollArea->setWidget(widget); scrollArea->setWidgetResizable(true); scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); QVBoxLayout *parentLayout = new QVBoxLayout(widget); this->setStyleSheet("background-color:blue"); for(int i=0;i<12;i++){ QHBoxLayout* labelLineEdit = f1(); parentLayout->addStretch(1); parentLayout->addLayout
  • QLabel 显示 QScrollArea 内的图像(QLabel showing an image inside a QScrollArea)
    问题 我已经在 Qt 中成功实现了一个图像查看器(用于 DICOM)。 我可以看到图像,并且可以正确放大和缩小。 现在,如果图像太大而无法在放大时显示,我想查看滚动条。 我用过用户界面。 我放置了一个QScrollArea 。 在里面, QLabel 。 VerticalScrollBarPolicy是ScrollBarAsNeeded 。 horizo​​ntalScrollBarPolicy是ScrollBarAsNeeded 。 问题是:它不起作用。 我放大,但没有出现滚动条。 第二次尝试:使用 QScrollArea 内的布局。 所以现在在 QScrollArea 和 QLabel 之间有一个QWidget :一个水平布局。 打开相同的图像,现在我可以在右侧看到一个垂直滚动条。 图像从左到右拉伸。 当我缩放图像时,它会得到正确的比例。 但是...我缩小并且滚动条是一样的,即使我可以看到整个图像。 水平滚动条永远不会出现。 调整 QLabel 的大小似乎没有影响。 但是,如果我调整 QScrollArea 的大小(调整主窗口的大小),则会出现水平滚动条。 我一直在检查一些数字: 在 QScrollArea 它的大小发生变化:低于 599 宽度(为什么是这个数字?我在任何地方都看不到)水平条出现。 sizeHint()总是返回相同的值:33x41 在 QLabel 尺寸会改变
  • QLabel showing an image inside a QScrollArea
    I've successfully implemented a Image Viewer (for DICOM) in Qt. I can see the image and I can zoom in and out correctly. Now, I want to see scroll bars if the image is too big to show when I zoom in. I've used the UI. I placed a QScrollArea. Inside, the QLabel. The verticalScrollBarPolicy is ScrollBarAsNeeded. The horizontalScrollBarPolicy is ScrollBarAsNeeded. The problem is: it doesn't work. I zoom in, but no scrollbar appears. Second try: using a layout inside the QScrollArea. So now there's a QWidget between the QScrollArea and the QLabel: a horizontal layout. Opened the same image, now I
  • QScrollArea resizing QWidget
    I have a QScrollArea, which displays a custom QWidget. Whenever the Scrollbar is displayed, it causes the entire widget to resize. I want some space to be left for the scrollbar, so that the entire widget is not resized. How can this be done?
  • QScrollArea 调整 QWidget 的大小(QScrollArea resizing QWidget)
    问题 我有一个 QScrollArea,它显示一个自定义 QWidget。 每当显示滚动条时,它都会导致整个小部件调整大小。 我希望为滚动条留出一些空间,以便不会调整整个小部件的大小。 如何才能做到这一点?
  • Why is the QScrollArea restricted in size?
    To my custom widget, inherited from QWidget, I have added a QScrollArea like this: MainWindow::MainWindow(QWidget *parent) : QWidget(parent)//MainWindow is a QWidget { auto *scrollArea = new QScrollArea(this); auto *widget = new QWidget(this); widget->setStyleSheet("background-color:green"); scrollArea->setWidget(widget); scrollArea->setWidgetResizable(true); scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); QVBoxLayout *parentLayout = new QVBoxLayout(widget); this->setStyleSheet("background-color:blue"); for(int i=0;i<12;i++){ QHBoxLayout* labelLineEdit = f1(); parentLayout-
  • QScrollArea with dynamically changing contents
    I have a QScrollArea with some buttons in it, like shown on the picture. The idea of the layout is: 1. The left and right button should be used for scrolling the buttons when they are too wide 2.The numbers of buttons in the scroll area can be changed dynamically 3. Any free space should be used to expand the scroll area as much as possible. If no such space exist navigation buttons should be used for scrolling. With my current implementation when i increase the buttons i have this: But there is free space on the right, so this should look like: If i increase once more to 10 for example, then
  • 如何使用 QHBoxLayout 和 QScrollArea 创建可滚动小部件(How to create a scrollable widget using QHBoxLayout and QScrollArea)
    问题 我正在尝试使用 QHBoxLayout 和 QScrollArea 创建一个可滚动的小部件,但我无法成功创建 GUI,这是我的代码,任何人都可以建议我在哪里需要更改。 任何帮助,将不胜感激 mainLayout = new QHBoxLayout(this); mainLayout->setSizeConstraint(QLayout::SetMaximumSize); QCheckBox *sam_box = new QCheckBox(this); sam_box->setText("HAIIIIIIIIIII"); sam_box->setFixedSize(10000,10000); QCheckBox *so_box = new QCheckBox(this); so_box->setText("HOWWWWWWWWWWWW"); so_box->setFixedSize(150000,15000); mainLayout->addWidget(sam_box); mainLayout->addWidget(so_box); QScrollArea *scrollarea = new QScrollArea(this); scrollarea->setBackgroundRole(QPalette::Shadow); scrollarea->setFixedSize
  • Matplotlib 上的滚动条显示页面(Scrollbar on Matplotlib showing page)
    问题 我想知道是否有plt.show在包含多个子批次( sublot2grid )的 matplotlib 显示页面( plt.show )上放置滚动条(水平或垂直)。 目前,我找到的唯一解决方案是使子图非常小,这根本不是很优雅。 回答1 显示 matplotlib 图的窗口没有添加滚动条的选项。 它会自动将自身调整为图形大小。 相反,如果调整大小,图形也会调整大小。 一种选择是构建一个具有此功能的自定义窗口。 为此,可以使用 PyQt。 下面给出了一个示例,其中不是调用plt.show()而是调用自定义类,将要绘制的图形作为参数。 图形大小应事先设置为图形fig并且该自定义类不会更改它。 相反,它将图形放入带有滚动条的画布中,以便图形保持其原始大小并且可以在 Qt 窗口中滚动。 您不必处理类中的细节,而只需处理脚本末尾的调用。 此示例适用于PyQt4 ,请参阅下面的 PyQt5 示例。 import matplotlib.pyplot as plt from PyQt4 import QtGui from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas from matplotlib.backends.backend_qt4agg import
  • 如何根据 QDialog 使 QScrollArea 改变大小?(How to make QScrollArea change size according to QDialog?)
    问题 我有一个这样的 QDialog: 我在这个 QDialog 中添加了一个 QScrollArea,如下所示: 我想要的是当用户展开 QDialog 时, QScrollArea 也应该随之展开。 我已经尝试了QScrollArea几个属性,比如verticalScrollBarPolicy horizontalScrollBarPolicy 、 sizeAdjustPolicy ,但似乎没有任何效果。 有人可以建议如何做到这一点吗? 回答1 要使对话框调整其子小部件的大小,它必须具有布局。 在对话框上设置布局。 不要更改QScrollArea的任何属性:它们只影响区域本身及其子项,与父小部件(对话框)如何管理滚动区域的geometry()无关。
  • 放大/缩小鼠标点?(Zooming in/out on a mouser point ?)
    问题 如图所示。 我在 QScrollArea 中有 QWidget。 QWidget 充​​当细胞图像和一些基于矢量的轮廓数据的渲染小部件。 用户可以执行放大/缩小,简单地发生的是,它会相应地更改 QPainters 的比例并更改 QWidget 的大小。 现在我想在鼠标下的点上执行放大/缩小。 (如 GIMP 中的缩放操作)。 如何根据缩放级别计算滚动条的新位置? 使用转换而不使用滚动区域来实现这个更好吗? 回答1 一种解决方案可能是从 QScrollArea 派生一个新类并重新实现wheelEvent例如,以便使用鼠标滚轮在当前鼠标光标位置执行缩放。 此方法通过相应地调整滚动条位置以反映新的缩放级别来工作。 这意味着只要没有可见的滚动条,就不会在鼠标光标位置下进行缩放。 这是大多数图像查看器应用程序的行为。 void wheelEvent(QWheelEvent* e) { double OldScale = ... // Get old scale factor double NewScale = ... // Set new scale, use QWheelEvent... QPointF ScrollbarPos = QPointF(horizontalScrollBar()->value(), verticalScrollBar()->value())
  • QScrollArea 内禁用的 QToolButtons 防止滚动(PySide)(Disabled QToolButtons inside QScrollArea prevent scrolling (PySide))
    问题 无论鼠标是否位于禁用的 QToolButton 上方,我都希望能够在 QScrollArea 内使用鼠标滚动。 文档提到禁用的小部件不会将鼠标事件传播给父母,我发现我需要安装事件过滤器来克服我遇到的这个问题。 这是我设法做到的程度。 我认为事件过滤器是在检测到车轮事件时安装的,但我不确定下一步应该是什么: from PySide import QtGui from PySide.QtCore import * import sys app = QtGui.QApplication(sys.argv) wid = QtGui.QWidget() wid.resize(200, 200) scroll = QtGui.QScrollArea() scroll.setWidget(wid) layout = QtGui.QVBoxLayout() wid.setLayout(layout) class installEvent(QObject): def eventFilter(self, i_obj, i_event): if i_event.type() == QEvent.Wheel: print "QEvent: " + str(i_event.type()) buttonEnabled = QtGui.QToolButton() layout.addWidget
  • python Qt:主要小部件滚动条(python Qt: main widget scroll bar)
    问题 我们试图将滚动条放在主窗口小部件上,因此如果用户调整主窗口的大小,滚动条就会出现,并让他上下移动以查看小窗口窗口小部件之外的子窗口小部件,允许其左右移动. 这是带有滚动条的主要小部件的代码.. def centralWDG(self,MainWindow): self.centralwidget = QtGui.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") self.summaryBox = QtGui.QGroupBox("Project Management Layout") self.summaryBox.setMinimumHeight(300) self.summaryBox.setMinimumWidth(500) self.summaryBoxScroll = QtGui.QScrollArea() self.summaryBoxScroll.setFrameStyle(QtGui.QFrame.NoFrame) self.summaryBoxTopLayout = QtGui.QVBoxLayout(self.summaryBox) self.summaryBoxTopLayout.setContentsMargins(1,1,1,1) self
  • react on the resizing of a QMainWindow for adjust widget's size
    How do I react on the resize of a QMainWindow? I have QTextBrowsers in a QScrollArea and I adjust them to the size of the content on creating them (the only thing that should scroll is the QScrollArea). Everything works for now, but if I resize the mainWindow, the height of the QTextBrowsers isn't changed, because the reflow function isn't triggered. Do you have any better idea to adjust a QTextBrowser to it's content? My current code is: void RenderFrame::adjustTextBrowser(QTextBrowser* e) const { e->document()->setTextWidth(e->parentWidget()->width()); e->setMinimumHeight(e->document()->size
  • 在qt窗口中添加滚动条?(add scrollbar in qt window?)
    问题 我一直在从这里的视频教程中学习 qt。 我已经完成了 35 个视频。 所以我想创建一个示例应用程序来理解 qt。 我正在使用最新版本的 qt creator。 我添加了一些按钮并删除了主窗口中的菜单栏和工具栏。 运行后我发现如果我调整窗口滚动条不会出现。 我不希望按钮调整大小或移动。 我对它们变得不可见感到满意,但我想要滚动条,以便用户可以滚动到不可见的部分。 我添加了一个滚动区域小部件,但它不起作用。 我通过在互联网上搜索进行了一些编码,但这也不起作用。 当我将滚动区域的大小增加到窗口大小时; 运行后窗口出现空白。 也许按钮位于滚动区域的“下方”。 我如何更改哪个对象应该在“顶部”? 此外,由于我只是一个初学者,我不知道使用 qt 进行设计的最佳方法是什么。 我应该使用设计器放置所需的小部件然后通过编码给出它们的特征吗? 还是应该使用设计师进行完整的设计? 还是我应该放弃设计师并完成完整的编码? 谢谢你! 编辑@Synxis,这没有多大帮助。 我什至使用了 secentralwidget(ui->scrollareacontentswidget); 我尝试删除 centralwidget QWidget,但我不能。 有什么解决办法吗? 回答1 QWidget 没有滚动条,您需要添加一个带有滚动条的区域。 只需将 QScrollArea 添加到您的窗口,并将所有小部件(按钮等
  • 设置 QScrollBar 与内容对应的滑块大小(Set slider size of QScrollBar correspond with content)
    问题 我正在做一个带有绘图表面的软件,它表示一个绘图(如 sin 函数)(QWidget 的子项),我希望 QScrollBar 像 QScrollArea 一样工作。 因此,如果我的绘图小部件显示显示 750 个点(我的绘图由点组成),但有 1000 个点,我希望 ScrollBar 的滑块填充 75% 的可用空间。 我不能使用 QScrollArea,因为滚动与其包含的小部件的大小成正比。 就我而言,滚动必须与屏幕上的点数成正比。 我知道如何获得我的比率,但我不知道如何正确设置 QScrollBar 示例:我编辑了 PageStep 的值,但我不明白这是如何工作的。 我可以将 pageStep 设置为 100,范围为 [0,99],它将填充 QScrollBar 的一半。 我的界面: QWidget (Vertical Layout) //Main Widget Drawing Surface (Child of QWidget) QScrollBar (Horizontal) 回答1 好吧,我想我可以用这个做点什么: http://harmattan-dev.nokia.com/docs/library/html/qt4/qscrollbar.html 在许多常见情况下,文档长度、滚动条中使用的值范围和页面步骤之间的关系很简单。