Получить абсолютный размер QScrollArea

У меня есть пользовательский виджет, который является дочерним элементом QScrollArea. Мне нужно получить абсолютный размер QScrollArea, независимо от того, отображаются полосы прокрутки или нет.

class MyWidget : public QWidget { /*...*/ };

void
MyWidget::Foo()
{
    auto scrollAreaHeight = parentWidget()->height();
    auto scrollAreaWidth = parentWidget()->width();

    /* height and width change depending on scrollbars 
       being displayed or not */
}

Есть ли способ сделать это?

В качестве альтернативы, если это невозможно через интерфейс QWidget, возвращаемый функцией parentWidget(), есть ли способ получить абсолютный размер QScrollArea из самого QScrollArea?


person Unimportant    schedule 13.03.2019    source источник
comment
Я предполагаю, что parentWidget() возвращает viewport области прокрутки. Следовательно, ширина и высота меняются в зависимости от того, видны ли полосы прокрутки. С parentWidget()->parentWidget()->size() это, вероятно, будет работать лучше. Однако я бы посчитал это решение хрупким, если виджет предполагает наличие определенного родительского виджета. Возможно, вам следует рассмотреть возможность получения виджета напрямую от QAbstractScrollArea, чтобы обойти это.   -  person Scheff's Cat    schedule 13.03.2019


Ответы (1)


Я не совсем понимаю, почему OP не может получить абсолютный размер QScrollArea.

Однако я предполагаю, что в понимании ОП чего-то не хватает. Я подготовил следующий небольшой образец:

QWidget с QVBoxLayout с QScrollArea с QPushButton:

#!/usr/bin/python3

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QScrollArea, QPushButton

app = QApplication(sys.argv)
qWinMain = QWidget()
qVBox = QVBoxLayout()
qScrollArea = QScrollArea()
qBtn = QPushButton("Consume somehow some space\nConsume somehow some space\nConsume somehow some space\n")
qScrollArea.setWidget(qBtn)
qVBox.addWidget(qScrollArea)
qWinMain.setLayout(qVBox)
qWinMain.show()

def onBtnClicked():
  print("Sizes:")
  print("qWinMain:               ", qWinMain.size())
  print("qWinMain.childrenRect():", qWinMain.childrenRect().size())
  print("qScrollArea:            ", qScrollArea.size())
  print("qScrollArea.viewport(): ", qScrollArea.viewport().size())
  print("qBtn:                   ", qBtn.size())

qBtn.clicked.connect(onBtnClicked)
sys.exit(app.exec_())

При нажатии на QPushButton печатаются некоторые размеры виджетов. Он сделал это дважды, один раз, когда полосы прокрутки невидимы, и снова после того, как я изменил размер главного окна, чтобы полосы прокрутки стали видны.

Снимок 1 (с отключенными полосами прокрутки) Снимок 2 (с активированными полосами прокрутки)

Выход:

Sizes:
qWinMain:                PyQt5.QtCore.QSize(225, 100)
qWinMain.childrenRect(): PyQt5.QtCore.QSize(203, 78)
qScrollArea:             PyQt5.QtCore.QSize(203, 78)
qScrollArea.viewport():  PyQt5.QtCore.QSize(201, 76)
qBtn:                    PyQt5.QtCore.QSize(201, 65)
Sizes:
qWinMain:                PyQt5.QtCore.QSize(120, 92)
qWinMain.childrenRect(): PyQt5.QtCore.QSize(98, 70)
qScrollArea:             PyQt5.QtCore.QSize(98, 70)
qScrollArea.viewport():  PyQt5.QtCore.QSize(82, 54)
qBtn:                    PyQt5.QtCore.QSize(201, 65)

Итак, как это читать:

  • qWinMain.size() вернул размер клиентской области qWinMain (без учета оформления окон).
  • qWinMain.childrenRect().size() возвращает размер ограничивающей рамки дочерних элементов qWinMain. Он ровно на 22 пикселя меньше по ширине и высоте, что имеет смысл, поскольку 11 пикселей — это поле по умолчанию для QWidget.
  • qScrollArea.size() вернул точно такой же размер, как qWinMain.childrenRect().size() в обоих случаях, что разумно, поскольку это единственный дочерний элемент.
  • qScrollArea.viewport().size() возвращает размер области просмотра QScrollArea, размер которого зависит от того, видны полосы прокрутки или нет. Без полос прокрутки разница с qScrollArea составляет всего 2 пикселя по ширине и высоте, но с полосами прокрутки она соответственно больше.
  • qBtn.size() возвращает размер кнопки, который не зависит от ее визуальных/обрезанных областей и, следовательно, в обоих случаях одинаков.

Итак, что бы OP ни имел в виду под «абсолютным размером QScrollArea», один из них должен быть OP, который ищет.

person Scheff's Cat    schedule 13.03.2019
comment
@Unimportant Извините, что я сделал это в PyQt. На самом деле C++ — мой родной язык. Однако, 1-е) вы не отметили ни одного языка 2-е) код Python еще короче 3-е) принцип не меняется в C++. - person Scheff's Cat; 13.03.2019
comment
Спасибо, мне нужно время, чтобы разобраться с этим. - person Unimportant; 14.03.2019
comment
Вы правы, QScrollArea::width() и QScrollArea::height() возвращают абсолютный размер области прокрутки, а вызов parentWidget()->width() и parentWidget()->height() из дочернего виджета области прокрутки возвращает размер области просмотра области прокрутки. Это послало меня на дикую гусиную погоню. - person Unimportant; 14.03.2019