Инструменты пользователя

Инструменты сайта


products:pussy:other:dev_propertycontainer_gui

Различия

Показаны различия между двумя версиями страницы.

Ссылка на это сравнение

Предыдущая версия справа и слеваПредыдущая версия
Следующая версия
Предыдущая версия
products:pussy:other:dev_propertycontainer_gui [2023/12/09 17:50] – А вот ironmeshproducts:pussy:other:dev_propertycontainer_gui [2023/12/13 14:54] (текущий) – внешнее изменение 127.0.0.1
Строка 1: Строка 1:
 ====== Разработка интерфейса для Контейнера Свойств ====== ====== Разработка интерфейса для Контейнера Свойств ======
  
-FIXME 
  
-В данном уроке я расскажу как разработать альтернативный интерфейс для Контейнера свойств, по умолчанию он генерирует интерфейс единым списком без группировки, если свойств немного, то этого будет вполне достаточно, но если их десятки или даже больше сотни, то таким интерфейсом будет пользоваться не слишком удобно, также может возникнуть желание добавить дополнительные функции, например, сортировка или фильтр и т.п.  Ниже показана предопределенная форма+В данном уроке я расскажу как разработать альтернативный интерфейс для [[:products:pussy:concepts:propertycontainer|Контейнера свойств]], по умолчанию он генерирует интерфейс единым списком без группировки по разделам и прочего, если свойств немного, то этого будет вполне достаточно, но если их десятки или даже сотни, то таким интерфейсом будет пользоваться не слишком удобно, также может возникнуть желание добавить дополнительные функции, например, сортировкафильтр и т.п. Ниже показана предопределенная форма вывода свойств
  
 {{  :products:pussy:screenshots:2023-09-17_14_14_34-configurate_plugin_properties_demo.jpg?400  |Дефолтный интерфейс Контейнера свойств}}Подробнее о концепции свойств читайте [[:products:pussy:concepts:propertycontainer|здесь]]. {{  :products:pussy:screenshots:2023-09-17_14_14_34-configurate_plugin_properties_demo.jpg?400  |Дефолтный интерфейс Контейнера свойств}}Подробнее о концепции свойств читайте [[:products:pussy:concepts:propertycontainer|здесь]].
Строка 37: Строка 36:
 </code> </code>
  
-===== искусственный разграничитель ===== 
  
 заметьте, что после определения класса метод //generate_properties()// нужно вызвать, чтобы свойства были созданы. Теперь, можно посмотреть как будет выглядеть дефолтная форма с сгенерированными свойствами заметьте, что после определения класса метод //generate_properties()// нужно вызвать, чтобы свойства были созданы. Теперь, можно посмотреть как будет выглядеть дефолтная форма с сгенерированными свойствами
  
-{{  :products:pussy:screenshots:lessons:def_propcontainer_gui_1.jpg?200  |def_propcontainer_gui_1.jpg}}выглядит она не очень презентабельно, тут собрано порядка 500 свойств, пользователю было бы непросто здесь разобраться. Напомню, что имя свойства определяет, на какую страницу оно попадет, то есть свойства с префиксом "s1" попадают на первую страницу, с "s2" на вторую и так далее. У [[:products:pussy:api:pyub:types:propertycontainer|]] за вывод интерфейса отвечает метод //[[http://wiki.mig-ironmesh.ru/products;pussy;api;pyub;types;propertycontainer#render_layout|render_layout()]]// , а метод //[[http://wiki.mig-ironmesh.ru/products;pussy;api;pyub;types;propertycontainer#retranslate|retranslate()]] // отвечает за перевод отображаемой информации, Менеджер автоматически вызывает данные методы, поэтому //retranslate() // не нужно вызывать в коде. Если перевод не нужен, то заполнение интерефейса можно произвести в методе //render_layout(), // а в методе //retranslate() // вписать ключевое слов//о pass//.+{{  :products:pussy:screenshots:lessons:def_propcontainer_gui_1.jpg?200  |def_propcontainer_gui_1.jpg}}выглядит она не очень презентабельно, тут собрано порядка 500 свойств, на практике с этим было бы трудно работать.
  
