simple dashed line

512 views
Skip to first unread message

Sadaka Technology

unread,
Jan 31, 2021, 2:42:15 AM1/31/21
to Kivy users support
how to simply draw a kivy dashed line ( with dashes)  

Elliot Garbus

unread,
Jan 31, 2021, 10:12:06 AM1/31/21
to kivy-...@googlegroups.com

https://kivy.org/doc/stable/api-kivy.graphics.html#kivy.graphics.Line

If the line width is 1, the dash parameters work to create a dashed line.  For width greater than 1, you would need to create your own line segments.

 

from kivy.app import App

from kivy.lang import Builder

 

kv = """

<DashedLabel@Label>:

    canvas:

        Color:

            rgb: 1, 1, 1

        Line:

            dash_offset: 2

            dash_length: 10

            rectangle: (*self.pos, *self.size)

 

BoxLayout:

    padding: 20

    spacing: 20

    DashedLabel:

        text: 'One'

    DashedLabel:

        text: 'Two'

 

"""

 

class DashedApp(App):

    def build(self):

        return Builder.load_string(kv)

 

DashedApp().run()

--
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 on the web visit https://groups.google.com/d/msgid/kivy-users/378c3985-6e3a-4198-baab-d16fa0ed5201n%40googlegroups.com.

 

Sadaka Technology

unread,
Jan 31, 2021, 11:19:48 AM1/31/21
to Kivy users support
what is the use of dash_length and dash_offset

Elliot Garbus

unread,
Jan 31, 2021, 11:28:09 AM1/31/21
to kivy-...@googlegroups.com

From the docs:

dash_length: int

Length of a segment (if dashed), defaults to 1.

 

dash_offset: int

Offset between the end of a segment and the beginning of the next one, defaults to 0. Changing this makes it dashed.

 

dashes: list of ints

List of [ON length, offset, ON length, offset, …]. E.g. [2,4,1,6,8,2] would create a line with the first dash length 2 then an offset of 4 then a dash lenght of 1 then an offset of 6 and so on. Defaults to []. Changing this makes it dashed and overrides dash_length and dash_offset.

Sadaka Technology

unread,
Jan 31, 2021, 11:48:48 AM1/31/21
to Kivy users support
how can I make one rounded rectangle corner ?

Sadaka Technology

unread,
Jan 31, 2021, 11:51:58 AM1/31/21
to Kivy users support
I am trying using :

Line:
width: 1.2
ellipse: (self.x, self.y, self.width, self.height, 315, 360)

but not getting a good angle (90 degrees) 

Elliot Garbus

unread,
Jan 31, 2021, 1:09:54 PM1/31/21
to kivy-...@googlegroups.com

360 – 315 = 45, not 90

The ellipse you are drawing is not a circle if that matters.  The size and height would need to be that same to draw a circle.

 

Rounded rectangle:

https://kivy.org/doc/stable/api-kivy.graphics.html?highlight=rounded%20rectangle#kivy.graphics.Line.rounded_rectangle

Sadaka Technology

unread,
Jan 31, 2021, 1:56:58 PM1/31/21
to Kivy users support
that is nice, Thank you!!

now how can I allow the widget to rotate,

when I am using:

canvas.before:
    PushMatrix
    Rotate:
        angle: root.angle
        axis: 0, 0, 1
        origin: root.center
canvas.after:
    PopMatrix

all canvas disappears or goes black

Elliot Garbus

unread,
Jan 31, 2021, 4:04:03 PM1/31/21
to kivy-...@googlegroups.com

I’ve updated the example:

 

from kivy.app import App
from kivy.lang import Builder
from kivy.animation import Animation
from kivy.uix.label import Label
from kivy.properties import NumericProperty

kv =
"""
<RRLabel>:

    canvas:
        Color:
            rgb: 1, 1, 1
        Line:
            width: 1.2
            rounded_rectangle: (self.center_x - 50, self.center_y - 50, 100, 100, 0, 20, 0, 0)

    canvas.before:
        PushMatrix
        Rotate:
            angle: root.angle
            origin: self.center
    canvas.after:
        PopMatrix
       
BoxLayout:
    orientation: 'vertical'    
    BoxLayout:
        padding: 100
        spacing: 75
        RRLabel:
            id: rr1
            text: 'One'
        RRLabel:
            id: rr2
            text: 'Two'
    Button:
        size_hint_y: None
        height: 48
        text: 'Spin'
        on_release:
            rr1.spin()
            rr2.spin()

"""


class RRLabel(Label):
    angle = NumericProperty(
0)

   
def spin(self):
       
self.angle = 0
       
anim = Animation(angle=360)
        anim.start(
self)


Sadaka Technology

unread,
Feb 1, 2021, 1:18:54 AM2/1/21
to Kivy users support
something wrong , why I am not getting the widget XD , when I add this part :
canvas.before:
    PushMatrix
    Rotate:
        angle: root.angle
        origin: self.center
canvas.after:
    PopMatrix

the total widget disappears

Sadaka Technology

unread,
Feb 1, 2021, 1:23:01 AM2/1/21
to Kivy users support
you can say , when I only remove the part

Rotate:

Sadaka Technology

unread,
Feb 1, 2021, 1:49:07 AM2/1/21
to Kivy users support
and pushmatrix and popmatrix they do bug my scrollviews

Sadaka Technology

unread,
Feb 1, 2021, 4:43:19 AM2/1/21
to Kivy users support
how can I reference the canvas in __init__ function

Elliot Garbus

unread,
Feb 1, 2021, 9:11:01 AM2/1/21
to kivy-...@googlegroups.com

how can I reference the canvas in __init__ function

self.canvas

You may want to use it with a context manager:  with self.canvas:

See: https://kivy.org/doc/stable/api-kivy.uix.widget.html?highlight=canvas#basic-drawing

 

I’d need to see more code to help with your other questions.

Sadaka Technology

unread,
Feb 1, 2021, 1:57:32 PM2/1/21
to Kivy users support
so I can use source in the canvas and based on source I can reference, any ways I used isinstance method and it worked,,

remember one time you sent me this example:

    def on_touch_move(self, touch):
        if touch.grab_current is self and self.touched == True:
            b = self.subject
            if b != None:
                b.x = sorted([self.x, touch.pos[0], self.right - b.width])[1]
                b.y = sorted([self.y, touch.pos[1], self.height - b.height])[1]
                return True
        return super().on_touch_move(touch)

I forgot what sorted means, is it ok if you repeat the use of sorted, and can I use it for instance.width ?! 

I am getting self.right = to the width of the widget I dont know why it is not giving me the exact value of self.right

Elliot Garbus

unread,
Feb 1, 2021, 5:05:23 PM2/1/21
to kivy-...@googlegroups.com

Sorted is a python built in: https://docs.python.org/3/library/functions.html#sorted

 

It returns a sorted list.  In the context below it can be used as a clamp, to return a value no higher that max and no lower that min

 

value = sorted(min, v, max)[1]

 

sorted returns a sorted list, if v is less that min: [v, min, max]

and [v, min, max][1] is min

 

if v is between min and max… [min, v, max][1] is v

and if v is over max… [min, max, v][1] is max.

Sadaka Technology

unread,
Feb 2, 2021, 2:38:31 PM2/2/21
to Kivy users support
how can I use if self.collide_widget(self.Line_left) for example ?!

it says Line is not a widget it is a canvas

Elliot Garbus

unread,
Feb 2, 2021, 2:48:04 PM2/2/21
to kivy-...@googlegroups.com

I would need more context.

collide_widget takes x,y as parameters.  I don’t know what Line_left is.

sersa...@outlook.com

unread,
Feb 2, 2021, 3:10:01 PM2/2/21
to kivy-...@googlegroups.com

Line left is one of the lines I have drawn using canvas,,

So I believe the only way is to make a class inside a line drawn in this class and add this class to the main class in order to make a line act as a widget

Tuesday, 02 February 2021, 11:48PM +04:00 from Elliot Garbus elli...@cox.net:

"""
:

:

Elliot Garbus

unread,
Feb 2, 2021, 3:42:37 PM2/2/21
to kivy-...@googlegroups.com

The collide_widget method is a widget method and takes a widget as an argument.  You would need to have the widget be the same size at the line (and assuming the line is a rectangle) for this to work.  You could also create your own collide test for the line.

 

Here is the code for collide_widget:

 

 

    def collide_widget(self, wid):

        '''

        Check if another widget collides with this widget. This function

        performs an axis-aligned bounding box intersection test by default.

        :Parameters:

            `wid`: :class:`Widget` class

                Widget to test collision with.

        :Returns:

            bool. True if the other widget collides with this widget, False

            otherwise.

        .. code-block:: python

            >>> wid = Widget(size=(50, 50))

            >>> wid2 = Widget(size=(50, 50), pos=(25, 25))

            >>> wid.collide_widget(wid2)

            True

            >>> wid2.pos = (55, 55)

            >>> wid.collide_widget(wid2)

            False

        '''

        if self.right < wid.x:

            return False

        if self.x > wid.right:

            return False

        if self.top < wid.y:

            return False

       if self.y > wid.top:

            return False

        return True

Sadaka Technology

unread,
Feb 3, 2021, 12:47:56 PM2/3/21
to Kivy users support
I am trying to draw lines in widget corner, each line has a height of 6, 

one line is left side in the center_y
2nd line in bottom side in the center_x
3rd line in top side in the center_x
4th line in right side in the center_y

I am trying to do a dynamic resize for the widget, if user hits say left side line, the widget x and width will be equal to self.right - touch.x and same for other lines

I will try to post full code so far, I am getting issue where widgets are colliding with each others.

this parent widget is only a widget added to its parent where size_hint = 1,1 pos_hint = {'x':0,'y':0}

using function  def get_resize_parameters I am getting values from data base for the root widget ( Float_edit)

check the attached code:
check.py

Elliot Garbus

unread,
Feb 3, 2021, 5:09:06 PM2/3/21
to kivy-...@googlegroups.com

This is just a code snippet.  Please attach an executable program.  

Elliot Garbus

unread,
Feb 3, 2021, 6:27:51 PM2/3/21
to kivy-...@googlegroups.com

Looking at your code I got a sense of what you are trying to do – but I don’t full understand it.  I thought this approach might be a simpler way to get to same outcome.  This code creates a dynamically sized widget, that gets size by touch movement. 

This code creates a float widget, and draw a resizable rectangle the move action is changed based on the original on_touch_down position.  This is not intended to do exactly what you want – but to illustrate an approach.

 

 

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.floatlayout import FloatLayout
from kivy.properties import ColorProperty

kv =
"""
<ResizeSelect>:
    canvas:
        Color:
            rgba: root.color
        Line:
            rectangle: (*self.pos, *self.size)

FloatLayout:
    ResizeSelect:
        size_hint: None, None
        size: 100,100
        pos_hint: {'center_x': 0.5, 'center_y': 0.5}
