B4J Question Drag the buttons - Invert buttons

WebQuest

Active Member
Licensed User
Hello Community,
I'm having trouble developing a function for my program. The problem is, I can't find a solution to swap any button dragged to another button. I am using the MouseDragged and MousePressed event to drag buttons to other locations, but I also wish that when a button is dragged to another button the dus swap positions. Anyone have any solutions? Any example will be appreciated.

1639881685261.png
 

EnriqueGonzalez

Well-Known Member
Licensed User
Longtime User
May be this library could help.
But i don't remember if it works with nodes sorry
 
Upvote 0

WebQuest

Active Member
Licensed User
Hello EnriqueGonzalez,
Grayie for the answer !. But currently I can already move the buttons, what I need is to be able to scale the position of the buttons when I add a dragged button.
 
Upvote 0

stevel05

Expert
Licensed User
Longtime User
The buttons all look identical in layout so it depends how you have set up the buttons, rather than actually moving the buttons, it would be simpler if you just change the text and tag if necessary for the source and target buttons when the dragged item is dropped.

This assumes that you have one click event for all buttons and are identifying the button clicked by it's text or tag.

If you are unsure of how to do this, attach an example project so we can see how you have set up the buttons.
 
Upvote 0

WebQuest

Active Member
Licensed User
I'm using Erel's example at this link to move the buttons.
Link: Example

Move Button:
Sub Process_Globals
   Private fx As JFX
   Private MainForm As Form
   Type PositionData (PressedX As Int, PressedY As Int)
   Private Button1 As Button
End Sub

Sub AppStart (Form1 As Form, Args() As String)
   MainForm = Form1
   MainForm.RootPane.LoadLayout("1") 'Load the layout file.
   MainForm.Show
End Sub

Sub Button1_MouseDragged (EventData As MouseEvent)
   Dim view As B4XView = Sender
   Dim pd As PositionData = view.Tag
   Dim ParentX As Int = EventData.X + view.Left
   Dim ParentY As Int = EventData.Y + view.Top
   view.Left = ParentX - pd.PressedX
   view.Top = ParentY - pd.PressedY
End Sub

Sub Button1_MousePressed (EventData As MouseEvent)
   Dim view As B4XView = Sender
   Dim pd As PositionData
   pd.PressedX = EventData.X
   pd.PressedY = EventData.Y
   view.Tag = pd
End Sub
 
Upvote 0

stevel05

Expert
Licensed User
Longtime User
That only has one button, you have 15, what we need to know is
  • How all of the buttons are set up.
  • How you are determining which button is to be replaced.
  • How you are going about replacing it.

If you can zip and post your project, it will allow me to confirm that my suggested solution is appropriate for your problem or not and save me having to write a whole new project to demonstrate it.
 
Upvote 0

ilan

Expert
Licensed User
Longtime User
i made few months ago a simple drag and drop example. not with button but with canvas where you draw everything. it may help you.

 
Upvote 0

WebQuest

Active Member
Licensed User
Ilano this effect is fantastic I will add it. But I didn't make myself clear! I need that when I move ex. BT1 on BT2 these have to change places. I tried to insert if then, but it is too long to write, there are too many cases with 15 buttons. I was looking for a solution that always works.
 
Upvote 0

WebQuest

Active Member
Licensed User
I've created an example of what I need! By dragging the BT1 to BT2 the two have to change places. Now I have used a simple if then code, but I need a solution that works with 15 buttons.
 

Attachments

  • ezgif.com-gif-maker.gif
    ezgif.com-gif-maker.gif
    420.9 KB · Views: 177
Upvote 0

ilan

Expert
Licensed User
Longtime User
I tried to insert if then, but it is too long to write

? ? ? No, No , No !!! This is the worst idea you could have.

just modified a little bit my code and i think i get what you want:


TIP: when we make the Recursive check for all views you can use any other technique. like checking if TAG value is the same or stuff like that. so instead of checking if the node is a button you could add 10 buttons with tag value "dragme" and then make the check if the node.tag = "dragme" :)

