【问题标题】:Subclassing NSView Subclasses (NSTextField, NSButton, NSPopUpButton)子类化 NSView 子类(NSTextField、NSButton、NSPopUpButton)
【发布时间】:2016-06-08 20:48:22
【问题描述】:

我一直在努力将我的自定义样式 (example) 应用于我一直在构建的 OSX 桌面应用程序,我想知道这样做的范例/习语是什么。

  • 我正在使用 X/Nibs 在窗口上布置组件
  • 我将组件的类设置为开箱即用组件的自定义子类(例如NSTextFieldNSButtonNSPopUpButton
  • 我将覆盖一些viewWillDraw,在另一些覆盖init?,并将它们全部设为wantsLayer,并在这些层上设置属性

这似乎非常在最好的情况下很笨拙,而且一些视觉上的事情是不可能用这种方式处理的,比如在NSTextField 中添加填充。 我应该创建一个NSTextFieldCell 子类并实例化一个并将其设置为单元格吗?这样做会完全破坏文本字段。我看到other places 你应该继承NSButtonCell,但我不能将它指定为 X/Nib 中的按钮类。(@Willeke 在 cmets 中告诉我可以选择一个控件的单元格,然后通过再次单击该控件来分配一个自定义单元格类)

很多人都在描述如何在viewDidLoad 中通过引用一个组件来对可视化组件进行某些更改,如果您的按钮/文本字段样式适用于项目中的所有内容,这似乎非常乏味。似乎我对子类化所做的每一次视觉更改都是一场噩梦,并且对于不同组件在何处进行视觉更改没有任何模式。如果您想让代码可重用,子类化似乎是任何规模项目的最佳选择,但我错过了什么吗?我还缺少其他一些模式或习语吗?

【问题讨论】:

  • 您有任何自定义样式的示例吗?如果我们能看到您尝试复制的效果,提供帮助可能会更容易
  • dropbox.com/s/320chi85n7ec5oj/… 显示了我们想要的 NSTextFieldNSButton 的示例,我们希望 NSPopUpButton 具有与文本字段相同的样式。
  • 您可以像更改控件的类一样更改XIB中单元格的类。再次单击选择单元格(不要双击)或使用顶部的路径控件或使用左侧的文档大纲。
  • 哦,我不知道。是否存在关于通常与控件单元相关联的视觉样式的模式,或者真的没有模式?

标签: xcode macos cocoa appkit


【解决方案1】:

继承一个 NSTextFieldCell 是最好的选择,但它肯定是一场漫长的战斗。 像 Willeke sez 一样,更改 XIB 中单元格的类别。

我使用 BGHUDAppKit 作为起点,多年来进行了主要的模组/升级。

FWIW 这是我当前版本的 BGHUDTextFieldCell.mm,它使用了一堆我自己的类别方法,如 attrStringWithColor,但总体思路应该很清楚。

处理对焦环动画特别麻烦。 绘制自定义焦点环的唯一方法是将很多东西子类化,包括 NSTextField 和可能的超级视图,以便您可以劫持默认的 NSTextView 焦点环。 但是,我强烈建议不要继承 NSTextView 本身...请参阅下面的 setupFieldEditorColors。

  //  BGHUDTextFieldCell.m
  //  BGHUDAppKit
  //
  //  Created by BinaryGod on 6/2/08.
  //
  //  Copyright (c) 2008, Tim Davis (BinaryMethod.com, binary.god@gmail.com)
  //  All rights reserved.
  //
  //  Redistribution and use in source and binary forms, with or without modification,
  //  are permitted provided that the following conditions are met:
  //
  //        Redistributions of source code must retain the above copyright notice, this
  //    list of conditions and the following disclaimer.
  //
  //        Redistributions in binary form must reproduce the above copyright notice,
  //    this list of conditions and the following disclaimer in the documentation and/or
  //    other materials provided with the distribution.
  //
  //        Neither the name of the BinaryMethod.com nor the names of its contributors
  //    may be used to endorse or promote products derived from this software without
  //    specific prior written permission.
  //
  //    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND
  //    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  //    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  //    IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
  //    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  //    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
  //    OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  //    WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  //    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
  //    POSSIBILITY OF SUCH DAMAGE.

  #import "BGHUDTextFieldCell.h"
  #import "VNSColorCategory.h"
  #import "BGThemeMbox.h"
  @interface BGHUDTextFieldCell (Private)
  - (void)doInit;
  - (NSRect)_focusRingFrameForFrame:(NSRect)aRect cellFrame:(NSRect)cellFrame; // bug fix
  @end
  @implementation BGHUDTextFieldCell

  @synthesize themeKey;
  @synthesize LayerKey;
  @synthesize defaultTextColor;
  @synthesize isVerticallyCentered;
  @synthesize fillsBackground;
  //@synthesize LayerKey;
  #pragma mark Drawing Functions

  - (id)initTextCell:(NSString *)aString {

     self = [super initTextCell: aString];

     if(self) {
        self.themeKey = @"gradientTheme";
        [self doInit];

     }

     return self;
  }

  - (id)initWithCoder:(NSCoder *) aDecoder {

     self = [super initWithCoder: aDecoder];

     if(self) {

        if([aDecoder containsValueForKey: @"themeKey"]) {

           self.themeKey = [aDecoder decodeObjectForKey: @"themeKey"];
        } else {

           self.themeKey = @"gradientTheme";
        }

        [self doInit];

     }

     return self;
  }

  - (void)doInit
  {
     self.defaultTextColor = [[[BGThemeManager keyedManager] themeForKey: self.themeKey] textColor];
     [self setTextColor:self.defaultTextColor];

     if([self drawsBackground]) {
        fillsBackground = YES;
        ////NSLog( @"t%d BGHUDTextFieldCell initTextCell ignoring nib backgroundColor %@, use fillsBackground", [self tag], [self backgroundColor] );
     }
     else // kpk 2010... always draw background?
     {
        fillsBackground = NO;
     }

     [self setDrawsBackground: NO];
  }


  -(void)encodeWithCoder:(NSCoder *)aCoder {

     [super encodeWithCoder: aCoder];

     [aCoder encodeObject: self.themeKey forKey: @"themeKey"];
  }

  - ( NSRect ) adjustFrameToVerticallyCenterText: ( NSRect ) frame
  {
     // super would normally draw text at the top of the cell
     int offset = floor ( ( NSHeight ( frame ) - ( [ [ self font ] ascender] - [ [ self font ] descender ] ) ) / 2 );
     frame = NSInsetRect ( frame, 0.0, offset );
     return frame;
  }

  - (NSText *)setUpFieldEditorAttributes:(NSText *)textObj
  {
     BGTheme *theTheme = [[BGThemeManager keyedManager] themeForKey: self.themeKey];
     //textObj = [super setUpFieldEditorAttributes:textObj];
     NSTextView *theTextView = (NSTextView *)textObj;   
     if ( [theTextView isKindOfClass:[NSTextView class]] )
     {
        //NSLog( @"t%d text view editor %@ bgcolor %@ insert color %@", [self tag], [theTextView description], [theTextView backgroundColor], [theTextView insertionPointColor] ); 
        [BGTheme setupFieldEditorColors:theTheme editor:theTextView window:[[self controlView] window]  forObject:self];
     }

     return textObj;
  }

  -(void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView {
     waitIfNeeded(self);
     if ( isVerticallyCentered ) // kpk 2013 _cFlags.vCentered = 1;
        cellFrame = [ self adjustFrameToVerticallyCenterText: cellFrame ];

     // kpk 2009/2010: get the fieldEditorView (NSTextView) to display properly as well.
     // Also be careful not to cause continuous redraws by setting text color unnecessarily.   
     NSWindow *theWindow = [controlView window];

     NSTextView* fieldEditorView = (NSTextView*)[theWindow fieldEditor: NO forObject: self]; 
     id fieldEditorDelegate = [fieldEditorView delegate];   
     if ( [theWindow firstResponder] == fieldEditorView && fieldEditorDelegate == controlView )
     {    
        //NSLog( @"t%d fieldEditorView bg color %@ self %@ controlView %@", [self tag], [self backgroundColor], [self description], [controlView description] );
        BGTheme *theTheme = [[BGThemeManager keyedManager] themeForKey: self.themeKey];
        if ( fieldEditorView )
           [BGTheme setupFieldEditorColors:theTheme editor:fieldEditorView window:theWindow forObject:self];

        NSRect editFrame = [fieldEditorView frame];
        NSRect controlViewFrame = [controlView frame];
        if ( [controlView isKindOfClass:[NSTextField class]] && NSIntersectsRect(controlViewFrame, editFrame ))
        {
           return;
        }
     }
     fieldEditorView = nil; // kpk 2010: we are done with this now

     //Create Path
     NSBezierPath *path = [[NSBezierPath new] autorelease];

     if([self bezelStyle] == NSTextFieldRoundedBezel) {

        [path appendBezierPathWithArcWithCenter: NSMakePoint(cellFrame.origin.x + (cellFrame.size.height /2), cellFrame.origin.y + (cellFrame.size.height /2))
                                 radius: cellFrame.size.height /2
                              startAngle: 90
                                endAngle: 270];

        [path appendBezierPathWithArcWithCenter: NSMakePoint(cellFrame.origin.x + (cellFrame.size.width - (cellFrame.size.height /2)), cellFrame.origin.y + (cellFrame.size.height /2))
                                 radius: cellFrame.size.height /2
                              startAngle: 270
                                endAngle: 90];

        [path closePath];
     } else {

        // kpk 2010: not desireable for table view cells
        //[path appendBezierPathWithRoundedRect: cellFrame xRadius: 3.0f yRadius: 3.0f];
        //[path appendBezierPathWithRect:cellFrame];
     }

     //Draw Background
     if(fillsBackground) {
        [[[[BGThemeManager keyedManager] themeForKey: self.themeKey] textFillColor] set];
        // kpk 2010: not desireable for table view cells
        NSRectFill( cellFrame );
        //[path fill];
     }
     else if ( [self isEditable] )
     {
        [[[[BGThemeManager keyedManager] themeForKey: self.themeKey] textFillColor] set]; 
        [path fill];      
        // NSRectFill( cellFrame );
     }

     if([self isBezeled] || [self isBordered]) {

        [NSGraphicsContext saveGraphicsState];

        if([super showsFirstResponder] && [theWindow isKeyWindow] && 
           ([self focusRingType] == NSFocusRingTypeDefault ||
           [self focusRingType] == NSFocusRingTypeExterior)) {

           [[[[BGThemeManager keyedManager] themeForKey: self.themeKey] focusRing] set];
        }

        //Check State
        if([self isEnabled]) {

           [[[[BGThemeManager keyedManager] themeForKey: self.themeKey] darkStrokeColor] set];
        } else {

           [[[[BGThemeManager keyedManager] themeForKey: self.themeKey] disabledStrokeColor] set];
        }

        [path setLineWidth: 1.0f];
        [path stroke];

        [NSGraphicsContext restoreGraphicsState];
     }

     // Check to see if the attributed placeholder has been set or not
     //if(![self placeholderAttributedString]) {
     if(![self placeholderAttributedString] && [self placeholderString]) {

        //Nope lets create it
        NSDictionary *attribs = [[NSDictionary alloc] initWithObjectsAndKeys: 
                           [[[BGThemeManager keyedManager] themeForKey: self.themeKey] placeholderTextColor] , NSForegroundColorAttributeName, nil];

        //Set it
        [self setPlaceholderAttributedString: [[[NSAttributedString alloc] initWithString: [self placeholderString] attributes: [attribs autorelease]] autorelease]];
     }

     //Adjust Frame so Text Draws correctly
     switch ([self controlSize]) {

        case NSRegularControlSize:

           if([self bezelStyle] == NSTextFieldRoundedBezel) { // kpk 2010

              cellFrame.origin.y += 1;
           }
           break;

        case NSSmallControlSize:

           if([self bezelStyle] == NSTextFieldRoundedBezel) {

              cellFrame.origin.y += 1;
           }
           break;

        case NSMiniControlSize:

           if([self bezelStyle] == NSTextFieldRoundedBezel) {

              cellFrame.origin.x += 1;
           }
           break;

        default:
           break;
     }

     [self drawInteriorWithFrame: cellFrame inView: controlView];
  }

  -(void)drawInteriorWithFrame:(NSRect) cellFrame inView:(NSView *) controlView {     
     if ( [controlView conformsToProtocol:@protocol(EditingAlignmentProtocol)] )
     {

        if ( [controlView isKindOfClass:[NSControl class]] && [(NSControl *)controlView currentEditor] )
        {       
           // DLog( @"danger: skipping draw to avoid call to validateEditing!" );
           return;
        }

        cellFrame = [(id <EditingAlignmentProtocol>)controlView editingAlignmentRect];
        cellFrame = [self titleRectForBounds:cellFrame];
        NSAttributedString *str = [self attributedStringValue];
        [str drawInRect:cellFrame];  
        return;
     }

     [super drawInteriorWithFrame: cellFrame inView: controlView];
  }

  - (NSColor *)highlightColorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView;
  {

     // Corbin Dunn (the apple author) says to return nil here
  //   The proper thing to do:
  //      
  //      1. Subclass NSCell, NSTextFieldCell, or whatever other cell you want.
  //      2. Override:
  //      
  //      - (NSColor *)highlightColorWithFrame:(NSRect)cellFrame inView:(NSView
  //                                                                     *)controlView
  //      
  //      and return nil.
  //      
  //      That is the correct thing to do for Tiger, Leopard, etc.
  //         
  //         corbin
     if ( [controlView isKindOfClass: [NSTableView class]] )
        return nil; // [[BGThemeMbox instance] cellHighlightColor];
     return [super highlightColorWithFrame:cellFrame inView:controlView];
  }

  // warning mIsEditingOrSelecting is probably not used correctly when call stack is deep,
  // while switching from one edit field to another
  - (NSRect)drawingRectForBounds:(NSRect)aRect
  {
     id controlView = [self controlView];
     NSRect newRect;
     if ( [controlView conformsToProtocol:@protocol(EditingAlignmentProtocol)] )
        newRect = [(id <EditingAlignmentProtocol>)controlView editingAlignmentRect];
     else
     {
        newRect = [super drawingRectForBounds:aRect];
        if (mIsEditingOrSelecting == NO)
        {
           // Get our ideal size for current text
           NSSize textSize = [self cellSizeForBounds:aRect];
           if ( textSize.height >= 22 && textSize.height > newRect.size.height )
           {
              newRect.origin.y = -(textSize.height - newRect.size.height) + 6;
              newRect.size.height = textSize.height + (textSize.height - newRect.size.height);
           }      
        }
     }

     return newRect;
  }

  // hack alert: undocumented _focusRingFrameForFrame
  // this fixes a hard to reproduce bug where NSTextView fieldEditor *sometimes* 
  // leaves behind white clutter.
  // to reproduce, have 10, 11, or 12 items in scene table, then edit xFade type.
  // scene table will have white clutter.
  - (NSRect)_focusRingFrameForFrame:(NSRect)aRect cellFrame:(NSRect)cellFrame
  {
     id ctl = [self controlView];
     if ( [ctl conformsToProtocol:@protocol(EditingAlignmentProtocol)] )
        return [ctl bounds];
     else
        return cellFrame;
  }

  //    This method is adapted from Red Sweater Software's RSVerticallyCenteredTextField class.
  //  Created by Daniel Jalkut on 6/17/06.
  //  Copyright 2006 Red Sweater Software. All rights reserved.
  //    MIT License
  - (void)selectWithFrame:(NSRect)aRect inView:(NSView *)controlView editor:(NSText *)textObj delegate:(id)anObject start:(NSInteger)selStart length:(NSInteger)selLength
  {
     if ( isVerticallyCentered ) // kpk 2013 _cFlags.vCentered replacement
        aRect = [ self adjustFrameToVerticallyCenterText: aRect ];
     aRect = [self drawingRectForBounds:aRect];
     mIsEditingOrSelecting = YES;
     [super selectWithFrame:aRect inView:controlView editor:textObj delegate:anObject start:selStart length:selLength];
     mIsEditingOrSelecting = NO;
     //NSLog( @"selectWithFrame %@ %@", controlView, textObj );
  }

  //    This method is adapted from Red Sweater Software's RSVerticallyCenteredTextField class.
  //  Created by Daniel Jalkut on 6/17/06.
  //  Copyright 2006 Red Sweater Software. All rights reserved.
  //    MIT License
  - (void)editWithFrame:(NSRect)aRect inView:(NSView *)controlView editor:(NSText *)textObj delegate:(id)anObject event:(NSEvent *)theEvent
  {   
     if ( isVerticallyCentered ) // kpk 2013 _cFlags.vCentered replacement
        aRect = [ self adjustFrameToVerticallyCenterText: aRect ];
     //NSLog( @"editWithFrame %@", controlView );
     aRect = [self drawingRectForBounds:aRect];
     mIsEditingOrSelecting = YES;   
     [super editWithFrame:[self drawingRectForBounds:aRect] inView:controlView editor:textObj delegate:anObject event:theEvent];
     mIsEditingOrSelecting = NO;   
  }

  -(void)_drawKeyboardFocusRingWithFrame:(NSRect)fp8 inView:(id)fp24 {
     //NSLog( @"_drawKeyboardFocusRingWithFrame" );
  }

  - (void)drawWithExpansionFrame:(NSRect)cellFrame inView:(NSView *)view
  {
     [[[[BGThemeManager keyedManager] themeForKey: @"gradientTheme"] darkStrokeColor] set];
     NSRectFill(cellFrame);
     [self drawInteriorWithFrame:cellFrame inView:view];
  }

  - (void) setAttributedColor: (NSColor *)iColor
  {
     NSMutableAttributedString *attrStr = [[self stringValue] attrStringWithColor: iColor];
     [attrStr setAlignment: [self alignment] range:[attrStr fullRange]];
     [attrStr setFont:[self font]];
     [self setAttributedStringValue:attrStr];
     if ( iColor )
        [self setTextColor:iColor];
     else if ( [self isEditable] )
        [self setTextColor: [NSColor defaultTextColor]];
     else
        [self setTextColor:[NSColor dimTextColor]];
  }

  #pragma mark -
  #pragma mark Helper Methods

  -(void)dealloc {

     [super dealloc];
  }

  #pragma mark -

  @end

.h 文件:

      #import <Cocoa/Cocoa.h>
  #import "BGThemeManager.h"

  @protocol EditingAlignmentProtocol
  - (NSRect)editingAlignmentRect; // used to align NSTextView field editor frame
  - (void)setIsSettingUpFieldEditor:(bool)flag;
  - (bool)isSettingUpFieldEditor;
  @end

  @interface BGHUDTextFieldCell : NSTextFieldCell {

     BOOL fillsBackground;
     NSString *themeKey;
     NSString *LayerKey;
     NSColor *defaultTextColor;
     BOOL mIsEditingOrSelecting;
     BOOL isVerticallyCentered;
  }

  @property (retain) NSString *themeKey;
  @property (retain) NSString *LayerKey;
  @property (retain) NSColor *defaultTextColor;
  @property (assign) BOOL isVerticallyCentered;
  @property (assign) BOOL fillsBackground;
  - (void)doInit; // if overriden, must call [super doInit];
  - (void) setAttributedColor: (NSColor *)iColor;
  @end

setupFieldEditor

+(void)setupFieldEditorColors:(BGTheme *)iTheme editor:(NSTextView *)iFieldEditorView window:(NSWindow *)iWindow forObject:(id)anObject
{
   if ( iFieldEditorView == nil )
      return;

   if ( !iFieldEditorView || ![iFieldEditorView isKindOfClass:[NSTextView class]] )
      return;

   // setup attributes such that editing in the field editor will
   // occur at the exact same position as the title cell was drawn
   [[iFieldEditorView textContainer] setLineFragmentPadding:2.0];
   //[[iFieldEditorView layoutManager] setTypesetterBehavior:NSTypesetterBehavior_10_2_WithCompatibility];
   NSRange theSelRange = [iFieldEditorView selectedRange];   
   @try
   {   
      if ( [anObject respondsToSelector: @selector(themeKey)] || 
          ( [anObject respondsToSelector: @selector(cell)] && 
           [[anObject cell] respondsToSelector: @selector(themeKey)] ))
      {
         //NSLog( @"theSelRange %@", NSStringFromRange(theSelRange));
         NSColor *theTextColor = [iTheme textColor];
         if ( [iFieldEditorView insertionPointColor] != theTextColor )
            [iFieldEditorView setInsertionPointColor:theTextColor]; 
         //if ( [iFieldEditorView textColor] != theTextColor )
         //{
            //NSLog( @"cell editor tc %@\n   change to %@", [iFieldEditorView textColor], theTextColor );
         //   [iFieldEditorView setTextColor: theTextColor];
         //}

         //NSLog( @"cell editor createFlag %d", createFlag);
         //if ( ![iFieldEditorView isKindOfClass:[BGHUDTextView class]] )
         //  iFieldEditorView = [BGHUDTextView alloc] init
         NSColor *theBgColor = [iTheme cellEditingFillColor];
         if ( [iFieldEditorView backgroundColor] != theBgColor )
         {
            //NSLog( @"cell editor bg %@\n   change to %@", [iFieldEditorView backgroundColor], theBgColor );
            [iFieldEditorView setBackgroundColor:theBgColor];
         }

         if ( [iFieldEditorView drawsBackground] == NO )
            [iFieldEditorView setDrawsBackground:YES];



         NSMutableDictionary *theDict = [[[iFieldEditorView selectedTextAttributes] mutableCopy] autorelease];        
         //NSColor *theSelTextColor = nil;
         if([iWindow isKeyWindow])
         {
            if ( [theDict objectForKey: NSBackgroundColorAttributeName] != [iTheme selectionHighlightActiveColor] )
            {  
               [theDict setObject: [iTheme selectionHighlightActiveColor]
                        forKey: NSBackgroundColorAttributeName];
               //theSelTextColor = [iTheme selectionTextActiveColor];
               //kpk why doesn't this work?
               [theDict setObject: [iTheme selectionTextActiveColor]
                        forKey: NSForegroundColorAttributeName];
               [iFieldEditorView setSelectedTextAttributes:theDict]; 
            }
         }
         else
         {
            if ( [theDict objectForKey: NSBackgroundColorAttributeName] != [iTheme selectionHighlightInActiveColor] )
            {  
               [theDict setObject: [iTheme selectionHighlightInActiveColor]
                           forKey: NSBackgroundColorAttributeName];
               //theSelTextColor = [iTheme selectionTextInActiveColor];         
               //kpk why doesn't this work?
               [theDict setObject: [iTheme selectionTextInActiveColor]
                           forKey: NSForegroundColorAttributeName]; 
               [iFieldEditorView setSelectedTextAttributes:theDict];                
            }
         }

/*
         NSString *theStr = [iFieldEditorView string];
         if ( !theStr )
            return;


         NSUInteger theStrLength = [theStr length];
         if ( theStrLength > 0 )
            [iFieldEditorView setTextColor: theTextColor
                                     range: NSMakeRange(0, theStrLength)];

         if(theSelRange.length > 0 && theSelRange.length <= theStrLength || theSelRange.location <= theStrLength && NSMaxRange(theSelRange) <= theStrLength )
         { 
            [iFieldEditorView setTextColor: theSelTextColor
                                     range: [iFieldEditorView selectedRange]];
         }
         else
         {

         }
         */


      }   
   }
   @catch(...)
   {
      //VLog::Log( kLogErrorType | kLogNoFlood, @"caught exception in setupFieldEditorColors %@", NSStringFromRange(theSelRange));
      NSLog( @"caught exception in setupFieldEditorColors %@", NSStringFromRange(theSelRange) );
   }      
}

【讨论】:

    【解决方案2】:

    我最终继承了NSTextFieldCell,并从this answer 得出以下具体问题:

    class TGTextFieldCell: NSTextFieldCell {
        override init(imageCell image: NSImage?) {
            super.init(imageCell: image)
        }
    
        override init(textCell aString: String) {
            super.init(textCell: aString)
        }
    
        required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
        }
    
        override func drawingRectForBounds(theRect: NSRect) -> NSRect {
            let rectInset = NSMakeRect(theRect.origin.x + 7, theRect.origin.y + 7, theRect.size.width, theRect.size.height)
            return super.drawingRectForBounds(rectInset)
        }
    }
    

    自定义视图似乎仍然比它需要的复杂得多(例如转到customizing focus styles),但这是一个我还没有听到好的答案的问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-29
      • 1970-01-01
      • 2023-04-06
      相关资源
      最近更新 更多