"""


class ResizeSelect(FloatLayout):
    color = ColorProperty(
'white')

   
def __init__(self, **kwargs):
       
super().__init__(**kwargs)
       
self.quadrant = None

    def
on_touch_down(self, touch):
       
if self.collide_point(*touch.pos):
            touch.grab(
self)
           
# which corner is closest NE, NW, SE, SW?
            
x, y = self.to_widget(*touch.pos)
           
self.quadrant = 'N' if y > self.center[1] else 'S'
           
self.quadrant += 'W' if x > self.center[0] else 'E'
           
print(self.quadrant)
           
return True
        return
super().on_touch_down(touch)

   
def on_touch_move(self, touch):
       
if touch.grab_current is self:
           
if self.quadrant == 'NW':
               
self.height += 2 * touch.dy
               
self.width += 2 * touch.dx
               
return True
            if
self.quadrant == 'NE':
               
self.height += 2 * touch.dy
               
self.width += 2 * -touch.dx
               
return True
            if
self.quadrant == 'SW':
               
self.height += 2 * -touch.dy
               
self.width += 2 * touch.dx
               
return True
            if
self.quadrant == 'SE':
               
self.height += 2 * -touch.dy
               
self.width += 2 * -touch.dx
               
return True
        return
super().on_touch_move(touch)

   
def on_touch_up(self, touch):
       
if touch.grab_current is self:
            touch.ungrab(
self)
           
return True
        return
super().on_touch_up(touch)


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


ResizeWidgetApp().run()

Sadaka Technology

unread,
Feb 4, 2021, 4:30:11 PM2/4/21
to Kivy users support
what is the difference between touch,dy touch.dx and touch.y / touch.x

Elliot Garbus

unread,
Feb 4, 2021, 4:41:03 PM2/4/21
to kivy-...@googlegroups.com

Read: https://kivy.org/doc/stable/api-kivy.input.motionevent.html?highlight=touch

touch.x, touch.y is the position of the mouse in windows coordinates.

dx and dy are the change from the previous position to the current position.

Sadaka Technology

unread,
Feb 4, 2021, 5:20:12 PM2/4/21
to Kivy users support
so if I use x,y self.to_widget I get dx and dy ?! 

suppose if I didnt do self.to_widget so I will be in window coordinate, the thing is if you touch a point somewhere in widget this point position say x is equal to 220 so dx must also equal 220 ?! or something else ?

Sadaka Technology

unread,
Feb 4, 2021, 5:22:07 PM2/4/21
to Kivy users support
I tried you example, when clicking on bottom left and top left corners I am getting SE , when clicking on bottom and top right I am getting SW o.o

Elliot Garbus

unread,
Feb 4, 2021, 5:42:54 PM2/4/21
to kivy-...@googlegroups.com
That does not sound right the example was working for me. 

Sent from my iPhone

On Feb 4, 2021, at 3:22 PM, Sadaka Technology <sersa...@outlook.com> wrote:

I tried you example, when clicking on bottom left and top left corners I am getting SE , when clicking on bottom and top right I am getting SW o.o

Elliot Garbus

unread,
Feb 4, 2021, 5:43:57 PM2/4/21
to kivy-...@googlegroups.com
If the user more the mouse by 5 pixels,  dx is 5. 

Sent from my iPhone

On Feb 4, 2021, at 3:42 PM, Elliot Garbus <elli...@cox.net> wrote:

That does not sound right the example was working for me. 

Elliot Garbus

unread,
Feb 4, 2021, 5:44:41 PM2/4/21
to kivy-...@googlegroups.com
Try printing out the values so you can see what is happening. 

Sent from my iPhone

On Feb 4, 2021, at 3:20 PM, Sadaka Technology <sersa...@outlook.com> wrote:

so if I use x,y self.to_widget I get dx and dy ?! 
Message has been deleted

Sadaka Technology

unread,
Feb 4, 2021, 6:37:21 PM2/4/21
to Kivy users support
could kivy or python version play a role !?

Elliot Garbus

unread,
Feb 4, 2021, 6:44:38 PM2/4/21
to kivy-...@googlegroups.com

Seems unlikely.  Are you running the example unmodified? 

 

I just confirmed, it works as expected on Kivy 2.0.0, python 3.9.1

 

I modified the app to change the color property to a ListProperty, and It works as expect on kivy 1.11.1 and Python 3.7.4

Message has been deleted

Sadaka Technology

unread,
Feb 4, 2021, 7:04:56 PM2/4/21
to Kivy users support
I am using kivy 2.0rc4 , I guess my only issue is regarding pos_hint, I will try something,,, I am running your code it is not running  which I mean , kivy config is not showing 

Elliot Garbus

unread,
Feb 4, 2021, 7:15:14 PM2/4/21
to kivy-...@googlegroups.com

Double check that the code is all there - that is strange that it is not running.

Sadaka Technology

unread,
Feb 4, 2021, 7:24:55 PM2/4/21
to Kivy users support
yes now running, that is cool, now you are doing resizing through the corners, I want it through the sides, for ex:

if click on total right side trying to resize, it will only resize from right side, if I click on left side of the square it will only resize through left side and same for bottom and top, this will resize the widget and also will change its position, another thing also, is that I want to rotate the widget , my issue is that I have started with parent widget as a pos_hint inside its parent and resize widget also as a pos_hint inside its parent

Sadaka Technology

unread,
Feb 4, 2021, 7:25:22 PM2/4/21
to Kivy users support
so what I mean if I resize from one side, all other sides must freeze

Sadaka Technology

unread,
Feb 4, 2021, 7:34:29 PM2/4/21
to Kivy users support
you are resizing from the corners, I want from the sides (edges) also I want to give a minimum size of 15 width 15 height

Elliot Garbus

unread,
Feb 4, 2021, 7:35:45 PM2/4/21
to kivy-...@googlegroups.com

As I have put it together I am looking for a touch in a quadrant and sizing the entire box.  If you want to maintain that behavior, add some new cases to the on_touch_down(), if the press is near the center of a side give that a ‘name’ NN, SS, EE, WW… and create the appropriate action in on_touch_move.

Elliot Garbus

unread,
Feb 4, 2021, 7:37:21 PM2/4/21
to kivy-...@googlegroups.com

Do you want to only resize a side, or sides and corners?

If you want to have a min size, set that up in the on_touch_move so the size can be no smaller than the min.

Sadaka Technology

unread,
Feb 4, 2021, 7:51:59 PM2/4/21
to Kivy users support
I want to resize only all sides , no corners,, can I use sorted in this case ?!

yes I got you, but regarding position which is best to use ?! I am using pos_hint and size_hint, I believe position is better than pos_hint could this work for pos_hint ?!

Message has been deleted

Sadaka Technology

unread,
Feb 4, 2021, 8:08:09 PM2/4/21
to Kivy users support
look, I have a FloatLayout, inside it another FloatLayout having a canvas, say rounded rectangle, once the user clicks on the button I am adding resize layout which equals size_hint =1,1 on this rounded rectangle, so that once this resize layout moves, its parent(rounded rectangle also moves) , so both must be always equal size and equal position, if I am setting pos_hint {'right':something} , this will not allow the widget to resize or move from the right side, so in each function I am adjusting pos_hint , if left side pos_hint = {'x':something} and same goes for right side 

Elliot Garbus

unread,
Feb 6, 2021, 10:57:19 AM2/6/21
to kivy-...@googlegroups.com

I would not use size hints or pos hints if you need to change the size and pos of the widget.

I suggest you start with the example I posted.  Make small changes.  If you have questions – ask and post the code.

Sadaka Technology

unread,
Feb 6, 2021, 1:48:01 PM2/6/21
to Kivy users support
look, my only question is if I want to resize from left side for example, I have to freeze right side, so that time I must bind pos_hint = {'right':something}, and once I go for right side resizing I have to freeeze left side so that time I must use pos_hint = {'x':something} you get the point, how can I freeze,

another thing is I would really like to know, the differences betweeen x,y = self.widget(*touch.pos) and touch.pos how it will differ and when it is equal,

another is the difference between touch.dx/touch.dy and touch.x/touch.y

Elliot Garbus

unread,
Feb 6, 2021, 2:10:03 PM2/6/21
to kivy-...@googlegroups.com

To change the size from the right.  I would not touch the position, but reduce the size (or perhaps just setting self.right ?).  To change the size on the left, I would change the position and the size.

 

I would really like to know, the differences betweeen x,y = self.to_widget(*touch.pos) and touch.pos how it will differ and when it is equal.  Only different if the widget is in a RelativeLayout.  Read: https://kivy.org/doc/stable/api-kivy.uix.relativelayout.html#coordinate-systems

 

difference between touch.dx/touch.dy and touch.x/touch.y.  I had described this previously. I’ll try again. 

Read: https://kivy.org/doc/stable/api-kivy.input.html

Using x as an example:

x is the position x, in windows coordinates

px is the previous position of x

dx = x – px

 

If the pointer was a x = 100, and you moved 5 pixels, dx would be 5.  The best way to understand this is to put together a simple example and print out the values.

Sadaka Technology

unread,
Feb 6, 2021, 2:31:37 PM2/6/21
to Kivy users support
yes yes I got it touch.dx, thank you alot,

but regarding these self.to_window, self.to_widget, self.to_parent , I must have an example of all with printing each value, 

because in your example u gave me, I am not getting the difference between x/y in x,y = self.to_widget(*touch,pos) and touch.x/touch.y

another thing, how can I freeze 1 opposite side while resizing the widget, so suppose the mouse click is on left side of the widget, I used on_touchmethod and moving mouse to left, I want this left side to move with the touch, but right side to be frozen I want it to be remain same during moving left side of the widget, and same thing applies on right side if I apply on_touch on right side

Elliot Garbus

unread,
Feb 6, 2021, 4:21:27 PM2/6/21
to kivy-...@googlegroups.com

I extended the example… I did not have time to get all of the size limits in place…    Let me know if this is in the right direction…

 

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.floatlayout import FloatLayout
from kivy.properties import ColorProperty

import math

kv =
"""
<ResizeSelect>:
    canvas:
        Color:
            rgba: root.top_color
        Line:
            width: 1.2
            points: (self.x, self.top, self.right, self.top)  # Top
        Color:
            rgba: root.bottom_color
        Line:
            width: 1.2
            points: (*self.pos, self.right, self.y)  # Bottom
        Color:
            rgba: root.left_color
        Line:
            width: 1.2
            points: (*self.pos, self.x, self.top)  # Left
        Color:
            rgba: root.right_color
        Line:
            width: 1.2
            points: (self.right, self.y, self.right, self.top)  # Right

               

