Захват и перетаскивание прокрутки на JPanel, заполненной нарисованными фигурами

#java #swing #jpanel

#java #качать #jpanel

Вопрос:

Хорошо, итак, я создал эту JPanel, заполненную шестиугольниками 20 x 20 в форме ромба. Они довольно большие, поэтому вы не можете видеть их все одновременно, но поскольку предполагается, что это карта в игре, я хотел бы использовать прокрутку grab’n’drag.

Фактическое перемещение работает — но когда я перемещаю панель, я удаляю только те плитки, которые я уже мог видеть, плитки, которые должны быть сразу за границами окна, не отображаются. Это похоже на то, что я перемещаю изображение. Однако, если я изменю размер окна, я смогу увидеть больше шестиугольников.

Я пытался принудительно перерисовывать после завершения mouseDragged, но безуспешно. Любой, у кого есть какие-либо идеи, очень рад поделиться ими!

Здесь я показываю все в интерфейсном классе:

             ComponentMover comp = new ComponentMover();
        comp.registerComponent(gameTiles,this);
        main.add(gameTiles, "Game");
        cardLayout.show(main, "Game");
  

и это ComponentMover-класс (заимствованный из http://tips4java.wordpress.com/2009/06/14/moving-windows с несколькими модами)

открытый класс ComponentMover расширяет MouseAdapter {

 private Class destinationClass;
private Component destinationComponent;
private Component destination;
private Component source;

private ArrayList<Component>comps;

private boolean changeCursor = true;

private Point pressed;
private Point location;

private Cursor originalCursor;
private boolean autoscrolls;

private Insets dragInsets = new Insets(0, 0, 0, 0);
private Dimension snapSize = new Dimension(1, 1);

/**
 *  Constructor for moving individual components. The components must be
 *  regisetered using the registerComponent() method.
 */
public ComponentMover()
{ comps = new ArrayList<Component>();
}

/**
 *  Constructor to specify a Class of Component that will be moved when
 *  drag events are generated on a registered child component. The events
 *  will be passed to the first ancestor of this specified class.
 *
 *  @param destinationClass  the Class of the ancestor component
 *  @param component         the Components to be registered for forwarding
 *                           drag events to the ancestor Component.
 */
public ComponentMover(Class destinationClass, Component... components)
{
    this.destinationClass = destinationClass;
    registerComponent( components );
}

/**
 *  Constructor to specify a parent component that will be moved when drag
 *  events are generated on a registered child component.
 *
 *  @param destinationComponent  the component drage events should be forwareded to
 *  @param components    the Components to be registered for forwarding drag
 *                       events to the parent component to be moved
 */
public ComponentMover(Component destinationComponent, Component... components)
{
    this.destinationComponent = destinationComponent;
    registerComponent( components );
}

/**
 *  Get the change cursor property
 *
 *  @return  the change cursor property
 */
public boolean isChangeCursor()
{
    return changeCursor;
}

/**
 *  Set the change cursor property
 *
 *  @param  changeCursor when true the cursor will be changed to the
 *                       Cursor.MOVE_CURSOR while the mouse is pressed
 */
public void setChangeCursor(boolean changeCursor)
{
    this.changeCursor = changeCursor;
}

/**
 *  Get the drag insets
 *
 *  @return  the drag insets
 */
public Insets getDragInsets()
{
    return dragInsets;
}

/**
 *  Set the drag insets. The insets specify an area where mouseDragged
 *  events should be ignored and therefore the component will not be moved.
 *  This will prevent these events from being confused with a
 *  MouseMotionListener that supports component resizing.
 *
 *  @param  dragInsets
 */
public void setDragInsets(Insets dragInsets)
{
    this.dragInsets = dragInsets;
}

/**
 *  Remove listeners from the specified component
 *
 *  @param component  the component the listeners are removed from
 */
public void deregisterComponent(Component... components)
{
    for (Component component : components)
        component.removeMouseListener( this );
}

/**
 *  Add the required listeners to the specified component
 *
 *  @param component  the component the listeners are added to
 */
public void registerComponent(Component... components)
{
    for (Component component : components) {
        component.addMouseListener( this );
        comps.add(component);
    }
}

/**
 *  Get the snap size
 *
 *  @return the snap size
 */
public Dimension getSnapSize()
{
    return snapSize;
}

/**
 *  Set the snap size. Forces the component to be snapped to
 *  the closest grid position. Snapping will occur when the mouse is
 *  dragged half way.
 */
public void setSnapSize(Dimension snapSize)
{
    this.snapSize = snapSize;
}

/**
 *  Setup the variables used to control the moving of the component:
 *
 *  source - the source component of the mouse event
 *  destination - the component that will ultimately be moved
 *  pressed - the Point where the mouse was pressed in the destination
 *      component coordinates.
 */
@Override
public void mousePressed(MouseEvent e)
{
    source = e.getComponent();
    int width  = source.getSize().width  - dragInsets.left - dragInsets.right;
    int height = source.getSize().height - dragInsets.top - dragInsets.bottom;
    Rectangle r = new Rectangle(dragInsets.left, dragInsets.top, width, height);

    if (r.contains(e.getPoint()))
        setupForDragging(e);
}

private void setupForDragging(MouseEvent e)
{
    source.addMouseMotionListener( this );

    //  Determine the component that will ultimately be moved

    if (destinationComponent != null)
    {
        destination = destinationComponent;
    }
    else if (destinationClass == null)
    {
        destination = source;
    }
    else  //  forward events to destination component
    {
        destination = SwingUtilities.getAncestorOfClass(destinationClass, source);
    }

    pressed = e.getLocationOnScreen();
    location = destination.getLocation();

    if (changeCursor)
    {
        originalCursor = source.getCursor();
        source.setCursor( Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR) );
    }

    //  Making sure autoscrolls is false will allow for smoother dragging of
    //  individual components

    if (destination instanceof JComponent)
    {
        JComponent jc = (JComponent)destination;
        autoscrolls = jc.getAutoscrolls();
        jc.setAutoscrolls( false );
    }
}

/**
 *  Move the component to its new location. The dragged Point must be in
 *  the destination coordinates.
 */
@Override
public void mouseDragged(MouseEvent e)
{
    destination.repaint();
    Point dragged = e.getLocationOnScreen();
    int dragX = getDragDistance(dragged.x, pressed.x, snapSize.width);
    int dragY = getDragDistance(dragged.y, pressed.y, snapSize.height);
    destination.setLocation(location.x   dragX, location.y   dragY);
    for(Component c : comps)
        c.repaint();
}

/*
 *  Determine how far the mouse has moved from where dragging started
 *  (Assume drag direction is down and right for positive drag distance)
 */
private int getDragDistance(int larger, int smaller, int snapSize)
{
    int halfway = snapSize / 2;
    int drag = larger - smaller;
    drag  = (drag < 0) ? -halfway : halfway;
    drag = (drag / snapSize) * snapSize;

    return drag;
}

/**
 *  Restore the original state of the Component
 */
@Override
public void mouseReleased(MouseEvent e)
{
    for(Component c : comps)
        c.repaint();
    System.out.println("Repainted!");

    source.removeMouseMotionListener( this );

    if (changeCursor)
        source.setCursor( originalCursor );

    if (destination instanceof JComponent)
    {
        ((JComponent)destination).setAutoscrolls( autoscrolls );
    }

}
  

}

Ответ №1:

ComponentMover используется для изменения расположения компонентов на панели.

Мне кажется, что вы хотите прокрутить панель, содержащуюся в окне просмотра области прокрутки. Если это так, я предлагаю вам проверить метод JComponent.setAutoScrolls(), который содержит некоторый пример кода для прокрутки компонента в области прокрутки.