├── LICENSE ├── README.md ├── examples ├── animated_horizontal_basic.py └── flet_carousel_basic.py ├── pyproject.toml ├── screenshot1.png ├── screenshot2.png ├── setup.py └── src └── fletcarousel ├── __init__.py ├── attributes.py ├── fletcarousel.py └── horizontal.py /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Mohammadreza Naderi 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 6 | copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 7 | 8 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 9 | 10 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Flet simple carousel sliders 2 | 3 | This project is a carousel sliders pack with different types for the Flet framework. This project is under development, so in 4 | the future, different types of sliders will be added to the project. 5 | 6 | # Installation 7 | 8 | ````shell 9 | pip install fletcarousel 10 | ```` 11 | or 12 | ````shell 13 | git clone https://github.com/naderidev/flet-carousel 14 | ```` 15 | 16 | # How to use 17 | 18 | There are some types of sliders, so in the following, we will explain each type of them. 19 | 20 | ### BasicHorizontalCarousel 21 | 22 | This type of slider is the basic one. This type is horizontal and there are two buttons to control slides. 23 | 24 | ![Screenshot of the app](https://raw.githubusercontent.com/naderidev/flet-carousel/master/screenshot1.png "Screenshot") 25 | 26 | for example: 27 | 28 | ````python 29 | BasicHorizontalCarousel( 30 | page=page, 31 | items_count=3, 32 | # auto_cycle=AutoCycle(duration=1), 33 | items=[ 34 | Container( 35 | content=Text(value=str(i), size=20), 36 | height=200, 37 | width=300, 38 | bgcolor='red', 39 | border_radius=15, 40 | alignment=alignment.center, 41 | ) for i in range(10) 42 | ], 43 | buttons=[ 44 | FloatingActionButton( 45 | icon=icons.NAVIGATE_BEFORE, 46 | bgcolor='#1f2127' 47 | ), 48 | FloatingActionButton( 49 | icon=icons.NAVIGATE_NEXT, 50 | bgcolor='#1f2127' 51 | ) 52 | ], 53 | vertical_alignment=CrossAxisAlignment.CENTER, 54 | items_alignment=MainAxisAlignment.CENTER 55 | ) 56 | ```` 57 | 58 | ### Properties 59 | 60 | ``page`` 61 | 62 | the main page 63 | 64 | #### Container properties 65 | 66 | 1. ``width`` : slider width 67 | 68 | 2. ``height`` :slider height 69 | 70 | 3. ``expand`` : filling available space 71 | 72 | 4. ``tooltip`` : tooltip 73 | 74 | 5. ``disabled`` : disabled 75 | 76 | 6. ``padding`` : padding 77 | 78 | 7. ``margin`` : margin 79 | 80 | 8. ``alignment`` : alignment 81 | 82 | 9. ``bgcolor`` : background color 83 | 84 | 10. ``gradient`` : gradient 85 | 86 | 11. ``border`` : border 87 | 88 | 12. ``border_radius`` : border_radius 89 | 90 | #### Slider properties 91 | 92 | 1. ``items`` : the items that you want to be in slide show 93 | 94 | 2. ``items_count`` : the count of controls in each slide 95 | 96 | 3. ``vertical_alignment`` : items vertical_alignment 97 | 98 | 4. ``items_alignment`` : items alignment 99 | 100 | 5. ``spacing`` : spacing between items 101 | 102 | 6. ``auto_cycle`` : auto cycleing (Auto changing slides) 103 | 104 | 7. ``buttons`` : the list of Slider's buttons that must be two buttons! the first one is the "previous" button and the second is the "next" button 105 | 106 | #### Methods 107 | 108 | 1. ``next`` : next slide 109 | 110 | 2. ``prev`` : previous slide 111 | 112 | 3. ``update_items`` : updating items 113 | 114 | 4. ``reset_items_index`` : reseting items index 115 | 116 | check out the file ``examples/flet_carousel_basic.py`` 117 | 118 | 119 | ### BasicAnimatedHorizontalCarousel 120 | 121 | This type of slider works with AnimatedSwitcher and unlike "BasicHorizontalCarousel" has no next and prev button but has hint lines. 122 | 123 | ![Screenshot of the app](https://raw.githubusercontent.com/naderidev/flet-carousel/master/screenshot2.png "Screenshot") 124 | 125 | for example: 126 | 127 | ````python 128 | BasicAnimatedHorizontalCarousel( 129 | page=page, 130 | auto_cycle=AutoCycle(duration=2), 131 | expand=True, 132 | padding=50, 133 | hint_lines=HintLine( 134 | active_color='red', 135 | inactive_color='white', 136 | alignment=MainAxisAlignment.CENTER, 137 | max_list_size=400 138 | ), 139 | items=[ 140 | Container( 141 | content=Text(value=str(i), size=30), 142 | height=400, 143 | expand=True, 144 | bgcolor='red', 145 | border_radius=15, 146 | alignment=alignment.center, 147 | ) for i in range(10) 148 | ], 149 | ) 150 | ```` 151 | 152 | ### Properties 153 | 154 | ``page`` 155 | 156 | the main page 157 | 158 | #### Container properties 159 | 160 | 1. ``width`` : slider width 161 | 162 | 2. ``height`` :slider height 163 | 164 | 3. ``expand`` : filling available space 165 | 166 | 4. ``tooltip`` : tooltip 167 | 168 | 5. ``disabled`` : disabled 169 | 170 | 6. ``padding`` : padding 171 | 172 | 7. ``margin`` : margin 173 | 174 | 8. ``alignment`` : alignment 175 | 176 | 9. ``bgcolor`` : background color 177 | 178 | 10. ``gradient`` : gradient 179 | 180 | 11. ``border`` : border 181 | 182 | 12. ``border_radius`` : border_radius 183 | 184 | #### Slider properties 185 | 186 | 1. ``items`` : the items that you want to be in slider 187 | 188 | 2. ``hint_lines`` : hint lines settings 189 | 190 | 3. ``animated_switcher`` : The AnimatedSwitcher settings 191 | 192 | 4. ``auto_cycle`` : auto cycleing (Auto changing slides) 193 | 194 | #### Methods 195 | 196 | 1. ``next`` : next slide 197 | 198 | 2. ``prev`` : previous slide 199 | 200 | 3. ``update_items`` : updating items 201 | 202 | 4. ``go`` : go to a specific slide 203 | 204 | check out the file ``examples/animated_horizontal_basic.py`` 205 | 206 | Hope to enjoy :) 207 | 208 | # Donating 209 | - [buy me a coffee](https://www.buymeacoffee.com/mohammadrezaN) 210 | -------------------------------------------------------------------------------- /examples/animated_horizontal_basic.py: -------------------------------------------------------------------------------- 1 | from flet import * 2 | from fletcarousel import BasicAnimatedHorizontalCarousel, HintLine, AutoCycle 3 | 4 | 5 | def main(page: Page): 6 | page.theme_mode = ThemeMode.DARK 7 | page.rtl = True 8 | carousel = BasicAnimatedHorizontalCarousel( 9 | page=page, 10 | auto_cycle=AutoCycle(duration=2), 11 | expand=True, 12 | padding=50, 13 | hint_lines=HintLine( 14 | active_color='red', 15 | inactive_color='white', 16 | alignment=MainAxisAlignment.CENTER, 17 | max_list_size=400 18 | ), 19 | items=[ 20 | Container( 21 | content=Text(value=str(i), size=30), 22 | height=400, 23 | expand=True, 24 | bgcolor='red', 25 | border_radius=15, 26 | alignment=alignment.center, 27 | ) for i in range(10) 28 | ], 29 | ) 30 | page.add(carousel) 31 | 32 | 33 | app(target=main) 34 | -------------------------------------------------------------------------------- /examples/flet_carousel_basic.py: -------------------------------------------------------------------------------- 1 | from flet import * 2 | 3 | from fletcarousel import BasicHorizontalCarousel 4 | 5 | 6 | def main(page: Page): 7 | page.theme_mode = ThemeMode.DARK 8 | page.rtl = True 9 | page.vertical_alignment = 'center' 10 | page.horizontal_alignment = 'center' 11 | carousel = BasicHorizontalCarousel( 12 | page=page, 13 | items_count=3, 14 | # auto_cycle=AutoCycle(duration=1), 15 | items=[ 16 | Container( 17 | content=Text(value=str(i), size=20), 18 | height=200, 19 | width=300, 20 | bgcolor='red', 21 | border_radius=15, 22 | alignment=alignment.center, 23 | ) for i in range(10) 24 | ], 25 | buttons=[ 26 | FloatingActionButton( 27 | icon=icons.NAVIGATE_BEFORE, 28 | bgcolor='#1f2127' 29 | ), 30 | FloatingActionButton( 31 | icon=icons.NAVIGATE_NEXT, 32 | bgcolor='#1f2127' 33 | ) 34 | ], 35 | vertical_alignment=CrossAxisAlignment.CENTER, 36 | items_alignment=MainAxisAlignment.CENTER 37 | ) 38 | page.add(carousel) 39 | 40 | 41 | app(target=main) 42 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ['setuptools>=42'] 3 | build-backend = 'setuptools.build_meta' -------------------------------------------------------------------------------- /screenshot1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naderidev/flet-carousel/efac54f41b53c0ea4bb08f87851d2ab813ae96f8/screenshot1.png -------------------------------------------------------------------------------- /screenshot2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naderidev/flet-carousel/efac54f41b53c0ea4bb08f87851d2ab813ae96f8/screenshot2.png -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import setuptools 2 | 3 | with open('README.md', 'r', encoding='utf-8') as f: 4 | long_description = f.read() 5 | 6 | setuptools.setup( 7 | name='fletcarousel', 8 | version='0.0.14', 9 | license='LICENSE', 10 | author='naderidev', 11 | author_email='mohammadrezanaderi84@gmail.com', 12 | description='Simple carousel sliders for flet framework', 13 | keywords=['flet', 'carousel', 'slideshow', 'slider', 'python', 'flet-carousel', 'fletcarousel'], 14 | long_description=long_description, 15 | long_description_content_type='text/markdown', 16 | url='https://github.com/naderidev/flet-carousel', 17 | package_dir={'': 'src'}, 18 | packages=setuptools.find_packages(where='src'), 19 | classifiers=[ 20 | 'Development Status :: 4 - Beta', 21 | 'Intended Audience :: Developers', 22 | 'Topic :: Software Development :: Libraries :: Python Modules', 23 | 'Programming Language :: Python :: 3.10', 24 | 'License :: OSI Approved :: MIT License', 25 | ], 26 | python_requires='>=3.9', 27 | include_package_data=True, 28 | ) 29 | -------------------------------------------------------------------------------- /src/fletcarousel/__init__.py: -------------------------------------------------------------------------------- 1 | from .horizontal import ( 2 | BasicAnimatedHorizontalCarousel, 3 | BasicHorizontalCarousel, 4 | ) 5 | from .attributes import ( 6 | AutoCycle, 7 | HintLine 8 | ) 9 | -------------------------------------------------------------------------------- /src/fletcarousel/attributes.py: -------------------------------------------------------------------------------- 1 | from flet import MainAxisAlignment 2 | from typing import Optional 3 | from pydantic import BaseModel 4 | 5 | class AutoCycle: 6 | duration: int 7 | 8 | def __init__(self, duration: int = 1): 9 | self.duration = duration 10 | 11 | 12 | class HintLine(BaseModel): 13 | active_color: Optional[str] 14 | inactive_color: Optional[str] 15 | alignment: Optional[MainAxisAlignment] 16 | max_list_size: Optional[int] 17 | -------------------------------------------------------------------------------- /src/fletcarousel/fletcarousel.py: -------------------------------------------------------------------------------- 1 | import threading 2 | from typing import Union, Optional 3 | from flet import ( 4 | ClipBehavior, 5 | Border, 6 | Control, 7 | Page, 8 | Alignment, 9 | Container 10 | ) 11 | from flet_core.gradients import Gradient 12 | from flet_core.types import ( 13 | PaddingValue, 14 | MarginValue, 15 | BorderRadiusValue, 16 | ) 17 | 18 | 19 | class FletCarousel(Container): 20 | def __init__( 21 | self, 22 | page: Page, 23 | width: int = None, 24 | height: int = None, 25 | expand: Union[None, bool, int] = None, 26 | tooltip: Optional[str] = None, 27 | visible: Optional[bool] = None, 28 | disabled: Optional[bool] = None, 29 | padding: PaddingValue = None, 30 | margin: MarginValue = None, 31 | alignment: Optional[Alignment] = None, 32 | bgcolor: Optional[str] = None, 33 | gradient: Optional[Gradient] = None, 34 | border: Optional[Border] = None, 35 | border_radius: BorderRadiusValue = None, 36 | ): 37 | super().__init__() 38 | self.page = page 39 | self.width = width 40 | self.height = height 41 | self.expand = expand 42 | self.tooltip = tooltip 43 | self.visible = visible 44 | self.disabled = disabled 45 | self.padding = padding 46 | self.margin = margin 47 | self.alignment = alignment 48 | self.bgcolor = bgcolor 49 | self.gradient = gradient 50 | self.border = border 51 | self.border_radius = border_radius 52 | self.clip_behavior = (ClipBehavior.HARD_EDGE,) 53 | 54 | def build(self): 55 | self.content = self.render() 56 | threading.Thread(target=self.init_state).start() 57 | 58 | def render(self) -> Control: 59 | return Control() 60 | 61 | def init_state(self): 62 | pass 63 | -------------------------------------------------------------------------------- /src/fletcarousel/horizontal.py: -------------------------------------------------------------------------------- 1 | import time 2 | from typing import Union, Optional 3 | from flet import ( 4 | Border, 5 | Control, 6 | Page, 7 | CrossAxisAlignment, 8 | MainAxisAlignment, 9 | TextButton, 10 | FloatingActionButton, 11 | IconButton, 12 | Alignment, 13 | Row, 14 | AnimatedSwitcherTransition, 15 | AnimationCurve, 16 | AnimatedSwitcher, 17 | Container, 18 | Column 19 | ) 20 | from flet_core.gradients import Gradient 21 | from flet_core.types import ( 22 | PaddingValue, 23 | MarginValue, 24 | BorderRadiusValue, 25 | ) 26 | from .fletcarousel import FletCarousel 27 | from .attributes import AutoCycle, HintLine 28 | 29 | 30 | class BasicHorizontalCarousel(FletCarousel): 31 | current_items: tuple = 0, 0 32 | _auto_cycle_status: int = 1 # 1:play 0:pause -1:stop 33 | 34 | def __init__( 35 | self, 36 | page: Page, 37 | items: Optional[list[Control]] = None, 38 | items_count: Optional[int] = 1, 39 | vertical_alignment: CrossAxisAlignment = CrossAxisAlignment.CENTER, 40 | items_alignment: MainAxisAlignment = None, 41 | spacing: int = None, 42 | width: int = None, 43 | height: int = None, 44 | expand: Union[None, bool, int] = None, 45 | tooltip: Optional[str] = None, 46 | visible: Optional[bool] = None, 47 | disabled: Optional[bool] = None, 48 | padding: PaddingValue = None, 49 | margin: MarginValue = None, 50 | alignment: Optional[Alignment] = None, 51 | bgcolor: Optional[str] = None, 52 | gradient: Optional[Gradient] = None, 53 | border: Optional[Border] = None, 54 | border_radius: BorderRadiusValue = None, 55 | auto_cycle: AutoCycle = None, 56 | buttons: Optional[list[TextButton | 57 | IconButton | FloatingActionButton]] = None, 58 | ): 59 | FletCarousel.__init__( 60 | self, 61 | page=page, 62 | width=width, 63 | height=height, 64 | expand=expand, 65 | tooltip=tooltip, 66 | visible=visible, 67 | disabled=disabled, 68 | padding=padding, 69 | margin=margin, 70 | alignment=alignment, 71 | bgcolor=bgcolor, 72 | gradient=gradient, 73 | border=border, 74 | border_radius=border_radius, 75 | ) 76 | 77 | self.items = items 78 | self.items_count = items_count 79 | self.vertical_alignment = vertical_alignment 80 | self.items_alignment = items_alignment 81 | self.spacing = spacing 82 | self.auto_cycle = auto_cycle 83 | self.buttons = buttons 84 | 85 | if len(items) > 0: 86 | self.current_items = (0, self.items_count) 87 | 88 | self.__update_buttons() 89 | 90 | def render(self) -> Row: 91 | 92 | self.__carousel = Row( 93 | controls=self.__controls(self.items), 94 | expand=True, 95 | alignment=MainAxisAlignment.SPACE_AROUND 96 | ) 97 | 98 | return self.__carousel 99 | 100 | def __controls(self, items: Optional[list[Control]] = None): 101 | 102 | self.__item_list = Row( 103 | controls=[] if len(items) == 0 else ( 104 | items[0:self.items_count] if len( 105 | items) >= self.items_count else items 106 | ), 107 | vertical_alignment=self.vertical_alignment, 108 | spacing=self.spacing, 109 | alignment=self.items_alignment, 110 | ) 111 | 112 | c = [self.__item_list] 113 | 114 | if not self.buttons: 115 | return c 116 | 117 | c.insert(0, self.buttons[0]) 118 | 119 | if len(self.buttons) >= 2: 120 | c.append(self.buttons[1]) 121 | 122 | return c 123 | 124 | def next(self, e=None): 125 | if self.__item_list.controls and self.current_items[1] < len(self.items): 126 | self.current_items = self.current_items[0] + \ 127 | 1, self.current_items[1] + 1 128 | self.__item_list.controls = self.items[self.current_items[0]:self.current_items[1]] 129 | self.page.update(self.__item_list) 130 | 131 | def prev(self, e=None): 132 | if self.__item_list.controls and self.current_items[0] > 0: 133 | self.current_items = self.current_items[0] - \ 134 | 1, self.current_items[1] - 1 135 | self.__item_list.controls = self.items[self.current_items[0]:self.current_items[1]] 136 | self.page.update(self.__item_list) 137 | 138 | def pause(self): 139 | self._auto_cycle_status = 0 140 | 141 | def play(self): 142 | self._auto_cycle_status = 1 143 | 144 | def stop(self): 145 | self._auto_cycle_status = -1 146 | 147 | def __update_buttons(self): 148 | if self.buttons: 149 | self.buttons[0].on_click = self.prev 150 | 151 | if len(self.buttons) >= 2: 152 | self.buttons[1].on_click = self.next 153 | 154 | def update_items(self, new_items: Optional[list[Control]] = None): 155 | self.items = new_items 156 | if len(new_items) > 0: 157 | self.current_items = (0, self.items_count) 158 | self.__carousel.controls = self.__controls(new_items) 159 | self.__carousel.update() 160 | 161 | def reset_items_index(self): 162 | if self.items: 163 | # self.update_items(self.items) 164 | self.current_items = (0, self.items_count) 165 | 166 | def __auto_cycle(self): 167 | if self.items and self.auto_cycle: 168 | self.current_items = (0, self.items_count) 169 | while 1: 170 | try: 171 | match self._auto_cycle_status: 172 | case 1: 173 | time.sleep(self.auto_cycle.duration) 174 | self.next() 175 | if self.current_items[1] == len(self.items): 176 | self.current_items = (0, self.items_count) 177 | case -1: 178 | return 179 | except: 180 | break 181 | 182 | def init_state(self): 183 | self.__auto_cycle() 184 | 185 | 186 | class BasicAnimatedHorizontalCarousel(FletCarousel): 187 | current_item: int = 0 188 | 189 | def __init__( 190 | self, 191 | page: Page, 192 | items: Optional[list[Control]] = None, 193 | width: int = None, 194 | height: int = None, 195 | expand: Union[None, bool, int] = None, 196 | tooltip: Optional[str] = None, 197 | visible: Optional[bool] = None, 198 | disabled: Optional[bool] = None, 199 | padding: PaddingValue = None, 200 | margin: MarginValue = None, alignment: Optional[Alignment] = None, 201 | bgcolor: Optional[str] = None, 202 | gradient: Optional[Gradient] = None, border: Optional[Border] = None, 203 | border_radius: BorderRadiusValue = None, 204 | auto_cycle: AutoCycle = None, 205 | hint_lines: Optional[HintLine] = False, 206 | animated_switcher: Optional[AnimatedSwitcher] = AnimatedSwitcher( 207 | content=Control(), 208 | transition=AnimatedSwitcherTransition.SCALE, 209 | duration=500, reverse_duration=100, 210 | switch_in_curve=AnimationCurve.BOUNCE_OUT, 211 | switch_out_curve=AnimationCurve.BOUNCE_IN 212 | ) 213 | ): 214 | FletCarousel.__init__( 215 | self, 216 | page=page, 217 | width=width, 218 | height=height, 219 | expand=expand, 220 | tooltip=tooltip, 221 | visible=visible, 222 | disabled=disabled, 223 | padding=padding, 224 | margin=margin, 225 | alignment=alignment, 226 | bgcolor=bgcolor, 227 | gradient=gradient, 228 | border=border, 229 | border_radius=border_radius, 230 | ) 231 | 232 | self.items = items 233 | self.auto_cycle = auto_cycle 234 | self.hint_lines = hint_lines 235 | self.animated_switcher = animated_switcher 236 | if animated_switcher and self.items: 237 | self.animated_switcher.content = self.items[0] if items else Container( 238 | ) 239 | 240 | def render(self) -> Control: 241 | 242 | _controls = [self.animated_switcher] 243 | 244 | if self.hint_lines: 245 | self.__hint_lines_element = Row( 246 | controls=self.__hint_lines_elements(), 247 | vertical_alignment=CrossAxisAlignment.CENTER, 248 | alignment=self.hint_lines.alignment, 249 | spacing=10 250 | ) 251 | _controls.append(self.__hint_lines_element) 252 | 253 | return Column( 254 | _controls, 255 | spacing=20 256 | ) 257 | 258 | def __hint_lines_elements(self): 259 | return [ 260 | Container( 261 | bgcolor=self.hint_lines.active_color if i == 0 else self.hint_lines.inactive_color, 262 | border_radius=20, 263 | width=int(self.hint_lines.max_list_size / 264 | len(self.items)), 265 | height=5, 266 | on_click=lambda e, i=i: self.go(i) 267 | ) for i in range(len(self.items)) 268 | ] 269 | 270 | def next(self, e=None): 271 | if self.current_item < len(self.items): 272 | self.go(self.current_item + 1) 273 | 274 | def prev(self, e=None): 275 | if self.current_item > 0: 276 | self.go(self.current_item - 1) 277 | 278 | def go(self, index: int): 279 | if index in range(len(self.items)): 280 | try: 281 | self.current_item = index 282 | self.animated_switcher.content = self.items[self.current_item] 283 | self.animated_switcher.update() 284 | 285 | if self.hint_lines: 286 | 287 | for c in self.__hint_lines_element.controls: 288 | c.bgcolor = self.hint_lines.inactive_color 289 | 290 | self.__hint_lines_element.controls[self.current_item].bgcolor = self.hint_lines.active_color 291 | self.__hint_lines_element.update() 292 | except: 293 | pass 294 | 295 | def __auto_cycle(self): 296 | if self.items and self.auto_cycle: 297 | self.current_item = 0 298 | while 1: 299 | try: 300 | time.sleep(self.auto_cycle.duration) 301 | self.next() 302 | if int(self.current_item + 1) == len(self.items): 303 | time.sleep(self.auto_cycle.duration) 304 | self.go(0) 305 | except: 306 | break 307 | 308 | def update_items(self, new_items: Optional[list[Control]] = None): 309 | self.items = new_items 310 | self.go(0) 311 | if self.hint_lines: 312 | self.__hint_lines_element.controls = self.__hint_lines_elements() 313 | self.__hint_lines_element.update() 314 | 315 | def init_state(self): 316 | self.__auto_cycle() 317 | --------------------------------------------------------------------------------