FloatLayout:
    ResizeSelect:
        size_hint: None, None
        size: 100,100
        pos: 200, 200
"""


class ResizeSelect(FloatLayout):
    top_color = ColorProperty(
'white')
    bottom_color = ColorProperty(
'white')
    left_color = ColorProperty(
'white')
    right_color = ColorProperty(
'white')
    highlight_color = ColorProperty(
'red')

   
def __init__(self, **kwargs):
       
super().__init__(**kwargs)
       
self.selected_side = None

    def
on_touch_down(self, touch):
       
if self.collide_point(*touch.pos):
            touch.grab(
self)
           
# use the distance formula to find the shortest distance to a line center
            # d = sqrt((x1-x2)^2 - (y1-y2)^2)
           
x, y = self.to_widget(*touch.pos)
            d_b = math.sqrt(((x -
self.center_x) ** 2) + ((y - self.y) ** 2))  # bottom
           
d_t = math.sqrt(((x - self.center_x) ** 2) + ((y - self.top) ** 2))  # top
           
d_l = math.sqrt(((x - self.x) ** 2) + ((y - self.center_y) ** 2))  # left
           
d_r = math.sqrt(((x - self.right) ** 2) + ((y - self.center_y) ** 2))  # right
           
print(f'{d_b=}, {d_t=}, {d_l=}, {d_r=}')
           
# create tuples
           
distances = [('bottom', d_b), ('top', d_t), ('left', d_l), ('right', d_r)]
            distances.sort(
key=lambda dist: dist[1])
           
self.selected_side = side = distances[0][0]
           
if side == 'top':
               
self.top_color = self.highlight_color
           
elif side == 'bottom':
               
self.bottom_color = self.highlight_color
           
elif side == 'left':
               
self.left_color = self.highlight_color
           
elif side == 'right':
               
self.right_color = self.highlight_color
           
return True
        return
super().on_touch_down(touch)

   
def on_touch_move(self, touch):
        min_size =
15.0
       
if touch.grab_current is self:
           
if self.selected_side == 'top':
               
self.height = max(self.height + touch.dy, min_size)
           
elif self.selected_side == 'bottom'# TODO: Add limits to other dimensions...
               
self.height -= touch.dy
               
self.y += touch.dy
           
elif self.selected_side == 'left':
               
self.x += touch.dx
               
self.width -= touch.dx
           
elif self.selected_side == 'right':
               
self.width += touch.dx

       
return super().on_touch_move(touch)

   
def on_touch_up(self, touch):
       
if touch.grab_current is self:
            touch.ungrab(
self)
           
self.bottom_color = self.top_color = self.left_color = self.right_color = 'white'
           
return True
        return
super().on_touch_up(touch)


Sadaka Technology

unread,
Feb 6, 2021, 4:56:34 PM2/6/21
to Kivy users support
what are you man :P !! thank you very much for the kindness, yes it worked, remaining only size limits, 

Thank you very much!

Message has been deleted
Message has been deleted

Sadaka Technology

unread,
Feb 7, 2021, 8:09:35 AM2/7/21
to Kivy users support
is it possible in this code to allow also +10 for each side so if the touch appears say in right side +10 the widget resizing applies

Elliot Garbus

unread,
Feb 7, 2021, 9:29:14 AM2/7/21
to kivy-...@googlegroups.com

The distances of the current touch are calculated to the middle of each of the sides.  The app then determines the slide that is closest to the touch.

 

# a list of tuples that associates a name with each of the measurements.

distances = [('bottom', d_b), ('top', d_t), ('left', d_l), ('right', d_r)]

 

# to find the smallest tuple the app sorts the values.  The values need to be sorted by the distance value, not the name.

# sort uses key to indicate the value to be used for sort.  Key take a function that is passed a list element and returns the sort key

# this is the typical use of a lambda.  A lambda is an anonymous function.  Passed a tuple from the list “dist” it returns dist[1], a distance value


distances.sort(key=lambda dist: dist[1])

 

# distances is now sorted, the smallest element is in distances[0].  The name is in distances[0][0]


self.selected_side = side = distances[0][0]

 

Answering your question I realize this could be written with the built-in min() function.  The logic is the same, the code is even shorter:

distances = [('bottom', d_b), ('top', d_t), ('left', d_l), ('right', d_r)]
self.selected_side = side = min(distances, key=lambda dist: dist[1])[0]

 

 

 

From: Sadaka Technology
Sent: Sunday, February 7, 2021 3:30 AM
To: Kivy users support
Subject: Re: RE: [kivy-users] simple dashed line

 

here comes the questions if ok for you:

 

distances = [('bottom', d_b), ('top', d_t), ('left', d_l), ('right', d_r)]
distances.sort(key=lambda dist: dist[1])
self.selected_side = side = distances[0][0]

 

these 3 lines, what is the use of .sort and  lambda, what is dist : dist[1], and tuples inside list 

Elliot Garbus

unread,
Feb 7, 2021, 9:32:04 AM2/7/21
to kivy-...@googlegroups.com

Draw the lines 10 pixels inside their current positions.  Then all of the other logic remains the same, and you are sure you are clicking on this widget, and not one next to it.

Sadaka Technology

unread,
Feb 7, 2021, 2:03:04 PM2/7/21
to Kivy users support
actually, I tried to remove the comments, guess they did not get deleted, because I studied the points one by one, all I understood clearly, thank you for you time,

the only thing that is not entering my head, is self.to_widget, how can this help me why not just touch.x touch.y, why not self.to_parent, I need an example with prints of the differences and the use of them, what could  happen if I run your code with touch.x and touch.y not self.to_widget

Sadaka Technology

unread,
Feb 7, 2021, 3:56:32 PM2/7/21
to Kivy users support
one other thing, in your example, the root layout is taking the whole screen, how can I give limits to the position in my example, so that it doesnt surpass the root limits

Elliot Garbus

unread,
Feb 7, 2021, 4:52:39 PM2/7/21
to kivy-...@googlegroups.com

I put the ResizeSelect widget in a RelativeLayout.  You  can see there are now different values for the to_widget(),  but I realize the conversion is not required because the ResizeSelect widget is a FloatLayout.

 

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.relativelayout import RelativeLayout
"""
GridLayout:
    cols:2
    rows: 2
    Button:
        text: 'One'
    Button:
        text: 'Two'
    Button:
        text:'Three'
    BoxLayout:
        RelativeLayout:
            Button:
                text: 'RB'
                pos_hint: {'top': 1, 'right': 1}
                size_hint: None, None
                size: 100, 100

           
            ResizeSelect:
                size_hint: None, None
                size: 100,100
                pos: 20, 20
