【问题标题】:NSButton: show alternate image on hoverNSButton:在悬停时显示替代图像
【发布时间】:2013-11-20 12:08:16
【问题描述】:

我有一个NSButton,有一个图片备用图片。我希望在悬停时显示备用图像。为了解决这个问题,我扩展了 NSButton 以在悬停视图时显示备用图像。有没有更好的解决方案?

我的解决方案:

@interface HoverButton()
@property (nonatomic, strong) NSTrackingArea *trackingArea;
@property (nonatomic, strong) NSImage *imageTmp;
@end

@implementation HoverButton

-(void)mouseEntered:(NSEvent *)theEvent {
    [super mouseEntered:theEvent];

    [self updateImages];
    self.image = self.alternateImage;
}

-(void)mouseExited:(NSEvent *)theEvent {
    [super mouseExited:theEvent];

    self.image = self.imageTmp;
}

- (void)updateImages {
    self.imageTmp = self.image;
}

-(void)updateTrackingAreas
{
    if(self.trackingArea != nil) {
        [self removeTrackingArea:self.trackingArea];
    }

    int opts = (NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways);
    self.trackingArea = [[NSTrackingArea alloc] initWithRect:[self bounds]
                                                     options:opts
                                                       owner:self
                                                    userInfo:nil];

    [self addTrackingArea:self.trackingArea];
}


@end

【问题讨论】:

    标签: objective-c nsbutton


    【解决方案1】:

    CustomButton.h

    @interface CustomButton : NSButton
    @property (getter=isMouseInside) BOOL mouseInside;
    @end
    

    CustomButton.m

    @implementation CustomButton
    
    + (Class)cellClass
    {
        return [CustomButtonCell class];
    }
    
    - (instancetype)initWithFrame:(NSRect)frame
    {
        self = [super initWithFrame:frame];
        if (self)
        {
            [self commonCustomButtonInit];
        }
        return self;
    }
    
    - (void)commonCustomButtonInit
    {
        NSTrackingArea *trackingArea = nil;
        trackingArea = [[NSTrackingArea alloc] initWithRect:[self bounds]
                                                    options:NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways | NSTrackingInVisibleRect
                                                      owner:self
                                                   userInfo:nil];
    
        [self addTrackingArea:trackingArea];
    }
    
    
    - (void)mouseEntered:(NSEvent *)event
    {
        self.mouseInside = YES;
        if ([self.cell isKindOfClass:[CustomButtonCell class]])
        {
            CustomButtonCell *cell = self.cell;
            cell.mouseInside = YES;
        }
    }
    
    -(void)mouseExited:(NSEvent *)event
    {
        self.mouseInside = NO;
        if ([self.cell isKindOfClass:[CustomButtonCell class]])
        {
            CustomButtonCell *cell = self.cell;
            cell.mouseInside = NO;
        }
    }
    
    @end
    

    CustomButtonCell.h

    @interface CustomButtonCell : NSButtonCell
    @property (getter=isMouseInside) BOOL mouseInside;
    @end
    

    CustomButtonCell.m

    @implementation CustomButtonCell
    @end
    

    另见answer

    【讨论】:

      【解决方案2】:

      我会说这更适合NSButtonCell 子类。你可以用一种方法做到这一点,它不会适用于所有 NSButtons(我怀疑那是你真正想要的)。只需将您在 IB 中的纽扣电池类型设置为您的自定义子类。

      这是我刚刚编写并测试过的一些代码:

      - (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView
      {
          if (_alternateImageOrKeyEquivalentFont && _bcFlags2.mouseInside) {
              // the draw bezel call is optional. maybe you don't want it
              [self drawBezelWithFrame:cellFrame inView:controlView];
              [self drawImage:_alternateImageOrKeyEquivalentFont
                    withFrame:cellFrame
                       inView:controlView];
          } else {
              [super drawInteriorWithFrame:cellFrame
                                    inView:controlView];
          }
      }
      

      您可能需要在单元格的init 方法中将showsBorderOnlyWhileMouseInside 设置为YES

      【讨论】:

      • 虽然这有效,但它会被应用商店拒绝,因为_alternateImageOrKeyEquivalentFont_bcFlags2 是私有api。
      • @Zenox 究竟是什么让它们成为私有的?它们在头文件中被声明为全世界都可以看到的。我不知道确切的规则是什么,因为我没有在 App Store 上发布;请赐教。
      • 这对私有内容有很好的回答:stackoverflow.com/questions/17580251/…。至于这个具体的例子:imgur.com/2PFuEqM.
      • @Zenox 谢谢你,这肯定会回答它:) 我会尽量记住在有时间时用合适的非私人解决方案更新这个答案。
      • 对于mouseInside,您只需在您的NSButtonCell 子类中实现-mouseEntered:-mouseExited: 并设置一个本地mouseInside 属性。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多