操纵CellControl

本文包含用于处理CellControl的其他技巧和示例。

设置CellControl的大小

要将Cell(以及任何封闭的只有一个CellControl)的大小设置为符合人机界面准则的最佳大小,请执行以下操作:

  1. 如果Cell包含文本,请将文本的字体设置为与以下三种标准大小之一一致:regularsmallmini。为此,请使用NSFont类方法systemFontSizeForControlSize:。该方法的参数是NSControl类声明的NSControlSize常量。
  1. float fontSize = [NSFont systemFontSizeForControlSize:NSMiniControlSize];
  2. NSCell *theCell = [theControl cell];
  3. NSFont *theFont = [NSFont fontWithName:[[theCell font] fontName] size:fontSize];
  4. [theCell setFont:theFont];
  1. 使用相同的常数将Control大小设置为与字体大小相同的大小。使用NSControlsetControlSize:方法。
  1. [theCell setControlSize:NSMiniControlSize];
  1. 最后,将sizeToFit发送到Control以修剪额外的宽度。
  1. [theControl sizeToFit];

Cell边界内绘制聚焦环

The NSSetFocusRingStyle sets the style that a focus ring will be drawn in the next time you fill a bezier path. It takes a constant of type of NSFocusRingPlacement to tell the Application Kit to draw the focus ring over an image, under text, or (when neither text or image is a consideration) around a shape. You can use this function with a constant of NSFocusRingOnly to draw a focus ring just inside a cell’s bounds.

Listing 1 shows how you draw such a focus ring. It requires you to override the NSCell drawWithFrame:inView:. In this method, if the cell is supposed to draw evidence of first-responder status, set the rectangle for the focus ring, call NSSetFocusRingStyle with an argument of NSFocusRingOnly, and then create and fill a bezier path defining that rectangle. Filling in this case simply draws the ring.

Note: This technique requires you to subclass a cell class. See “Subclassing NSCell” for information.

Listing 1 Drawing a focus ring just inside a cell’s bounds

  1. - (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView {
  2. // other stuff might happen here
  3. if ([self showsFirstResponder]) {
  4. // showsFirstResponder is set for us by the NSControl that is drawing us.
  5. NSRect focusRingFrame = cellFrame;
  6. focusRingFrame.size.height -= 2.0;
  7. [NSGraphicsContext saveGraphicsState];
  8. NSSetFocusRingStyle(NSFocusRingOnly);
  9. [[NSBezierPath bezierPathWithRect: NSInsetRect(focusRingFrame,4,4)] fill];
  10. [NSGraphicsContext restoreGraphicsState];
  11. }
  12. // other stuff might happen here
  13. }

Cell内放置图像

如果Cell显示的是图像而不是文本(或除文本之外也显示图像),则可以通过覆盖imageRectForBounds:方法来影响图像在Cell中的放置,该方法由NSCellNSMenuItemCell类都声明。此方法返回绘制Cell图像的矩形,通常是一个稍微偏离Cell边界的矩形。例2给出了一个示例。

注意: 此技术要求你将Cell类子类化。有关信息,请参见“对NSCell进行子类化”

例2 将图像居中放置在Cell

  1. - (NSRect) imageRectForBounds:(NSRect)theBounds {
  2. NSRect r = theBounds;
  3. // get size. If no image, result of method returning NSSize is undefined so assume NSZeroSize
  4. NSSize imageSize = [self image] != nil ? [[self image] size] : NSZeroSize;
  5. r.origin.x = floor((r.size.width/2) - (imageSize.width/2) + 0.5);
  6. r.origin.y = floor((r.size.height/2) - (imageSize.height/2) + 0.5);
  7. r.size = imageSize;
  8. return r;
  9. }

在此示例中,Cell将图像居中。请注意,它会将返回值四舍五入到最接近的像素,以避免使用部分像素偏移可能导致的绘图模糊。该代码还将返回的矩形的size字段设置为图像的大小,以便在矩形中正确绘制(假设NSImage对象使用drawInRect:fromRect:operation:fraction:进行绘制,而不使用compositeToPoint:operation:)。