"""


class ResizeSelect(FloatLayout):
    top_color = ColorProperty(
'white')
    bottom_color = ColorProperty(
'white')
    left_color = ColorProperty(
'white')
    right_color = ColorProperty(
'white')
    highlight_color = ColorProperty(
'red')

   
def __init__(self, **kwargs):
       
super().__init__(**kwargs)
       
self.selected_side = None

    def
on_touch_down(self, touch):
       
if self.collide_point(*touch.pos):
            touch.grab(
self)
           
# use the distance formula to find the shortest distance to a line center

            # d = sqrt((x1-x2)^2 - (y1-y2)^2)
            x, y = touch.pos[0], touch.pos[1]
           
print(f'{touch.pos=}{self.to_widget(*touch.pos)=}, {self.center=}')

            d_b = math.sqrt(((x -
self.center_x) ** 2) + ((y - self.y) ** 2))  # bottom
           
d_t = math.sqrt(((x - self.center_x) ** 2) + ((y - self.top) ** 2))  # top
           
d_l = math.sqrt(((x - self.x) ** 2) + ((y - self.center_y) ** 2))  # left
           
d_r = math.sqrt(((x - self.right) ** 2) + ((y - self.center_y) ** 2))  # right
           
print(f'{d_b=}, {d_t=}, {d_l=}, {d_r=}')
           
# create tuples
           
distances = [('bottom', d_b), ('top', d_t), ('left', d_l), ('right', d_r)]
           
self.selected_side = side = min(distances, key=lambda dist: dist[1])[0]
           
if side == 'top':
               
self.top_color = self.highlight_color
           
elif side == 'bottom':
               
self.bottom_color = self.highlight_color
           
elif side == 'left':
               
self.left_color = self.highlight_color
           
elif side == 'right':
               
self.right_color = self.highlight_color
           
return True
        return
super().on_touch_down(touch)

   
def on_touch_move(self, touch):
        min_size =
15.0
       
if touch.grab_current is self:
           
if self.selected_side == 'top':
               
self.height = max(self.height + touch.dy, min_size)
           
elif self.selected_side == 'bottom'# TODO: Add limits to other dimensions...
               
self.height -= touch.dy
               
self.y += touch.dy
           
elif self.selected_side == 'left':
               
self.x += touch.dx
               
self.width -= touch.dx
           
elif self.selected_side == 'right':
               
self.width = max(self.width + touch.dx, min_size)

       
return super().on_touch_move(touch)

   
def on_touch_up(self, touch):
       
if touch.grab_current is self:
            touch.ungrab(
self)
           
self.bottom_color = self.top_color = self.left_color = self.right_color = 'white'
           
return True
        return
super().on_touch_up(touch)


Elliot Garbus

unread,
Feb 7, 2021, 6:56:09 PM2/7/21
to kivy-...@googlegroups.com

I got started on putting together the layout to update on_touch_move() to restrict the max sizes…  I’m not sure where I left this earlier today – I won’t get a chance to get back to this till tomorrow… I’m sharing this WIP in case you do any work on it…

 

"""
    cols:3
    rows: 3

    Button:
        text: 'One'
    Button:
        text: 'Two'
    Button:
        text:'Three'
    Button:
        text: 'Four'

    BoxLayout:
        RelativeLayout:
            Button:
                text: 'RB'
                pos_hint: {'top': 1, 'right': 1}
                size_hint: None, None
                size: 50, 50
           
            ResizeSelect:
               size_hint: None, None
                size: 50,50
                pos: 20, 20
   
    Button:
        text: 'Six'
    Button:
        text: 'Seven'
    Button:
        text: 'Eight'
    Button:
        text:'Nine'
