B4J Question xGantt class. Duration of tasks by ours instead of days .

javiers

Active Member
Licensed User
Longtime User
Is it possible to have the duration of tasks by hours?
xGantt class is great ( @klaus ), but I wish the duration could be expressed in hours (1...24) for each day.

I would appreciate the help.
 
Last edited:
Solution
Attached version 0.98.
Tested with B4J and B4A, not B4i yet.
Please test it, and when it works also for you, i will then publish it as b4xlib Library.

1725538982516.png


What you can do:
- Change the texts, adapt them to your language.

1725539001620.png


- Hide the ID and or the Responsible column.

1725539028692.png


- When you click on a row and move the mouse, the data of that row is displayed.

1725539094854.png


- When you click on an arrow, the diagram jumps to show the beginning of the task or group.

1725539715813.png
1725539736172.png


- You can take a snapshot of the current display with the Snapshot method which returns a B4XBitmap.

EDIT 2024.09.13
I have removed the zip file.
You find the latest version in the xGanttLite thread.

klaus

Expert
Licensed User
Longtime User
You may have seen that that in the last version the begin and end times must be added with Tick values, but you have String values.
Before you make too many changes in your project, I now made two add methods AddTaskDates and AddTaskTicks, one with dates and another one with Ticks to make things easier.

You find the latest version in the xGanttLite thread.
 
Last edited:
Upvote 0

klaus

Expert
Licensed User
Longtime User
Attached version 0.98.
Tested with B4J and B4A, not B4i yet.
Please test it, and when it works also for you, i will then publish it as b4xlib Library.

1725538982516.png


What you can do:
- Change the texts, adapt them to your language.

1725539001620.png


- Hide the ID and or the Responsible column.

1725539028692.png


- When you click on a row and move the mouse, the data of that row is displayed.

1725539094854.png


- When you click on an arrow, the diagram jumps to show the beginning of the task or group.

1725539715813.png
1725539736172.png


- You can take a snapshot of the current display with the Snapshot method which returns a B4XBitmap.

EDIT 2024.09.13
I have removed the zip file.
You find the latest version in the xGanttLite thread.
 

Attachments

  • 1725539435203.png
    1725539435203.png
    41.2 KB · Views: 124
Last edited:
Upvote 1
Solution

javiers

Active Member
Licensed User
Longtime User
Attached version 0.98.
Tested with B4J and B4A, not B4i yet.
Please test it, and when it works also for you, i will then publish it as b4xlib Library.

View attachment 156627

What you can do:
- Change the texts, adapt them to your language.

View attachment 156628

- Hide the ID and or the Responsible column.

View attachment 156629

- When you click on a row and move the mouse, the data of that row is displayed.

View attachment 156630 View attachment 156632

- When you click on an arrow, the diagram jumps to show the beginning of the task or group.

View attachment 156633 View attachment 156634

- You can take a snapshot of the current display with the Sbapshot method which returns a B4XBitmap.
Tested for B4J and B4A. Works perfectly! I don't have an iPhone.
It has more than I would have expected.
Your work and how you solve it is impressive.
Thank you so much, not only for the final result, but also for the dedication with which you have done this work (I suppose that in your daily life you have more important things to do...).
I'm sure that the library will be super useful for many more people.šŸ’Æ
 
Upvote 0

klaus

Expert
Licensed User
Longtime User
Could this be interesting for you ?

Select a Task.
1725558673826.png

1725558739736.png


Move a cursor, begin time, end time or move the task. End time in the example.
1725558770745.png


And validate.
1725558781895.png


For the moment it is at a state of demonstrator.
Will need some more time.
The next two days no time for B4X.

I suppose that in your daily life you have more important things to do...
Sure I do also this, via ferrata, probably again tomorrow morning:

1725560325441.png


And your project was a kind of challenge for me and i like doing this.
 
Upvote 0

javiers

Active Member
Licensed User
Longtime User
Could this be interesting for you ?

Select a Task.
View attachment 156636
View attachment 156637

Move a cursor, begin time, end time or move the task. End time in the example.
View attachment 156638

And validate.
View attachment 156639

For the moment it is at a state of demonstrator.
Will need some more time.
The next two days no time for B4X.


Sure I do also this, via ferrata, probably again tomorrow morning:

View attachment 156640

And your project was a kind of challenge for me and i like doing this.
Very interesting! It goes from being a viewer that displays information to being interactive for the user. It is a qualitative leap.
 
Upvote 0

amorosik

Expert
Licensed User
Could this be interesting for you ?

