Groups keyboard shortcuts have been updated
Dismiss
See shortcuts

Syncing issue between two layouts

48 views
Skip to first unread message

Steven Gerber

unread,
Apr 14, 2025, 7:06:28 AMApr 14
to Kivy users support
Hey there guys & gals...
I'm back again...So i am pretty near the end of my build...a total newbie...
Sadly must admit use of ChatGPT too
Looking at below images...I have a syncing issue...

Untitled-2.png


The slider and the overlay stencil view should remain in line throughout the slider motion...
Sadly, as I move up the alignment fails...I have been knocking my head against the wall for two days and still cannot get this solved...I have provided my code below...Not sure if one would be able to ascertain the issue...I have tried to manipulate the alignment without success...because if it works in python run it does not work with android compile as the screen enlarges and issues arise...
Here is my Slider build
<EzLaunchScreen>:
    name: 'EzLaunch'
    val_text: ToT_label
    slide_text: slider_label
    tot_text: slider_tot  
    FloatLayout:      
        Slider:
            background_color: 0, 0, 0, 0
            background_width: 1
            id: slider_widget      
            min: 33
            max: 794
            step: 0.25
            value: 33
            cursor_image: 'Images/slider.png'
            cursor_width: root.width * root.csW
            cursor_height: 15.05 * root.csH
            orientation: 'vertical'
            size_hint: None, None
            size: root.slider_width, root.slider_height
            pos_hint: {'x': 0, 'y': 0.027}
            on_value: root.slide_it(*args)
            on_value: root.update_overlay_height(self.value)  

and here my python code...
W = 368
H = 794

if(platform == 'android'):
    szW = Window.width
    szH = Window.height
else:
    szW = W
    szH = H

class EzLaunchScreen(Screen):    
    image1 = StringProperty("")
    overlay_height = NumericProperty(szH)
    overlay_opacity = NumericProperty(0)          
   
    def __init__(self, **kwargs):
        super().__init__(**kwargs)

        if platform == 'android':
            self.slider_width = Window.width
            self.slider_height = Window.height
            self.csW = 0.65
            self.csH = 3
        else:
            self.slider_width = W
            self.slider_height = H
            self.csW = 0.725
            self.csH = 1.5

        img_path1 = os.path.join(main_path, 'Images/Carousel')
        img_path2 = os.path.join(main_path, 'Images/CarouselF')
        img_path3 = os.path.join(main_path, 'Images/LaunchScreen.png')

        with self.canvas.before:
            self.bg_color = Color(1, 1, 1, 1)  
            self.bg_rect = Rectangle(source=img_path3, size=Window.size, pos=self.pos)
        self.bind(size=self._update_bg, pos=self._update_bg)

        layout = FloatLayout()
        self.carousel_widget = Carousel(direction='right', size_hint=(1, 1), size=(szW, self.overlay_height))  
     
        # Load images into carousel from path...
        for img_file in os.listdir(img_path1):
            if img_file.endswith(('.png', '.jpg', '.jpeg')):                
                if not self.image1:
                    self.image1 = img_file.split('.')[0].upper()            
                img = Image(source=os.path.join(img_path1, img_file), allow_stretch = True, keep_ratio = True, size_hint=(1,1))
                self.carousel_widget.add_widget(img)
        layout.add_widget(self.carousel_widget)

        # Function to create an overlay container (StencilView to clip)
        self.overlay_container = StencilView(size_hint=(None, None), size=(self.carousel_widget.width, self.overlay_height), pos=(0,0))
       
        # Added border for testing only .............................................................................
        # with self.overlay_container.canvas.before:
        #     Color(0, 1, 0, 1)
        #     self.overlay_fill = Rectangle(pos=self.overlay_container.pos,size=self.overlay_container.size)
        # ...........................................................................................................

        self.carousel_widget.bind(width=self._update_overlay_container_width, pos=self._update_overlay_container_pos)

        self.carouselF_widget = Carousel(direction='right', size_hint=(1, 1), pos=(0, 0),size=self.carousel_widget.size)  
        # Funtion get images into carouselF from path...Top
        for img_file in os.listdir(img_path2):
            if img_file.endswith('.png'):                
                if not self.image1:
                    self.image1 = img_file.split('.')[0].upper()
                img = Image(source=os.path.join(img_path2, img_file), allow_stretch = True, keep_ratio = True, size_hint=(1,1))
                self.carouselF_widget.add_widget(img)
             
        self.overlay_container.add_widget(self.carouselF_widget)
        layout.add_widget(self.overlay_container)
        self.add_widget(layout)
        self.carousel_widget.bind(size=self._sync_overlay_size, pos=self._sync_overlay_size)

 

     # Function to clip overlay image to view underlay image to create liquid level variation...
    def update_overlay_height(self, value):
        slider = self.ids.slider_widget
        effective_max = self.startup_val if hasattr(self, 'startup_val') else slider.max
        mapped_value = (value - slider.min) / (slider.max - slider.min)
        cursor_y = slider.y + (slider.height * mapped_value)
        # Height of the overlay = percentage * visual height of the slider
        self.overlay_height = mapped_value * slider.height

        # Position stays fixed to slider base
        self.overlay_container.pos = (0, slider.y + 16.5)
        self.overlay_container.height = self.overlay_height

        print(f'====================')
        print(f'Slider cursor Y position: {cursor_y:.2f}')
        print(f'Slider value       : {slider.value}')
        print(f'Mapped value       : {mapped_value}')
        print(f'Slider Y position  : {slider.y}')
        print(f'Slider height      : {slider.height}')
        print(f'Overlay height     : {self.overlay_container.height}')
        print(f'Overlay Y pos      : {self.overlay_container.y}')
        print(f'====================')
    #..........................................................................................