"""


class ResizeSelect(FloatLayout):
    top_color = ColorProperty(
'white')
    bottom_color = ColorProperty(
'white')
    left_color = ColorProperty(
'white')
    right_color = ColorProperty(
'white')
    highlight_color = ColorProperty(
'red')

   
def __init__(self, **kwargs):
        
super().__init__(**kwargs)
       
self.selected_side = None

    def
on_touch_down(self, touch):
       
if self.collide_point(*touch.pos):
            touch.grab(
self)
           
# use the distance formula to find the shortest distance to a line center
            # d = sqrt((x1-x2)^2 - (y1-y2)^2)
           
x, y = touch.pos[0], touch.pos[1
]

           
# print(f'{touch.pos=},  {self.to_widget(*touch.pos)=}, {self.center=}')

           
d_b = math.sqrt(((x - self.center_x) ** 2) + ((y - self.y) ** 2))  # bottom
           
d_t = math.sqrt(((x - self.center_x) ** 2) + ((y - self.top) ** 2))  # top
           
d_l = math.sqrt(((x - self.x) ** 2) + ((y - self.center_y) ** 2))  # left
           
d_r = math.sqrt(((x - self.right) ** 2) + ((y - self.center_y) ** 2))  # right
            # print(f'{d_b=}, {d_t=}, {d_l=}, {d_r=}')
            # create tuples
           
distances = [('bottom', d_b), ('top', d_t), ('left', d_l), ('right', d_r)]
           
self.selected_side = side = min(distances, key=lambda dist: dist[1])[0]
           
if side == 'top':
               
self.top_color = self.highlight_color
           
elif side == 'bottom':
               
self.bottom_color = self.highlight_color
           
elif side == 'left':
               
self.left_color = self.highlight_color
           
elif side == 'right':
               
self.right_color = self.highlight_color
           
return True
        return
super().on_touch_down(touch)

   
def on_touch_move(self, touch):
        min_size =
15.0
       
if touch.grab_current is self:
           
print(f'{self.parent.pos=}, {self.pos=}, {touch.pos=}, {self.to_window(*touch.pos)=} {self.parent.right=} ')
            x,y =
self.to_window(*self.pos)
            top = y +
self.height
            right = x +
self.width
           
if x < self.parent.x or right > self.parent.right:
               
print('X out of bounds')
           
if y < self.parent.y or top > self.parent.top:
               
print('y out of bounds')

           
if self.selected_side == 'top':
               
self.height = max(self.height + touch.dy, min_size)
           
elif self.selected_side == 'bottom'# TODO: Add limits to other dimensions...
               
self.height -= touch.dy
               
self.y += touch.dy
               
self.y = max(self.to_widget(*self.parent.pos)[1], self.y)
           
elif self.selected_side == 'left':
               
self.x += touch.dx
               
self.width -= touch.dx
               
# self.x = min(self.parent.x, self.x)
           
elif self.selected_side == 'right':
               
self.width = max(self.width + touch.dx, min_size)

       
return super().on_touch_move(touch)

   
def on_touch_up(self, touch):
       
if touch.grab_current is self:
            touch.ungrab(
self)
           
self.bottom_color = self.top_color = self.left_color = self.right_color = 'white'
           
return True
        return
super().on_touch_up(touch)


Sadaka Technology

unread,
Feb 8, 2021, 4:10:02 AM2/8/21
to Kivy users support
look, your code is not working in my example, unfortunately , in your case you are resizing widget inside parent window, in mine I am resizing widget inside FloatLayout inside FloatLayout inside GridLayout inside horizontal scroll inside FloatLayout inside GridLayout inside window, I will try to combine the total code

Sadaka Technology

unread,
Feb 8, 2021, 4:20:47 AM2/8/21
to Kivy users support
somehow self.to_local is working in on_touch_down, but on_touch_move is too height and widget size and pos and going far than the touch.pos by big difference

Sadaka Technology

unread,
Feb 8, 2021, 4:36:58 AM2/8/21
to Kivy users support
the other thing is, in on_touch_move , I am getting multiple sides,, red color is appearing in more than one side

Sadaka Technology

unread,
Feb 8, 2021, 9:51:14 AM2/8/21
to Kivy users support
I have doubt that during on_touch_move, I am calling on_touch_down mutliple times, I used print('here') it is printing frequently in on_touch_down, what could be the reason

Elliot Garbus

unread,
Feb 8, 2021, 10:21:19 AM2/8/21
to kivy-...@googlegroups.com

I have updated the test case to look at the widget in both a relative layout and a floatlayout.

The size limit and top position limit (top can not go past parent top) are working.  I’ll share more as I update.

 

"""
                pos: 20, 40
           
            Label:
                text: 'RelativeLayout'
                size_hint: None, None
                size: self.texture_size
                pos_hint: {'center_x': .5, 'y': .05}
   
    Button:
        text: 'Six'

    FloatLayout:
        ResizeSelect:
            size_hint: None, None
            size: 50,50
            pos: 20, 40
        Label:
            text: 'FloatLayout'
            size_hint: None, None
            size: self.texture_size
            pos_hint: {'center_x': .5, 'y': .05}
)
            x, y =