I believe that allowing interactively the insertion of a task and its modification of start, end, would make this example of great value and great utility for all the forum participants
I greatly envy the skills of Klaus, Erel, and all the big names present in these forums, fortunately they are a great inspiration for all of us of the 'minor league'
 
Upvote 0

javiers

Active Member
Licensed User
Longtime User
I have placed a timer that updates the graph every so often. When it is redrawn, the horizontal scroll moves to the beginning. Would it be possible to move it, I understand by code, to the end, or to show the red NOW line?
This would make it easier for the user not to have to constantly scroll the graph to see the current moment.
Thanks again for your work!

1725732968323.png
 
Upvote 0

klaus

Expert
Licensed User
Longtime User
Attached you find version 0.99.
It includes several Jump methods:
JumpToBegin
JumpToEnd
JumpToNow
JumpToDate(Ticks)
JumpToDate2(String)
And you can now also jump to the beginning or the end in the scrollbars.
1725810641027.png
1725810653169.png


The task editing is still a work in progress.

1725809947527.png


Do a long click on a task and you get this:
1725809992290.png


When you click on one of three lines you can either expand the task to the right, to the left or move it:
1725810108927.png

1725810129857.png


With the middle line move the task:
1725809947527.png

1725810211284.png


1725810235041.png


All this needs still some work to fine tune every thing.

EDIT 2024.09.13
I have removed the zip file.
You find the latest version in the xGanttLite thread.
 
Last edited:
Upvote 0

klaus

Expert
Licensed User
Longtime User
Attached you fing version 0.99.
I anticipated the first wish which would have been asked if i had already published this class.
Having the scales not only in hours but also in days.

Hours:
1726224786385.png


Days large:

1726224812104.png


Days small:

1726224843629.png


You can select the scale directly on the chart with the three buttons in the lower left corner:

1726224991457.png


The selection for the editing with the mouse is now with a double click instead of a long click.
It is not yet fine tuned, there are some details to improve.
What is still missing:
- The editing of an entry, changing the name, ID, color etc.
- Add, insert or remove an entry.
- Generate a text file with all words used, a few are already done but with the editing there will be longer texts.
This will be added quite soon and then i will publish it as a b4xlib library.

I have for sure not tested everything, therefore bug reports are welcome.

EDIT 2024.09.22
I have removed the zip file.
You find the latest version in the xGanttLite thread.
 
Last edited:
Upvote 0

javiers

Active Member
Licensed User
Longtime User
Your work is still impressive. šŸ„‡
Viewing by day or hour is great. I wouldn't have thought of that, honestly.
Double-click editing works much better now.
And what's coming will give the library a lot of power. šŸ’Ŗ
I'll keep trying it, but I can tell you that I won't find many or any errors. For me, the different versions are fully functional.
Thanks again for everything!!
 
Upvote 0

amorosik

Expert
Licensed User
Attached you fing version 0.99.
I anticipated the first wish which would have been asked if i had already published this class.
Having the scales not only in hours but also in days.
....
I have for sur not tested everything, therefore bug reports are welcome.

Now that the gantt is almost complete, you could focus on the next project:
"e-commerce for everyone" . šŸ˜‡

Jokes aside, the basic structure of an e-commerce, which can then be modified as each of us likes, I think is a universally appealing project for anyone
 
Upvote 0

amorosik

Expert
Licensed User
It was just a nice way to ask if you wanted to get involved with another project like e-commerce
Yes, I mean a system that can be consulted via the web
My request was motivated by the fact that all the e-commerce systems available (Magento, Prestashop, NopCommerce...) are very complex systems
And above all very difficult to modify and interface with the outside
Being able to create a system of low-medium complexity would allow many of us to study the code and adapt it to our needs
 
Upvote 0

javiers

