LoginSignup
1
1

More than 3 years have passed since last update.

NSView上のドラッグによって、ウィンドウをドラッグさせる

Posted at

概要

  • 指定したカスタムビュー上でドラッグした場合に、ウィンドウの位置を移動させる

Jun-25-2019 15-30-04

GitHub

実装

カスタムビュー(DraggingView)

  • コード全体
#import "DraggingView.h"

@interface DraggingView()
@property NSPoint currentPoint;
@end

@implementation DraggingView

- (void)drawRect:(NSRect)dirtyRect {
    [super drawRect:dirtyRect];
    // Drawing code here.
    // 分かりやすいようにビューに色を付ける
    NSRect bounds = [self bounds];
    [[[NSColor blueColor] colorWithAlphaComponent:0.1] set];
    [NSBezierPath fillRect:bounds];
}

#pragma mark Events
- (void)mouseDown:(NSEvent *)event {
    NSPoint p = [event locationInWindow];
    _currentPoint = [self convertPoint:p fromView:nil]; // viewの座標系に変換
    [self setNeedsDisplay:YES];
}

- (void)mouseDragged:(NSEvent *)event {
    NSPoint previousPoint = _currentPoint;
    NSPoint p = [event locationInWindow];
    _currentPoint = [self convertPoint:p fromView:nil]; // viewの座標系に変換

    // 移動したマウスの距離だけウィンドウの位置を移動させる
    double  distance_x   = _currentPoint.x - previousPoint.x;
    double  distance_y   = _currentPoint.y - previousPoint.y;
    NSRect  windowFrame  = self.window.frame;
    NSPoint windowOrigin = windowFrame.origin; // 現在のウィンドウ位置
    windowOrigin.x  += distance_x;
    windowOrigin.y  += distance_y;
    _currentPoint.x -= distance_x;             // ウィンドウの位置が変わったので、次のマウス移動の計算のために補正を行う
    _currentPoint.y -= distance_y;
    [self.window setFrameOrigin:windowOrigin]; // ウィンドウの位置を移動
    [self setNeedsDisplay:YES];
}

- (void)mouseUp:(NSEvent *)event {
    NSPoint p = [event locationInWindow];
    _currentPoint = [self convertPoint:p fromView:nil]; // viewの座標系に変換
    [self setNeedsDisplay:YES];
}

@end
  • NSViewNSResponderを継承していて、これにはイベントを処理するメソッドが定義されています。
  • 今回はその中のmouseDownmouseDraggedmouseUpを使用します。
- (void)mouseDown:(NSEvent *)event {
    NSPoint p = [event locationInWindow];
    _currentPoint = [self convertPoint:p fromView:nil]; // viewの座標系に変換
    [self setNeedsDisplay:YES];
}
  • マウスを押し込んだ際に呼ばれるメソッド
  • 引数のNSEventオブジェクトから作成できる座標情報はウィンドウのものなので、今回は必要ないが、利便性のためNSViewの座標系に変換することが多い。
  • _currentPointに押された位置を記録しておく
- (void)mouseDragged:(NSEvent *)event {
    NSPoint previousPoint = _currentPoint;
    NSPoint p = [event locationInWindow];
    _currentPoint = [self convertPoint:p fromView:nil]; // viewの座標系に変換

    // 移動したマウスの距離だけウィンドウの位置を移動させる
    double  distance_x   = _currentPoint.x - previousPoint.x;
    double  distance_y   = _currentPoint.y - previousPoint.y;
  • ドラッグ前のマウス位置はpreviousPointへ保存
  • ドラッグ後のマウス位置を_currentPointへ保存
  • この2点からドラッグした距離を計算する
NSRect  windowFrame  = self.window.frame;
NSPoint windowOrigin = windowFrame.origin; // 現在のウィンドウ位置
windowOrigin.x  += distance_x;
windowOrigin.y  += distance_y;
_currentPoint.x -= distance_x;             // ウィンドウの位置が変わったので、次のマウス移動の計算のために補正を行う
_currentPoint.y -= distance_y;
[self.window setFrameOrigin:windowOrigin]; // ウィンドウの位置を移動
[self setNeedsDisplay:YES];
  • 移動した距離だけウィンドウの位置を変更する
  • このとき_currentPointを更新しておくことを忘れないように。
    • ウィンドウ位置が変更したため_currentPointを補完しないと、次回のドラッグ距離計算のときにずれが生じてしまう。
- (void)mouseUp:(NSEvent *)event {
    NSPoint p = [event locationInWindow];
    _currentPoint = [self convertPoint:p fromView:nil]; // viewの座標系に変換
    [self setNeedsDisplay:YES];
}
  • ドラッグが終了したときに呼ばれるメソッド。
  • 今回は必要なし。

参考

1
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1