I am not sure if one can get the services to have this resolved at a cost...
Thank you kindly
Steven



Chisoul Munthali

unread,
Apr 14, 2025, 7:24:33 AMApr 14
to kivy-...@googlegroups.com
Steve,
You can upload source code files to diagnose this issue effectively.

--
You received this message because you are subscribed to the Google Groups "Kivy users support" group.
To unsubscribe from this group and stop receiving emails from it, send an email to kivy-users+...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/kivy-users/1f875eab-6123-48d7-b2c9-434581b5978en%40googlegroups.com.

Steven Gerber

unread,
Apr 14, 2025, 7:47:35 AMApr 14
to Kivy users support
Hi Muntha...
Thank you for your response...
I have zipped all required to run...
This is driving me crazy...I am a VBA specialist and developed this in Excel a couple of months back...
https://www.youtube.com/watch?v=62G-834U1Yo
Obviously Excel has no security hence the need for apk...

Thanks for any advice to resolve this issue...
Forum Help.rar

Chisoul Munthali

unread,
Apr 14, 2025, 8:17:01 AMApr 14
to kivy-...@googlegroups.com
I'm going through your source code... expect a solution soon.

Steven Gerber

unread,
Apr 14, 2025, 9:43:05 AMApr 14
to Kivy users support
What...that is amazing thank you...You will make me the happiest chappie in the world...

ElliotG

unread,
Apr 14, 2025, 4:16:49 PMApr 14
to Kivy users support
You can get the desired effect by simplifying update_overlay_height to the code below.  Note you do not need to pass value, it is not used.

    def update_overlay_height(self, value):
        self.overlay_container.top = self.ids.slider_widget.value_pos[1]
 

Unrelated to this issue, you should remove the following line from your python code:
sm = ScreenManager()
sm.add_widget(EzHomeScreen(name='EzHome'))
sm.add_widget(EzLaunchScreen(name='EzLaunch'))

This is redundant with your KV code, at best it just wastes memory.

ElliotG

unread,
Apr 14, 2025, 4:39:22 PMApr 14
to Kivy users support
Here is a small example that highlights the issue you were experiencing... using value or normalized value, there is compensation for the height of the cursor.
Using value_pos delivers the desired result.

from kivy.app import App
from kivy.lang import Builder

kv = """
BoxLayout:
    orientation: 'vertical'
    Label:
        text: 'Stretch box example'
        size_hint_y: None
        height: dp(30)
    BoxLayout:
        size_hint_x: None
        width: self.minimum_width
        spacing: dp(40)
        pos_hint: {'center_x': 0.5}
        BoxLayout:
            orientation: 'vertical'
            size_hint_x: None
            width: dp(200)
            Label:
                text: 'Use value_pos'
                size_hint_y: None
                height: dp(30)
            Slider:
                cursor_image: 'Images/slider.png'
                cursor_width: self.width
                orientation: 'vertical'
                canvas:
                    Color:
                        rgba: .9, .9, .9, .5
                    Rectangle:
                        size: self.width, self.value_pos[1]
                        pos: self.pos
       
        BoxLayout:
            orientation: 'vertical'
            size_hint_x: None
            width: dp(200)
            Label:
                text: 'Use value_normalized'
                size_hint_y: None
                height: dp(30)
            Slider:
                cursor_image: 'Images/slider.png'
                cursor_width: self.width
                orientation: 'vertical'
                canvas:
                    Color:
                        rgba: .9, .9, .9, .5
                    Rectangle:
                        size: self.width, self.value_normalized * self.height
                        pos: self.pos
"""

