В Qt есть 3 класса, которые взаимодействуют друг с другом: Style, Option и Widgets. Когда виджет готовится к отрисовке, он передается в Option. Опция — это, по сути, состояние виджета. Затем этот параметр передается в стиль, который будет использовать эти параметры/переменную из параметра для его отображения на экране.
Мой вопрос: какой цели служит этот вариант? Почему стиль не принимает виджет в качестве параметра для рисования и не извлекает атрибуты напрямую, он делает это для параметра? Кажется, что все, что делает Option, можно переместить в Style и сохранить создание этого класса-контейнера. Кроме того, почему это называется «опцией», я считаю, что это название очень вводит в заблуждение, поскольку опции обычно относятся к серии вариантов, не имеющих ничего общего с объектом передачи данных.





Хотя основная цель классов QStyleOption — использовать их, когда необходимо отрисовать виджет, их полезность гораздо шире и не ограничивается этим.
Частично это объясняется в документации Style and Style Aware Widgets:
Благодаря QStyleOption можно создавать виджеты QStyle для рисования без привязки какого-либо кода к виджету. Это позволяет использовать функции рисования QStyle на любом устройстве рисования, т. е. вы можете рисовать поле со списком на любом виджете, а не только на QComboBox.
Это означает, что мы можем виртуально нарисовать любой стандартный виджет Qt, даже в базовом QWidget. В том числе рисование несуществующего виджета на растровом изображении.
Интересно, что то же самое делают некоторые виджеты и стили. Например, QStyleOptionFrame обычно используется классами QFrame для рисования границ (и, возможно, фона), но эта опция также используется QLineEdit, который не наследуется от QFrame, для рисования «врезной границы» своего поля.
Например, представление элемента может просто отображать (рисовать) поле со списком и создавать настоящее только тогда, когда требуется взаимодействие с пользователем, что явно лучше, чем создание сотен или тысяч виджетов, даже если одновременно всегда будет использоваться только один. время.
Некоторые стили используют одну и ту же функцию для рисования индикатора QCheckBox и проверяемого элемента в представлении модели, но с разными классами QStyleOption. Это было бы невозможно, если бы стиль мог рисовать объекты только путем запроса виджета и требовал бы отдельных функций и параметров.
Параметр стиля также обеспечивает уровень абстракции между виджетом и стилем, поэтому стилю не нужно постоянно запрашивать виджет для какой-либо из его внутренних функций: как только параметр инициализируется (возможно, виджетом), все уже установлен на более простом объекте, который также имеет более быстрый доступ к своим членам из соображений производительности[1].
Более того, как объяснялось выше, по практическим соображениям опцию можно использовать для другого виджета. Если бы QStyleOptions не существовало, стилю пришлось бы запрашивать виджет, возможно, различаясь в зависимости от типа, и все это путем вызова функций виджета. Параметр стиля упрощает задачу, поскольку стиль уже содержит все необходимое в отдельном, более простом объекте, к которому легче получить доступ и который гораздо более гибок.
Фактически, экземпляр параметра стиля также можно повторно использовать или легко скопировать, так что снова нет необходимости постоянно запрашивать виджет (возможно, для того же результата). Представления элементов Qt обычно создают только один QStyleOptionViewItem, когда начинается рисование, и обновляют его только при необходимости, а затем, наконец, отбрасывают его, когда рисование заканчивается.
Некоторые стили часто внутри себя создают копии (прямые или производные) полученного параметра стиля, чтобы выполнять сложные вызовы функций или правильную композицию при рисовании.
Простота QStyleOptions также полезна для некоторых сложных виджетов (например, счетчиков): с помощью простого вызова функции initStyleOption() устанавливаются все текущие состояния виджетов, и стилю нужно будет только проверить, что для него важно. Опять же, если бы QStyleOptions не существовало, стиль должен был бы каждый раз выполнять отдельные (и дорогостоящие) вызовы функций.
Другим важным аспектом является то, что виджеты могут использовать QStyleOptions для запроса стиля об аспектах, которые могут не быть отражены текущим состоянием виджета. Типичным случаем является sizeFromContents(), который может привести к изменению состояния/размера виджета в зависимости от возможного состояния (например, пустого в данный момент QComboBox). Это было бы непросто без промежуточного объекта абстракции.
Наконец, аспект именования тривиален. Хотя я могу согласиться, что термин «опция» может вводить в заблуждение, он, вероятно, возник в более ранних версиях Qt[2], когда QStyleOptions был необязательным аргументом и содержал определенные параметры для виджета, которые стиль мог использовать (или игнорировать). Это имя осталось (вероятно, для обратной совместимости), хотя «опция» теперь обязательна почти для всех функций QStyle.
[1] When using Python, the only difference in accessing "values" of a QObject or QStyleOption is that the former is normally done with getter and setter functions (which need to be called), while style option attributes are direct, similarly to object attributes; in C++ the difference is that style option members are accessed using . (as in Python) or the -> operator, which provides better performance for things that need to respond fast as things like painting or layout management require.
[2] see the archives: "Some QStyle functions take an optional argument specifying extra information that is required for a paritical primitive or control. So that the QStyle class can be extended, QStyleOption is used to provide a variable-argument for these options." (emphasis mine).
Верно, значит, это не какой-то популярный «шаблон проектирования», а адаптированный под конкретную Qt?
@ memelord23 Я не знаю, существуют ли для этого известные шаблоны проектирования, и в целом они меня не особо волнуют. Хотя они, безусловно, полезны и в некоторой степени необходимы для определения некоторых типичных и четко определенных случаев, я часто считаю необходимость найти/определить шаблон бессмысленной, как иногда бывает и принудительно следовать конкретным шаблонам. Некоторые программы или аспекты программы/библиотеки могут следовать известному шаблону, некоторые нет, другие могут использовать вариации или смеси. Шаблоны проектирования — это всего лишь возможные формы и рекомендации. Если это работает и имеет смысл, не имеет значения, что у него нет известного определения.
Я голосую за возобновление этого вопроса, так как чувствую, что на него можно ответить, предоставив надлежащие факты/цитаты, объясняющие цель упомянутого объекта (что, по моему мнению, я и сделал).