Active Member
Licensed User
Longtime User
Hello, an error occurs when scrolling vertically (in my case using the mouse wheel).
B4J:
WARNING: package com.sun.javafx.embed.swing.oldimpl not in javafx.swing
Waiting for debugger to connect...
Program started.
Call B4XPages.GetManager.LogEvents = True to enable logging B4XPages events.
Error occurred on line: 450 (xGanttLite)
java.lang.IndexOutOfBoundsException: Index 25 out of bounds for length 25
    at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:100)
    at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:106)
    at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:302)
    at java.base/java.util.Objects.checkIndex(Objects.java:385)
    at java.base/java.util.ArrayList.get(ArrayList.java:427)
    at anywheresoftware.b4a.objects.collections.List.Get(List.java:122)
    at b4j.xGanttLiteDemo.xganttlite._drawfixedcolumnsdata(xganttlite.java:2347)
    at b4j.xGanttLiteDemo.xganttlite._drawfixedcolumns(xganttlite.java:2130)
    at b4j.xGanttLiteDemo.xganttlite._redrawgantt(xganttlite.java:887)
    at b4j.xGanttLiteDemo.xganttlite._cvscursor_filter(xganttlite.java:1271)
    at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
    at java.base/java.lang.reflect.Method.invoke(Method.java:578)
    at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:629)
    at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:234)
    at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:167)
    at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
    at java.base/java.lang.reflect.Method.invoke(Method.java:578)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:111)
    at anywheresoftware.b4a.shell.ShellBA.raiseEvent2(ShellBA.java:100)
    at anywheresoftware.b4a.BA.raiseEvent(BA.java:98)
    at anywheresoftware.b4j.agraham.reflection.Reflection$3.handle(Reflection.java:243)
    at javafx.base/com.sun.javafx.event.CompositeEventHandler$NormalEventFilterRecord.handleCapturingEvent(CompositeEventHandler.java:321)
    at javafx.base/com.sun.javafx.event.CompositeEventHandler.dispatchCapturingEvent(CompositeEventHandler.java:98)
    at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchCapturingEvent(EventHandlerManager.java:221)
    at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchCapturingEvent(EventHandlerManager.java:180)
    at javafx.base/com.sun.javafx.event.CompositeEventDispatcher.dispatchCapturingEvent(CompositeEventDispatcher.java:43)
    at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:52)
    at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at javafx.base/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
    at javafx.base/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
    at javafx.base/javafx.event.Event.fireEvent(Event.java:198)
    at javafx.graphics/javafx.scene.Scene.processGestureEvent(Scene.java:1956)
    at javafx.graphics/javafx.scene.Scene$ScenePeerListener.scrollEvent(Scene.java:2701)
    at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleScrollEvent$5(GlassViewEventHandler.java:543)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
    at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleScrollEvent$6(GlassViewEventHandler.java:523)
    at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:424)
    at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.handleScrollEvent(GlassViewEventHandler.java:522)
    at javafx.graphics/com.sun.glass.ui.View.notifyScroll(View.java:965)
    at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:184)
    at java.base/java.lang.Thread.run(Thread.java:1589)
 
Upvote 0

klaus

Expert
Licensed User
Longtime User
Sorry, but i cannot reproduce this error.
It looks strange to me because in the code i check the values.
Can you please explain in what conditions the error happens.
During a fast scroll ?
How many rows do you have ?
Is it with version 0.991 ?
 
Last edited:
Upvote 0

javiers

Active Member
Licensed User
Longtime User
Hello, yes it is version 0.991. I run your example. If the cursor is inside the control, if I move the mouse wheel down, the error occurs.
I haven't added or modified anything from your example...

B4X:
WARNING: package com.sun.javafx.embed.swing.oldimpl not in javafx.swing
Waiting for debugger to connect...
Program started.
Call B4XPages.GetManager.LogEvents = True to enable logging B4XPages events.
Error occurred on line: 450 (xGanttLite)
java.lang.IndexOutOfBoundsException: Index 25 out of bounds for length 25
    at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:100)
    at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:106)
    at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:302)
    at java.base/java.util.Objects.checkIndex(Objects.java:385)
    at java.base/java.util.ArrayList.get(ArrayList.java:427)
    at anywheresoftware.b4a.objects.collections.List.Get(List.java:122)
    at b4j.xGanttLiteDemo.xganttlite._drawfixedcolumnsdata(xganttlite.java:2347)
    at b4j.xGanttLiteDemo.xganttlite._drawfixedcolumns(xganttlite.java:2130)
    at b4j.xGanttLiteDemo.xganttlite._redrawgantt(xganttlite.java:887)
    at b4j.xGanttLiteDemo.xganttlite._cvscursor_filter(xganttlite.java:1271)
    at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
    at java.base/java.lang.reflect.Method.invoke(Method.java:578)
    at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:629)
    at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:234)
    at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:167)
    at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
    at java.base/java.lang.reflect.Method.invoke(Method.java:578)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:111)
    at anywheresoftware.b4a.shell.ShellBA.raiseEvent2(ShellBA.java:100)
    at anywheresoftware.b4a.BA.raiseEvent(BA.java:98)
    at anywheresoftware.b4j.agraham.reflection.Reflection$3.handle(Reflection.java:243)
    at javafx.base/com.sun.javafx.event.CompositeEventHandler$NormalEventFilterRecord.handleCapturingEvent(CompositeEventHandler.java:321)
    at javafx.base/com.sun.javafx.event.CompositeEventHandler.dispatchCapturingEvent(CompositeEventHandler.java:98)
    at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchCapturingEvent(EventHandlerManager.java:221)
    at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchCapturingEvent(EventHandlerManager.java:180)
    at javafx.base/com.sun.javafx.event.CompositeEventDispatcher.dispatchCapturingEvent(CompositeEventDispatcher.java:43)
    at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:52)
    at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at javafx.base/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
    at javafx.base/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
    at javafx.base/javafx.event.Event.fireEvent(Event.java:198)
    at javafx.graphics/javafx.scene.Scene.processGestureEvent(Scene.java:1956)
    at javafx.graphics/javafx.scene.Scene$ScenePeerListener.scrollEvent(Scene.java:2701)
    at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleScrollEvent$5(GlassViewEventHandler.java:543)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
    at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleScrollEvent$6(GlassViewEventHandler.java:523)
    at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:424)
    at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.handleScrollEvent(GlassViewEventHandler.java:522)
    at javafx.graphics/com.sun.glass.ui.View.notifyScroll(View.java:965)
    at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:184)
    at java.base/java.lang.Thread.run(Thread.java:1589)