self.to_window(*self.pos)
            top = y +
self.height
            right = x +
self.width
           
if x < self.parent.x or right > self.parent.right:
               
print('X out of bounds')
           
if y < self.parent.y or top > self.parent.top:
               
print('y out of bounds')

           
if self.selected_side == 'top':
               
self.height = max(self.height + touch.dy, min_size)  # todo: Simplify to include top limit?
               
if top > self.parent.top:
                   
self.height = self.parent.height - (y - self.parent.y)
           
elif self.selected_side == 'bottom'# TODO: Add limits to other dimensions...
               
self.height -= touch.dy
               
self.y += touch.dy
               
self.y = max(self.to_widget(*self.parent.pos)[1], self.y)
           
elif self.selected_side == 'left':
               
self.x += touch.dx
               
self.width -= touch.dx
               
# self.x = min(self.parent.x, self.x)
           
elif self.selected_side == 'right':
               
self.width = max(self.width + touch.dx, min_size)

        
return super().on_touch_move(touch)

   
def on_touch_up(self, touch):
       
if touch.grab_current is self:
            touch.ungrab(
self)
           
self.bottom_color = self.top_color = self.left_color = self.right_color = 'white'
           
return True
        return
super().on_touch_up(touch)


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


ResizeWidgetApp().run()

Sadaka Technology

unread,
Feb 8, 2021, 4:14:25 PM2/8/21
to Kivy users support
I did something like x,y = self.to_local(touch.dx,touch.dy) and then used x and y insted of touch.dx and touch.dy this was the smoothest resizing so far, but yet not smooth as your code,, the last code you sent I tried to copy paste the widget again flied :D

Sadaka Technology

unread,
Feb 8, 2021, 4:16:33 PM2/8/21
to Kivy users support
I want to know why are all the sides getting affected,, I am getting mutiple red lines , must be something!! , rede lines are only used in on_touch_down, so why is it calling it frequently

Elliot Garbus

unread,
Feb 8, 2021, 4:24:00 PM2/8/21
to kivy-...@googlegroups.com

Are you using my most recent example?  I don’t see that issue.

Here is an update top and right now limited to parent size.

 

:
               
