2010-07-12 8 views
6

Ich habe ausgiebig gesucht und kann nicht für das Leben von mir keine Informationen darüber finden, wie man einen ähnlichen Effekt wie den iTunes Songtitel Scrolling erreicht, wenn der Text in Cocoa zu groß ist. Ich habe versucht, die Grenzen auf einem NSTextField vergebens zu setzen. Ich habe versucht, NSTextView sowie verschiedene Versuche, NSScrollView zu verwenden. Ich bin sicher, dass ich etwas einfaches vermisse, aber jede Hilfe würde sehr geschätzt werden. Ich hoffe auch, CoreGraphics möglichst nicht verwenden zu müssen.iTunes Songtitel Scrollen in Cocoa

Example, beachten Sie die "Base.FM http://www." Text wurde gescrollt. Wenn Sie ein besseres Beispiel benötigen, öffnen Sie iTunes mit einem Titel mit einem ziemlich großen Titel und beobachten Sie, wie er vor und zurück blättert.

Ich würde sicherlich denken, es gibt eine einfache Möglichkeit, nur einen Markiereffekt mit einem NSTextField und einem NSTimer zu erzeugen, aber leider.

Antwort

18

Ich kann sehen, wie dies schwierig wäre, wenn Sie versuchen, die Funktionalität in ein vorhandenes Steuerelement zu schuhen. Wenn Sie jedoch nur mit einem einfachen NSView beginnen, ist es nicht so schlimm. Ich peitschte dies in etwa 10 Minuten ...

//ScrollingTextView.h: 
#import <Cocoa/Cocoa.h> 
@interface ScrollingTextView : NSView { 
    NSTimer * scroller; 
    NSPoint point; 
    NSString * text; 
    NSTimeInterval speed; 
    CGFloat stringWidth; 
} 

@property (nonatomic, copy) NSString * text; 
@property (nonatomic) NSTimeInterval speed; 

@end 


//ScrollingTextView.m 

#import "ScrollingTextView.h" 

@implementation ScrollingTextView 

@synthesize text; 
@synthesize speed; 

- (void) dealloc { 
    [text release]; 
    [scroller invalidate]; 
    [super dealloc]; 
} 

- (void) setText:(NSString *)newText { 
    [text release]; 
    text = [newText copy]; 
    point = NSZeroPoint; 

    stringWidth = [newText sizeWithAttributes:nil].width; 

    if (scroller == nil && speed > 0 && text != nil) { 
     scroller = [NSTimer scheduledTimerWithTimeInterval:speed target:self selector:@selector(moveText:) userInfo:nil repeats:YES]; 
    } 
} 

- (void) setSpeed:(NSTimeInterval)newSpeed { 
    if (newSpeed != speed) { 
     speed = newSpeed; 

     [scroller invalidate]; 
     scroller == nil; 
     if (speed > 0 && text != nil) { 
      scroller = [NSTimer scheduledTimerWithTimeInterval:speed target:self selector:@selector(moveText:) userInfo:nil repeats:YES]; 
     } 
    } 
} 

- (void) moveText:(NSTimer *)timer { 
    point.x = point.x - 1.0f; 
    [self setNeedsDisplay:YES]; 
} 

- (void)drawRect:(NSRect)dirtyRect { 
    // Drawing code here. 

    if (point.x + stringWidth < 0) { 
     point.x += dirtyRect.size.width; 
    } 

    [text drawAtPoint:point withAttributes:nil]; 

    if (point.x < 0) { 
     NSPoint otherPoint = point; 
     otherPoint.x += dirtyRect.size.width; 
     [text drawAtPoint:otherPoint withAttributes:nil]; 
    } 
} 

@end 

einfach eine NSView auf Ihr Fenster im Interface Builder ziehen und seine Klasse ändern „ScrollingTextView“. Dann (in Code), die Sie tun:

[myScrollingTextView setText:@"This is the text I want to scroll"]; 
[myScrollingTextView setSpeed:0.01]; //redraws every 1/100th of a second 

Das ist offensichtlich ziemlich rudimentär ist, aber es macht die Wrap-around-Sachen, die Sie suchen und ist ein angenehmer Ort zu starten.

+0

Funktioniert wie ein Champion. Ich kann nicht glauben, dass ich ähnliche Beispiele im Internet nicht finden konnte. Vielleicht ist es jetzt einfach zu einfach, dass ich deine Lösung sehe. –

+0

Das liegt wahrscheinlich an seiner Art von UI-Anti-Pattern. Aus ein paar Gründen ist der Chef, dass der Benutzer zu jeder gegebenen Zeit die Information zeigt, die er wünscht? Wahrscheinlich nicht. – EricLeaf