Error occurred on line: 450 (xGanttLite)
java.lang.NullPointerException: Cannot invoke "java.lang.reflect.Method.invoke(Object, Object[])" because "data.method" is null
    at anywheresoftware.b4a.shell.Shell.runGoodChain(Shell.java:370)
    at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:181)
    at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:167)
    at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
    at java.base/java.lang.reflect.Method.invoke(Method.java:578)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:111)
    at anywheresoftware.b4a.shell.ShellBA.raiseEvent2(ShellBA.java:100)
    at anywheresoftware.b4a.BA.raiseEvent(BA.java:98)
    at anywheresoftware.b4j.agraham.reflection.Reflection$3.handle(Reflection.java:243)
    at javafx.base/com.sun.javafx.event.CompositeEventHandler$NormalEventFilterRecord.handleCapturingEvent(CompositeEventHandler.java:321)
    at javafx.base/com.sun.javafx.event.CompositeEventHandler.dispatchCapturingEvent(CompositeEventHandler.java:98)
    at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchCapturingEvent(EventHandlerManager.java:221)
    at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchCapturingEvent(EventHandlerManager.java:180)
    at javafx.base/com.sun.javafx.event.CompositeEventDispatcher.dispatchCapturingEvent(CompositeEventDispatcher.java:43)
    at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:52)
    at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at javafx.base/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
    at javafx.base/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
    at javafx.base/javafx.event.Event.fireEvent(Event.java:198)
    at javafx.graphics/javafx.scene.Scene.processGestureEvent(Scene.java:1956)
    at javafx.graphics/javafx.scene.Scene$ScenePeerListener.scrollEvent(Scene.java:2701)
    at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleScrollEvent$5(GlassViewEventHandler.java:543)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
    at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleScrollEvent$6(GlassViewEventHandler.java:523)
    at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:424)
    at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.handleScrollEvent(GlassViewEventHandler.java:522)
    at javafx.graphics/com.sun.glass.ui.View.notifyScroll(View.java:965)
    at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:184)
    at java.base/java.lang.Thread.run(Thread.java:1589)

1726394213015.png



1726394165936.png
 
Upvote 0

klaus

Expert
Licensed User
Longtime User
I get it too now.
I had not tested the scrolling when there is no vertical scrollbar.
Amended in version 0.992

In the mean time you could modify the cvsCursor_Filter sub routine like this:

B4X:
Private Sub cvsCursor_Filter(E As Event)
    Private MouseEvent As JavaObject = E
    Private Delta As Int
    
    If ScrollV.Active = True Then
        Delta = MouseEvent.RunMethod("getDeltaY",Null)
        If Delta > 0 Then
            If ScrollV.BeginIndex > 0 Then
                ScrollV.BeginIndex = ScrollV.BeginIndex - 1
            End If
        Else If Delta < 0 Then
            If ScrollV.EndIndex < Rows.Size - 1 Then
                ScrollV.BeginIndex = ScrollV.BeginIndex + 1
            End If
        End If
        ScrollV.EndIndex = ScrollV.BeginIndex + NbRowsVisible - 1
        ReDrawGantt
        ScrollCursorDrawV
    End If
End Sub
 
Upvote 0
Top