-Итак, в итоге у меня получился следующий код для методов// render_layout() // и// ////retranslate()//+Напомнючто в новом интерфейсе имя свойства определяет, на какую страницу оно попадет, то есть свойства с префиксом "s1" попадают на первую страницу, с "s2" на вторую и так далее. У [[:products:pussy:api:pyub:types:propertycontainer|]] за вывод интерфейса отвечает метод //[[http://wiki.mig-ironmesh.ru/products;pussy;api;pyub;types;propertycontainer#render_layout|render_layout()]]// , а метод //[[http://wiki.mig-ironmesh.ru/products;pussy;api;pyub;types;propertycontainer#retranslate|retranslate()]] // отвечает за перевод отображаемой информации, Менеджер автоматически вызывает данные методы, поэтому //retranslate() // не нужно вызывать в коде, как это делается в Свойствах. Если перевод не нужен, то заполнение интерефейса можно произвести в методе //render_layout(), // а в методе //retranslate() // вписать ключевое слов//о pass//.
  
-//(вставить сюда код FIXME)//+Итак, в итоге у меня получился следующий код для методов// render_layout() // и// retranslate()//
  
-А вот так выглядит новый интерфейс, уже намного лучше. Это только один из вариант группировки свойств по разделам, токже можно для таких целей использовать виджеты: QTabWidget, QStackedWidget совместно с виджетом для выбора элементов, например, QListWidget, QComboBox и другие.{{  :products:pussy:screenshots:lessons:def_propcontainer_gui_2.jpg?200  }}Ну, вот и все, урок по разработке альтернативного интерфейса для контейнера свойств  подошел к концу, как вы могли убедиться это очень простой процесс, который не займет много времени и сил, но перед использованием не забывайте тестировать свой код. Если что-то не понятно, то можно задать вопрос в [[http://discord.gg/JD5yKPrKCk|Discord]].+ 
 +<code python> 
 +@classmethod 
 +    def render_layout(cls) -> QToolBox: 
 +        cls._lable_list = {} 
 +        cls._tool_box = QToolBox() 
 + 
 +        def render_page(suffix:str) ->QScrollArea: 
 +            scroll_area = QScrollArea() 
 +            scroll_area.setWidgetResizable(True) 
 +            widget_content = QWidget() 
 +            layout = QFormLayout(widget_content) 
 +            layout.setVerticalSpacing(15) 
 +            layout.setLabelAlignment(Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter) 
 +            row: int = 0 
 +            for key, prop in cls.__annotations__.items(): 
 +                if not key.endswith(suffix): continue 
 +                cls._lable_list[key] = QLabel() 
 +                cls._lable_list[key].setWordWrap(True) 
 +                layout.setWidget(row, QFormLayout.LabelRole, cls._lable_list[key]) 
 +                layout.setWidget(row, QFormLayout.FieldRole, prop.get_input_widget()) 
 +                row += 1 
 +            scroll_area.setWidget(widget_content) 
 +            return scroll_area 
 + 
 +        for i in range(1, 6): 
 +            cls._tool_box.addItem(render_page(f"s{i}"), ""
 + 
 +        return cls._tool_box 
 + 
 +    @classmethod 
 +    def retranslate(cls) -> None: 
 +        for key, label in cls._lable_list.items(): 
 +            label.setText(cls.get_property(key).get_name()) 
 +            cls.__annotations__[key].retranslate() 
 + 
 +        for i in range(cls._tool_box.count()): 
 +            cls._tool_box.setItemText(i, QCoreApplication.translate("properties", f"Section {i+1}")) 
 +</code> 
 + 
 +А вот так выглядит новый интерфейс, уже намного лучше. Это только один из вариант группировки свойств по разделам, также можно для таких целей использовать виджеты: [[:products:pussy:other:qtabwidget|QTabWidget]][[:products:pussy:other:qstackedwidget|QStackedWidget]] совместно с виджетом для выбора элементов, например, [[:products:pussy:other:qlistwidget|QListWidget]][[:products:pussy:other:qcombobox|QComboBox]] и другие.{{  :products:pussy:screenshots:lessons:def_propcontainer_gui_2.jpg?200  |def_propcontainer_gui_2.jpg}}Теперь, попробую объяснить код, который я написал, начну с метода// render_layout()//, в самом начале определяем словарь //_lable_list//, в котором будут содержаться все подписи для свойств, которые представляют из себя экземпляры виджета QLableа в переменной //_tool_box // будет находиться экземпляр [[:products:pussy:other:qtoolbox|QToolBox]], обе эти переменные сохраняются в классе, чтобы был к ним доступ из других методов. Затем я ввел вспомогательную вложенную функцию //render_page()//, которая отбирает свойства, имена которых имеют указанный суффикс и упаковывает их в форму ([[:products:pussy:other:qformlayout|QFormLayout]]) внутри виджета, который в свою очередь вложен в область ([[:products:pussy:other:qscrollarea|QScrollArea]]), затем функция возвращает сформированный интерфейс; в цикле //for // производится обход всех Свойств, которые хранятся в словаре //_ _annotations_ _//, имена свойств, которые не имеют нужный суффикс игнорируются, а те что соответствуют, у них берется виджет для ввода методом //get_input_widget()//, затем он добавляется в форму layout([[:products:pussy:other:qformlayout|QFormLayout]]) в правый столбец (роль //[[:products:pussy:other:qformlayout|QFormLayout]].[[:products:pussy:other:fieldrole|FieldRole]]), // а подписи для свойств (экземпляры QLable) помещаются в левый столбец (роль //[[:products:pussy:other:qformlayout|QFormLayout]].[[:products:pussy:other:labelrole|LabelRole]]//). Заметьте, что для подписей Свойств текст не устанавливается, это будет сделано позднее. В конце производится добавление страниц в //_tool_box//, для этого вызыватся метод //addItem()//, которому передается результат функции //render_page(), // которой передаются строки с суффиксами, определенные нами ранее. 
 + 
 +В методе //retranslate() // выполняется перевод отображаемой информации, а именно: подписи разделов для //_tool_box//, подписей Свойств и самих Свойств. Для перевода подписей свойств мы обходим все элементы в //_lable_list // и устанавливаем текст, которые вернет метод свойства //get_name()//, заметьте, что в качестве ключей использованы имена свойств в контейнере; также у каждого свойства вызывается метод //retranslate()//, чтобы перевести отображаемую информацию; в конце производится обход всех элементов в //_tool_box// и устанавливает их текст на предопределенный, для поиска перевода используется команда //[[:products:pussy:other:qcoreapplication|QCoreApplication]].translate(<контекст>, <текст>).// 
 + 
 +Подытожу все вышесказанное. Для того чтобы определить свой вариант интерефейса нужно переопределить всего 2 метода:// render_layout() // и// retranslate()//, первый метод должен вернуть виджет с сгенерированным интерфесом, а второй выполнить перевод отображаемой информации. Элементы для интерефейса мы извлекаем из самих свойст, вызовом метода //get_input_widget(), // а текст с именем свойства нам вернет метод //get_name()//; сами свойства хранятся в классе, в поле //_ _annotations_ _,  // которое представляет из себя обычный словар, где ключ - идентификатор свойства, а значение - ссылка на само свойство. 
 + 
 +Ну, вот и все, урок по разработке альтернативного интерфейса для Контейнера свойств подошел к концу, как вы могли убедиться это очень простой процесс, который не займет много времени и сил, при наличии опыта разработки интерфейсов, если опыта мало, то можно сверстать его в [[:products:pussy:other:qtdesigner|QtDesigner]], а затем посмотреть как устроен код и перенести его в свой проект с некоторыми изменениями или импортировать его целиков. Кстати, перед использованием не забывайте тестировать свой код. Если что-то не понятно, то можно задать вопрос в [[http://discord.gg/JD5yKPrKCk|Discord]].
  
  
products/pussy/other/dev_propertycontainer_gui.1702133448.txt.gz · Последнее изменение: (внешнее изменение)