self.height = sorted([min_size, self.height + touch.dy, self.parent.height - (y - self.parent.y)])[1]
           
elif self.selected_side == 'bottom'
                
self.height -= touch.dy
               
self.y += touch.dy
                
self.y = max(self.to_widget(*self.parent.pos)[1], self.y)
           
elif self.selected_side == 'left':
               
self.x += touch.dx
               
self.width -= touch.dx
               
# self.x = min(self.parent.x, self.x)
           
elif self.selected_side == 'right':
               
self.width = sorted([min_size, self.width + touch.dx, self.parent.width - (x - self.parent.x)])[1]

       
return super().on_touch_move(touch)

   
def on_touch_up(self, touch):
       
if touch.grab_current is self:
            touch.ungrab(
self)
           
self.bottom_color = self.top_color = self.left_color = self.right_color = 'white'
           
return True
        return
super().on_touch_up(touch)


Sadaka Technology

unread,
Feb 8, 2021, 4:44:16 PM2/8/21
to Kivy users support
ofcourse I used your recent example

Sadaka Technology

unread,
Feb 8, 2021, 4:52:29 PM2/8/21
to Kivy users support
look your example is gridLayout with cols and rows, mine is diff due to maybe scrollview, I am ofcourse freezing the scrollview during resize , I will show you a pick of how it looks like, these are 2 windows inside  scrollview, rows=1 , and more windows I can add, you can see the blue rectangle which is a widget, in this blue rectangle I added the resize widget, with size equals to the size of the resize widget, I also tried to add the resize widget inside the bigger FloatLayout, same issue is following
11.jpg

Sadaka Technology

unread,
Feb 8, 2021, 5:07:19 PM2/8/21
to Kivy users support
I am sorry I couldn't make the code for my total example cuz it is very big, but this python file will explain all what I am doing.: another thing I dont know how to write code in google groups :D
Trial 10.py

Elliot Garbus

unread,
Feb 8, 2021, 6:16:02 PM2/8/21
to kivy-...@googlegroups.com

If you’d like more of my help – start with the example I sent and modify as little as possible to better reflect your use case.  I’m suggesting a way to create a minimal runnable example.  If you want to start with your code – that will work also. 

 

The scrollview is a complex widget – it is quite possible there are touch interactions going on with the widget and the scrollview.

 

You can paste code into the google groups by right clicking and selecting paste as text.

Sadaka Technology

unread,
Feb 9, 2021, 11:07:07 AM2/9/21
to Kivy users support
I will try adding the resize widget inside window inside horizontal scroll inside vertical scroll in your code

sersa...@outlook.com

unread,
Feb 10, 2021, 2:51:15 PM2/10/21
to kivy-...@googlegroups.com

That aint working bro, I tried all methods everythinf, this scrollview is disturbing all, it is applying multiple on touch down methods, we have to trick it in a way that on touch down can only be called once and released on touch up, I will try the variable method

Tuesday, 09 February 2021, 03:16AM +04:00 from Elliot Garbus elli...@cox.net:

If you’d like more of my help – start with the example I sent and modify as little as possible to better reflect your use case.  I’m suggesting a way to create a minimal runnable example.  If you want to start with your code – that will work also. 

 

The scrollview is a complex widget – it is quite possible there are touch interactions going on with the widget and the scrollview.

 

You can paste code into the google groups by right clicking and selecting paste as text.

 

 

 

From: Sadaka Technology
Sent: Monday, February 8, 2021 3:08 PM
To: Kivy users support
Subject: Re: RE: [kivy-users] simple dashed line

 

I am sorry I couldn't make the code for my total example cuz it is very big, but this python file will explain all what I am doing.: another thing I dont know how to write code in google groups :D

 

On Tuesday, February 9, 2021 at 1:52:29 AM UTC+4 Sadaka Technology wrote:

look your example is gridLayout with cols and rows, mine is diff due to maybe scrollview, I am ofcourse freezing the scrollview during resize , I will show you a pick of how it looks like, these are 2 windows inside  scrollview, rows=1 , and more windows I can add, you can see the blue rectangle which is a widget, in this blue rectangle I added the resize widget, with size equals to the size of the resize widget, I also tried to add the resize widget inside the bigger FloatLayout, same issue is following

On Tuesday, February 9, 2021 at 1:44:16 AM UTC+4 Sadaka Technology wrote:

ofcourse I used your recent example

On Tuesday, February 9, 2021 at 1:24:00 AM UTC+4 ElliotG wrote:

Are you using my most recent example?  I don’t see that issue.

Here is an update top and right now limited to parent size.

 

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.relativelayout import RelativeLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.properties import ColorProperty

import math

kv =
"""
"""
import math

kv =
"""
"""

Elliot Garbus

unread,
Feb 10, 2021, 3:55:45 PM2/10/21
to kivy-...@googlegroups.com

Touches get bubbled down to children, and across children.  I suspect the Scrollview is consuming touches.  You may want to consider an implementation that does not rely on this widget in a ScrollView.  You can try overloading the ScrollView on_touch methods to see if ScrollView is consuming the touches.

Sadaka Technology

unread,
Mar 14, 2021, 9:40:33 AM3/14/21
to Kivy users support
Dear Elliot G, I have been working on your example, everything turned ok, regarding resizing widget, the issue now is the bind, when I resize the widget through Float_resize class, it is all cool except if I increased the window size the widget goes back to its original position, but different size as I adjusted how can I fix that!

Elliot Garbus

unread,
Mar 17, 2021, 4:17:51 PM3/17/21
to kivy-...@googlegroups.com

I would look at binding to the Window size event.

Reply all
Reply to author
Forward
0 new messages