EDIT: after watching the video i saw a small bug where the returned button (touchedbutton) is not scale back. it should very simple to be to fix it. i just need to get to work. will check if later. (FIXED)
 

Attachments

  • button drag 2.zip
    3.1 KB · Views: 197
Last edited:
Upvote 0

WebQuest

Active Member
Licensed User
Great, but I have a problem your code is not working for me. I am using a PanelSchermoTab2 to accommodate the buttons.
What am I doing wrong? I put the panel in place of MainForm.RootPanel but nothing works?
B4X:
Sub PanelSchermoTab2_Touch (Action As Int, X As Float, Y As Float)
        Select Action
        Case 0 'down
            touchedButton = checkifbuttonpressed(X,Y,False)
        Case 1 'up
            If touchedButton.IsInitialized Then
                If checkifbuttonpressed(X,Y,True).IsInitialized Then
                    changedButton = checkifbuttonpressed(X,Y,True)
                    Dim changebPoint As point = Createpoint(changedButton.Left, changedButton.Top)
                    changedButton.SetLayoutAnimated(200,lastPosition.x,lastPosition.y,buttonOrgSize.width,buttonOrgSize.height) 'move the changebuton to touchbutton position
                    touchedButton.SetLayoutAnimated(200,changebPoint.x,changebPoint.y,buttonOrgSize.width,buttonOrgSize.height) 'stick the touched button
                Else
                    touchedButton.SetLayoutAnimated(200,lastPosition.x,lastPosition.y,buttonOrgSize.width,buttonOrgSize.height) 'return touchedbutton to his origin
                End If
            End If
            touchedButton = Null
        Case 2 'moving
            If touchedButton.IsInitialized Then
                touchedButton.Left = X - difference.x
                touchedButton.top = Y - difference.y
            End If
    End Select

End Sub


Sub PanelSchermoTab_Touch (Action As Int, X As Float, Y As Float)


Private Sub checkifbuttonpressed(x As Float, y As Float, skipTouchedButton As Boolean) As Button
    For Each v As Node In B4XPages.MainPage.PanelSchermoTab2.GetAllViewsRecursive
        If v Is Button Then
            Dim b As Button = v
            If x > b.Left And y > b.Top And x < b.Left+b.Width And y < b.Top + b.Height Then
                If skipTouchedButton Then
                    If b = touchedButton Then Continue 'skip tocuhedbutton check
                Else
                     lastPosition = Createpoint(b.Left,b.Top)
                End If
                BringToFront(b)
                Dim scale As Float = 20dip
                difference = Createpoint(x-b.Left+scale, y-b.Top+scale)
                b.SetLayoutAnimated(50,b.Left-scale,b.Top-scale,b.Width+(scale*2),b.Height+(scale*2))
                Return b
            End If           
        End If
    Next
    Return Null
End Sub

Sub BringToFront(n As Node)
    Dim parent As Pane = n.Parent
    n.RemoveNodeFromParent
    parent.AddNode(n, n.Left, n.Top, n.PrefWidth, n.PrefHeight)
End Sub



Public Sub Createpoint (x As Float, y As Float) As point
    Dim t1 As point
    t1.Initialize
    t1.x = x
    t1.y = y
    Return t1
End Sub


Public Sub Createsize (width As Float, height As Float) As size
    Dim t1 As size
    t1.Initialize
    t1.width = width
    t1.height = height
    Return t1
End Sub
 
Upvote 0

ilan

Expert
Licensed User
Longtime User
but I have a problem your code is not working for me
if you try my example it is also not working for you?
it is really hard to understand what is wrong on your side without enough information.

as @DonManfred already wrote the best way to understand the issue on the other side is to try the same example they are running.
without seeing the code we cannot help much.
 
Upvote 0

WebQuest

Active Member
Licensed User
Sorry, here's the code. I believe it doesn't work because I am using the B4XPages base.

B4X:
Sub Class_Globals
    Private Root As B4XView
    Private xui As XUI
    Type point(x As Float, y As Float)
    Type size(width As Float, height As Float)
    Private touchedButton, changedButton As Button
    Private lastPosition, difference As point
    Private buttonOrgSize As size
    Private Button1 As Button
    Private Pane1 As Pane
End Sub

Public Sub Initialize
    
End Sub

'This event will be called once, before the page becomes visible.
Private Sub B4XPage_Created (Root1 As B4XView)
    Root = Root1
    Root.LoadLayout("MainPage")
    buttonOrgSize = Createsize(Button1.Width,Button1.Height) 'set the init size of the button
End Sub

'You can see the list of page related events in the B4XPagesManager object. The event name is B4XPage.

Sub Button1_Click
    xui.MsgboxAsync("Hello world!", "B4X")
End Sub


Private Sub MainForm_Touch (Action As Int, X As Float, Y As Float)
    Select Action
        Case 0 'down
            touchedButton = checkifbuttonpressed(X,Y,False)
        Case 1 'up
            If touchedButton.IsInitialized Then
                If checkifbuttonpressed(X,Y,True).IsInitialized Then
                    changedButton = checkifbuttonpressed(X,Y,True)
                    Dim changebPoint As point = Createpoint(changedButton.Left, changedButton.Top)
                    changedButton.SetLayoutAnimated(200,lastPosition.x,lastPosition.y,buttonOrgSize.width,buttonOrgSize.height) 'move the changebuton to touchbutton position
                    touchedButton.SetLayoutAnimated(200,changebPoint.x,changebPoint.y,buttonOrgSize.width,buttonOrgSize.height) 'stick the touched button
                Else
                    touchedButton.SetLayoutAnimated(200,lastPosition.x,lastPosition.y,buttonOrgSize.width,buttonOrgSize.height) 'return touchedbutton to his origin
                End If
            End If
            touchedButton = Null
        Case 2 'moving
            If touchedButton.IsInitialized Then
                touchedButton.Left = X - difference.x
                touchedButton.top = Y - difference.y
            End If
    End Select
End Sub

Private Sub checkifbuttonpressed(x As Float, y As Float, skipTouchedButton As Boolean) As Button
    For Each v As Node In Main.MainForm.RootPane.GetAllViewsRecursive
        If v Is Button Then
            Dim b As Button = v
            If x > b.Left And y > b.Top And x < b.Left+b.Width And y < b.Top + b.Height Then
                If skipTouchedButton Then
                    If b = touchedButton Then Continue 'skip tocuhedbutton check
                Else
                    lastPosition = Createpoint(b.Left,b.Top)
                End If
                BringToFront(b)
                Dim scale As Float = 20dip
                difference = Createpoint(x-b.Left+scale, y-b.Top+scale)
                b.SetLayoutAnimated(50,b.Left-scale,b.Top-scale,b.Width+(scale*2),b.Height+(scale*2))
                Return b
            End If
        End If
    Next
    Return Null
End Sub

Sub BringToFront(n As Node)
    Dim parent As Pane = n.Parent
    n.RemoveNodeFromParent
    parent.AddNode(n, n.Left, n.Top, n.PrefWidth, n.PrefHeight)
End Sub

Public Sub Createpoint (x As Float, y As Float) As point
    Dim t1 As point
    t1.Initialize
    t1.x = x
    t1.y = y
    Return t1
End Sub
 
Public Sub Createsize (width As Float, height As Float) As size
    Dim t1 As size
    t1.Initialize
    t1.width = width
    t1.height = height
    Return t1
End Sub
 
Upvote 0

klaus

Expert
Licensed User
Longtime User
Why do you not post the project !?
It would be much easier for helpers, because we could directly test solutions and give a concrete advice to your problem.
As your project is a B4XPages project you should zip it by clicking with Ctrl on this line on top or the B4XMainPage module.

1640000860035.png
 
Upvote 0

WebQuest