class SliderBoxApp(App):
    def build(self):
        return Builder.load_string(kv)


SliderBoxApp().run()

Chisoul Munthali

unread,
Apr 14, 2025, 8:17:12 PMApr 14
to kivy-...@googlegroups.com
Steven,
Check out this solution... It has fully fixed your slider issues. If you encounter any problem regarding the solution provided let me know. 

stevengerber_solution.zip

Steven Gerber

unread,
Apr 15, 2025, 2:48:46 AMApr 15
to Kivy users support
Elliot...Wow wow wow...I have just finished compiling to android and it works absolutely amazingly...
You are a rock star...Would in my wildest imagination not have been able to solve this...

It reminds me of my early days of VBA where I made use of 50 lines to achieve something and now one liners are the go to lol...

PS...Yes, I recall in a previous conversation you recommended removing the redundant "sm" snippet...Have now done so...
Now to go rebuild from scratch so that i can understand each function in detail...

This file below to show the variation was interesting...Thank you for sharing...

Steven Gerber

unread,
Apr 15, 2025, 2:57:49 AMApr 15
to Kivy users support
Hi Muntha

I can see you have put a lot of effort into the re-shaping of this main file breaking it all down into smaller kv string files...
I ran the code and sadly the output is not as desired...the screen opens up stretched and the slider does not accurately represent the database readings...Also the alignment of the slider vs overlay is still out of sync...

muntha.png

Elliot's solution above resolved all...

Thank you once again for your effort....\it is appreciated...

Steven Gerber

unread,
Apr 15, 2025, 4:58:21 AMApr 15
to Kivy users support
Can I ask a last question...Would it not be better to house my Bottom carousel in a anchor layout and then the top carousel and overlay in another anchor layout...which will allow all these to centre and change in size with window...my current layouts have so many functions to deal with the adjusting...

Something like this which sadly I cannot get the two layouts to work in sync

 # layout to house carousel bottom
        lo = AnchorLayout(anchor_x='center', anchor_y='bottom',size_hint=(1, 1), size=(szW, szH))
        self.carouselB_widget = Carousel(direction='right', size_hint=(1, 1), size=(szW, szH))    
        for img_file in os.listdir(img_path1):              

            if not self.image1:
                self.image1 = img_file.split('.')[0].upper()                        
            img = Image(source=os.path.join(img_path1, img_file), allow_stretch = True, keep_ratio = True, size_hint=(1,1))
            self.carouselB_widget.add_widget(img)
        lo.add_widget(self.carouselB_widget)

        # layout to house level marker and carousel top
        olo = AnchorLayout(anchor_x='center', anchor_y='bottom',size_hint=(1, 1), size=(szW, szH))
        self.level_marker = StencilView(size_hint=(None, None), size=(szW, szH))
        self.carouselT_widget = Carousel(direction='right', size_hint=(None, None),size=(szW, szH))
        for img_file in os.listdir(img_path2):

            if not self.image1:
                self.image1 = img_file.split('.')[0].upper()
            img = Image(source=os.path.join(img_path2, img_file), allow_stretch = True, keep_ratio = True, size_hint=(1,1))
            self.carouselT_widget.add_widget(img)
        self.level_marker.add_widget(self.carouselT_widget)
        olo.add_widget(self.level_marker)

        lo.add_widget(olo)
        self.add_widget(lo)    
        
Thank you

Steven Gerber

unread,
Apr 15, 2025, 5:03:39 AMApr 15
to Kivy users support
not to worry...I am rather gonna stick with what works...

elli...@cox.net

unread,
Apr 15, 2025, 9:39:10 AMApr 15
to Kivy users support
I'd encourage you to play with the layouts and try alternatives.  It's a great way to learn.
In the code you shared: 

 lo = AnchorLayout(anchor_x='center', anchor_y='bottom',size_hint=(1, 1), size=(szW, szH))
 self.carouselB_widget = Carousel(direction='right', size_hint=(1, 1), size=(szW, szH))    

Note that if the size_hint is set to a value other than None, the hint will override the size.  The size will have no effect.  If you want to set the size, the size_hint must be set to None.  

The default size_hint is 1, 1.

From: kivy-...@googlegroups.com <kivy-...@googlegroups.com> on behalf of Steven Gerber <ezs...@gmail.com>
Sent: Tuesday, April 15, 2025 1:58 AM
To: Kivy users support <kivy-...@googlegroups.com>
Subject: Re: [kivy-users] Syncing issue between two layouts
 

Steven Gerber

unread,
Apr 16, 2025, 3:01:23 AMApr 16
to Kivy users support
Have been doing that ...Tx again for your amazing support Elliot...
Reply all
Reply to author
Forward
0 new messages