NSView: перетаскивание вида - PullRequest
9 голосов
/ 25 августа 2011

У меня есть NSView, который я добавляю как подпредставление другого NSView. Я хочу иметь возможность перетащить первый NSView вокруг родительского представления. У меня есть код, который частично работает, но есть проблема с NSView, движущимся в противоположном направлении по оси Y от перетаскивания моей мыши. (т. е. я тяну вниз, оно идет вверх и наоборот).

Вот мой код:

// -------------------- MOUSE EVENTS ------------------- \\ 

- (BOOL) acceptsFirstMouse:(NSEvent *)e {
return YES;
}

- (void)mouseDown:(NSEvent *) e { 

//get the mouse point
lastDragLocation = [e locationInWindow];

}

- (void)mouseDragged:(NSEvent *)theEvent {

NSPoint newDragLocation = [theEvent locationInWindow];
NSPoint thisOrigin = [self frame].origin;
thisOrigin.x += (-lastDragLocation.x + newDragLocation.x);
thisOrigin.y += (-lastDragLocation.y + newDragLocation.y);
[self setFrameOrigin:thisOrigin];
lastDragLocation = newDragLocation;
}

представление перевернуто, хотя я вернул это значение по умолчанию, и это, похоже, не имело значения. Что я делаю неправильно?

Ответы [ 2 ]

13 голосов
/ 30 августа 2011

Лучший способ решить эту проблему - начать с глубокого понимания координатных пространств.

Во-первых, важно понимать, что когда мы говорим о «рамке» окна, оно находится в координатном пространстве суперпредставления . Это означает, что регулировка переворачивания самого представления на самом деле не будет иметь значения, потому что мы ничего не меняли внутри самого представления.

Но ваша интуиция о том, что переворот здесь важен, верна.

По умолчанию ваш код в напечатанном виде выглядит так, как будто он будет работать; возможно, ваше суперпредставление было перевернуто (или не перевернуто), и оно находится в другом координатном пространстве, чем вы ожидаете.

Вместо того, чтобы просто переворачивать и раскручивать виды случайным образом, лучше всего конвертировать точки, с которыми вы имеете дело, в известное координатное пространство.

Я отредактировал ваш приведенный выше код, чтобы всегда преобразовывать его в координатное пространство суперпредставления, потому что мы работаем с источником кадра. Это будет работать, если ваше перетаскиваемое представление помещено в перевернутое или не перевернутое супервидение.

// -------------------- MOUSE EVENTS ------------------- \\ 

- (BOOL) acceptsFirstMouse:(NSEvent *)e {
    return YES;
}

- (void)mouseDown:(NSEvent *) e { 

    // Convert to superview's coordinate space
    self.lastDragLocation = [[self superview] convertPoint:[e locationInWindow] fromView:nil]; 

}

- (void)mouseDragged:(NSEvent *)theEvent {

    // We're working only in the superview's coordinate space, so we always convert.
    NSPoint newDragLocation = [[self superview] convertPoint:[theEvent locationInWindow] fromView:nil];
    NSPoint thisOrigin = [self frame].origin;
    thisOrigin.x += (-self.lastDragLocation.x + newDragLocation.x);
    thisOrigin.y += (-self.lastDragLocation.y + newDragLocation.y);
    [self setFrameOrigin:thisOrigin];
    self.lastDragLocation = newDragLocation;
}

Кроме того, я бы рекомендовал рефакторинг вашего кода, чтобы он имел дело с исходным положением мыши и текущим местоположением указателя, а не с дельтами между событиями mouseDragged. Это может привести к неожиданным результатам в будущем.

Вместо этого просто сохраните смещение между началом перетаскиваемого вида и указателем мыши (где указатель мыши находится внутри вида) и задайте в качестве источника кадра расположение указателя мыши за вычетом смещения.

Вот дополнительное прочтение:

Руководство по рисованию какао

Руководство по обработке событий Cocoa

0 голосов
/ 17 июля 2014

Я думаю, что вы должны рассчитывать в соответствии с положением мыши, потому что в соответствии с моим тестом, он становится более плавным. Потому что, как показано ниже, только обеспечить положение внутри системы координат окна приложения:

[[self superview] convertPoint:[theEvent locationInWindow] fromView:nil];

Я предлагаю что-то вроде этого:

lastDrag = [NSEvent mouseLocation];

другие коды такие же.

...