Active Member
Licensed User
This is the project in which I am testing the code. I changed the Root and created the Pane1_Touch event. But it doesn't work as it should.

Code:
Sub Class_Globals
    Private Root As B4XView
    Private xui As XUI
    Type point(x As Float, y As Float)
    Type size(width As Float, height As Float)
    Private touchedButton, changedButton As Button
    Private lastPosition, difference As point
    Private buttonOrgSize As size
    Private Button1 As Button
    Private Pane1 As Pane
End Sub

Public Sub Initialize
    
End Sub

'This event will be called once, before the page becomes visible.
Private Sub B4XPage_Created (Root1 As B4XView)
    Root = Root1
    Root.LoadLayout("MainPage")
    buttonOrgSize = Createsize(Button1.Width,Button1.Height) 'set the init size of the button
End Sub

'You can see the list of page related events in the B4XPagesManager object. The event name is B4XPage.

Sub Button1_Click
    xui.MsgboxAsync("Hello world!", "B4X")
End Sub


Private Sub Pane1_Touch (Action As Int, X As Float, Y As Float)
    Select Action
        Case 0 'down
            touchedButton = checkifbuttonpressed(X,Y,False)
        Case 1 'up
            If touchedButton.IsInitialized Then
                If checkifbuttonpressed(X,Y,True).IsInitialized Then
                    changedButton = checkifbuttonpressed(X,Y,True)
                    Dim changebPoint As point = Createpoint(changedButton.Left, changedButton.Top)
                    changedButton.SetLayoutAnimated(200,lastPosition.x,lastPosition.y,buttonOrgSize.width,buttonOrgSize.height) 'move the changebuton to touchbutton position
                    touchedButton.SetLayoutAnimated(200,changebPoint.x,changebPoint.y,buttonOrgSize.width,buttonOrgSize.height) 'stick the touched button
                Else
                    touchedButton.SetLayoutAnimated(200,lastPosition.x,lastPosition.y,buttonOrgSize.width,buttonOrgSize.height) 'return touchedbutton to his origin
                End If
            End If
            touchedButton = Null
        Case 2 'moving
            If touchedButton.IsInitialized Then
                touchedButton.Left = X - difference.x
                touchedButton.top = Y - difference.y
            End If
    End Select
End Sub

Private Sub checkifbuttonpressed(x As Float, y As Float, skipTouchedButton As Boolean) As Button
    For Each v As Node In B4XPages.MainPage.Root.GetAllViewsRecursive
        If v Is Button Then
            Dim b As Button = v
            If x > b.Left And y > b.Top And x < b.Left+b.Width And y < b.Top + b.Height Then
                If skipTouchedButton Then
                    If b = touchedButton Then Continue 'skip tocuhedbutton check
                Else
                    lastPosition = Createpoint(b.Left,b.Top)
                End If
                BringToFront(b)
                Dim scale As Float = 20dip
                difference = Createpoint(x-b.Left+scale, y-b.Top+scale)
                b.SetLayoutAnimated(50,b.Left-scale,b.Top-scale,b.Width+(scale*2),b.Height+(scale*2))
                Return b
            End If
        End If
    Next
    Return Null
End Sub

Sub BringToFront(n As Node)
    Dim parent As Pane = n.Parent
    n.RemoveNodeFromParent
    parent.AddNode(n, n.Left, n.Top, n.PrefWidth, n.PrefHeight)
End Sub

Public Sub Createpoint (x As Float, y As Float) As point
    Dim t1 As point
    t1.Initialize
    t1.x = x
    t1.y = y
    Return t1
End Sub
 
Public Sub Createsize (width As Float, height As Float) As size
    Dim t1 As size
    t1.Initialize
    t1.width = width
    t1.height = height
    Return t1
End Sub
 

Attachments

  • Project.zip
    9.6 KB · Views: 145
  • ezgif.com-gif-maker.gif
    ezgif.com-gif-maker.gif
    145.4 KB · Views: 164
Upvote 0
Top