Skip to content

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

Closed
@pwilliam123

Description

@pwilliam123

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()

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions