Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dpg.set_axis_limits just lock the axis min limit and let the max limit be free (+vice versa) #2016

Open
pwilliam123 opened this issue Jan 13, 2023 · 0 comments · May be fixed by #2275
Open
Labels
state: pending not addressed yet

Comments

@pwilliam123
Copy link

pwilliam123 commented Jan 13, 2023

Is your feature request related to a problem? Please describe.
I want to have a function that can set limit of axis boundary but still allow right click for drag zoom to change the axis freely without pass the set boundary. Basically, I want to have a graph that can only be zoom OUT to certain axis, but they can move/zoom IN to any values when right click for drag zoom and pan and middle scroll zoom. So to accomplish that, I will need to have a function (similar to set_axis_limit) that can lock min OR max only and allow the other limit be free.

NOTE: in the built in right click function, we can lock ONE side of the axis and other side still be able to move freely, so I believe there might be a function call for that?

Describe the solution you'd like
Allow axis limits to just lock the axis min limit and let the max limit be free (+vice versa) or possible to make dpg.set_axis_limits take in min or max only. In other words, I want to set the boundary of the plot axis, but still allow all the zoom/move feature as normal with out exceed the set boundary.

Describe alternatives you've considered
In the built in right click function, we can lock ONE side of the axis and other side still be able to move freely. So it can still be done by manually lock one side. But that feature cannot be implemented in the code due to set_axis_limits require both min and max

Additional context
Below is the current implementation for the features that was mentioned above, however, when it reaches the boundary axis (limit), the axis locked and cannot move freely anymore. For this example, I set the x axis boundary to [0, 200] and y boundary to [0, 1]. But it lock the zoon/move (Left click move) when it zoom/move to one/both side(s) of the axis boundary. If there a function to lock one side, then it will accomplish the task.

import dearpygui.dearpygui as dpg
from math import sin, cos

dpg.create_context()

sindatax = []
sindatay = []
for i in range(0, 200):
    sindatax.append(i )
    sindatay.append(0.5 + 0.5 * sin(50 * i / 1000))

Y_MAX = 1
Y_MIN = 0
X_MAX = 200
X_MIN = 0

with dpg.window(label="Tutorial", tag="win"):
    # create plot
    with dpg.plot(label="Line Series", height=400, width=400, tag='plot'):

        # REQUIRED: create x and y axes
        dpg.add_plot_axis(dpg.mvXAxis, label="x", tag = "x_axis")
        dpg.add_plot_axis(dpg.mvYAxis, label="y", tag="y_axis")
        
        # series belong to a y axis
        dpg.add_line_series(sindatax, sindatay, label="0.5 + 0.5 * sin(x)", parent="y_axis", tag="series_tag")
        dpg.set_axis_limits('x_axis', X_MIN, X_MAX)
        dpg.set_axis_limits('y_axis', Y_MIN, Y_MAX)

def right_click_drag_callback():
    dpg.set_axis_limits_auto('x_axis')
    dpg.set_axis_limits_auto('y_axis')

def right_click_release_callback():
    with dpg.mutex():
        xmin, xmax = dpg.get_axis_limits('x_axis')
        dpg.set_axis_limits('x_axis', xmin, xmax)

        ymin, ymax = dpg.get_axis_limits('y_axis')
        dpg.set_axis_limits('y_axis', ymin, ymax)

def wheel_callback(sender, data):

    if dpg.is_item_hovered('plot'):
        with dpg.mutex():
            if data < 0: # data < 0 means scroll down (i.e zoom out)
                dpg.set_axis_limits_auto('x_axis')
                xmin, xmax = dpg.get_axis_limits('x_axis')
                if xmax > X_MAX:
                    dpg.set_axis_limits('x_axis', xmin, X_MAX)
                elif xmin < X_MIN:
                    dpg.set_axis_limits('x_axis', X_MIN, xmax)

                dpg.set_axis_limits_auto('y_axis')
                ymin, ymax = dpg.get_axis_limits('y_axis')
                if ymax > Y_MAX:
                    dpg.set_axis_limits('y_axis', ymin, Y_MAX)
                elif ymin < Y_MIN:
                    dpg.set_axis_limits('y_axis', Y_MIN, ymax)

            else: # data >0 means scroll up (i.e zoom in)
                xmin, xmax = dpg.get_axis_limits('x_axis')
                if xmin >= X_MIN:
                    dpg.set_axis_limits_auto('x_axis')
                elif xmax <= X_MAX:
                    dpg.set_axis_limits_auto('x_axis')

                ymin, ymax = dpg.get_axis_limits('y_axis')
                if ymin >=Y_MIN:
                    dpg.set_axis_limits_auto('y_axis')
                elif ymax <= Y_MAX:
                    dpg.set_axis_limits_auto('y_axis')

def left_click_drag_callback(sender, data):
    dpg.set_axis_limits_auto('x_axis')
    xmin, xmax = dpg.get_axis_limits('x_axis')
    if xmax >= X_MAX:
        dpg.set_axis_limits('x_axis', xmin, X_MAX)
    elif xmin <= X_MIN:
        dpg.set_axis_limits('x_axis', X_MIN, xmax)

    dpg.set_axis_limits_auto('y_axis')
    ymin, ymax = dpg.get_axis_limits('y_axis')
    if ymax >= Y_MAX:
        dpg.set_axis_limits('y_axis', ymin, Y_MAX)
    elif ymin <= Y_MIN:
        dpg.set_axis_limits('y_axis', Y_MIN, ymax)

def double_click_callback(sender):
    dpg.fit_axis_data('x_axis')
    dpg.fit_axis_data('y_axis')

with dpg.handler_registry():
    dpg.add_mouse_drag_handler(button=dpg.mvMouseButton_Right, callback=right_click_drag_callback)
    dpg.add_mouse_drag_handler(button=dpg.mvMouseButton_Left, callback=left_click_drag_callback)
    dpg.add_mouse_double_click_handler(button=dpg.mvMouseButton_Left, callback =double_click_callback )
    dpg.add_mouse_release_handler(button=dpg.mvMouseButton_Right, callback=right_click_release_callback)
    dpg.add_mouse_wheel_handler(callback=wheel_callback)


dpg.create_viewport(title='Custom Title', width=800, height=600)
dpg.setup_dearpygui()
dpg.show_viewport()
dpg.start_dearpygui()
dpg.destroy_context()
@pwilliam123 pwilliam123 added the state: pending not addressed yet label Jan 13, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
state: pending not addressed yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant