2013-01-20 128 views
7

我已經搜索瞭如何執行此操作,但找不到任何答案。
我想知道我的NSTextfield是否已經截斷文本(末尾),而不必檢查它的長度stringValue。我需要這樣做來知道我是否應該在我的NSTextfield上設置工具提示(表現得像一個簡單的標籤)。
原因我不想檢查我的文本框的長度stringValue這是因爲有一些字符比其他字符佔用更多的空間,所以這不是很準確
謝謝!如何檢查NSTextfield是否已經截斷文本(...末尾)

回答

4

最好的辦法可能是使用NSTextView而不是NSTextField。如果您使用NSTextView,則可以使用textContainer屬性獲取NSTextViewNSTextContainer。容器可以告訴你containerSize(文本所在的空間)。

NSString對象響應方法sizeWithAttributes:。如果使用給定的屬性繪製,您可以使用結果NSSize結構來獲取文本的寬度。請參閱NSAttributedString Application Kit Additions Reference的「常數」部分,瞭解哪些屬性是相關的。

如果containerSize寬度小於sizeWithAttributes:寬度,則文本將被截斷。

編輯:道歉,這是唯一的沒有lineFragmentPadding,但默認lineFragmentPadding是非零。從containerSize.width中減去textContainer.lineFragmentPadding或使用NSTextContainersetLineFragmentPadding:方法將其設置爲0

我想你也可以對文字區域做一些相對於NSTextField大小的假設,並使用sizeWithAttributes:NSString方法,但這並不是那麼幹淨。

編輯2:我意識到我沒有解決OP對使用橢圓截斷文本的興趣。下面的示例代碼使用NSTextView中的截斷。我也認爲我不妨將NSTextView放在NSBox的內部,使它的外觀與NSTextField更相似。使用上面提到的信息,添加一個檢查大小以確定是否應該顯示工具提示將是對以下代碼的簡單添加。

NSString* string = @"Hello World."; 

// get the size the text will take up using the default font 
NSSize textBounds = [string sizeWithAttributes:@{}]; 

// Create a border view that looks more or less like the border used around 
// text fields 
NSBox* borderView = [[NSBox alloc] initWithFrame:NSMakeRect(10, 10, 60, textBounds.height+4)]; 
[borderView setBoxType:NSBoxCustom]; 
[borderView setBorderType:NSBezelBorder]; 
[borderView setContentViewMargins:NSMakeSize(0, 0)]; 
[borderView setFillColor:[NSColor whiteColor]]; 

// Create the text view 
NSTextView* textView = [[NSTextView alloc] initWithFrame:NSMakeRect(0, 0, 60, textBounds.height)]; 
[textView setTextContainerInset:NSMakeSize(2, 0)]; 
[textView.textContainer setLineFragmentPadding:0]; 
[textView setEditable:YES]; 

// Set the default paragraph style so the text is truncated rather than 
// wrapped 
NSMutableParagraphStyle* parStyle = [[NSMutableParagraphStyle alloc] init]; 
[parStyle setLineBreakMode:NSLineBreakByTruncatingTail]; 

// Do not let text get squashed to fit 
[parStyle setTighteningFactorForTruncation:0.0]; 

[textView setDefaultParagraphStyle:parStyle]; 
[parStyle release]; 

// Set text 
[textView setString:string]; 

// add NSTextView to border view 
[borderView addSubview:textView]; 
[textView release]; 

// add NSBox to view you want text view displayed in 
[self addSubview:borderView]; 
[borderView release]; 
+0

請記住,NSTextField會略微收縮文本,如果它接近擬合而不截斷。 [這兩個文本字段都有相同大小的字體。](http://i.stack.imgur.com/wrJtj.png) –

+1

@JohnSauer好點。這實際上也發生在NSTextViews上。這是截斷算法的默認行爲,在截斷之前嘗試將字符移近一起。在我的第二次編輯中,我通過使用'NSMutableParagraphStyle'類的'setTighteningFactorForTruncation:'方法來阻止這種情況的發生。 – Mathew

+0

感謝您的回答,我會盡快嘗試,我會讓你知道 –

0

我想你可以通過查看文本框的字段編輯器來完成它。你在controlTextDidBeginEditing中檢查它的寬度,然後再在controlTextDidEndEditing中檢查它的寬度。如果後者的值較大,則文本已被截斷。在文本字段的委託實現以下(我創建了initialWidth伊娃):

- (void)controlTextDidBeginEditing:(NSNotification *)aNotification { 
    if (! initialWidth) 
     initialWidth = ((NSTextView *)aNotification.userInfo[@"NSFieldEditor"]).frame.size.width; 
} 


- (void)controlTextDidEndEditing:(NSNotification *)aNotification { 
    if (initialWidth) { //Make sure that beginEditing is called first 
     NSInteger finalWidth = ((NSTextView *)aNotification.userInfo[@"NSFieldEditor"]).frame.size.width; 
     if (finalWidth - initialWidth > 1) NSLog(@"We have truncation"); 
     NSLog(@"Final: %ld Initial: %ld", finalWidth,initialWidth); 
    } 
} 

這似乎工作的大部分時間,包括如果你在一個長字符串,然後刪除,直到它再次配合。在少數情況下,當我是文本字段末尾的一個字符時,它給了我日誌消息,但編輯結束時我沒有得到省略號。

9

對於未來的訪問者,您可以使用-[NSCell expansionFrameWithFrame:inView:]方法來確定截斷是否發生。從標題開始:

如果cellFrame對於視圖中的整個內容而言太小,則允許該單元格返回擴展單元框架。 ... <剪輯> ...如果框架不是太小 小,返回一個空的矩形,並沒有擴展工具提示視圖將 顯示。默認情況下,NSCell返回NSZeroRect,而某些子類 (如NSTextFieldCell)將在需要時返回適當的幀。

總之,可以看出該NSTextField被截斷這樣的:使用ipmcc

NSRect expansionRect = [[self cell] expansionFrameWithFrame: self.frame inView: self]; 
    BOOL truncating = !NSEqualRects(NSZeroRect, expansionRect); 
+2

這是最好的解決方案 – jimwan

+0

您能否提供一個Swift 3解決方案?我無法修改Obj-C代碼。 – ixany

-1

夫特4溶液作爲鹼

它將調整逐一直到它適合或fontSize = 3

var size_not_ok = true 

var conter = 0 
let mininum_font_size = 3 // will resize ultil 3 
while size_not_ok || conter < 15 { // will try 15 times maximun 
    let expansionRect = le_nstextfield.expansionFrame(withFrame: le_nstextfield.frame) 

    let truncated = !NSEqualRects(NSRect.zero, expansionRect) 

    if truncated { 

     if let actual_font_size : CGFloat = le_nstextfield.font?.fontDescriptor.object(forKey: NSFontDescriptor.AttributeName.size) as? CGFloat { 

      le_nstextfield.font = NSFont.systemFont(ofSize: actual_font_size - 1) 

      if actual_font_size < mininum_font_size { 
       break 
      } 
     } 
    } else {   
     size_not_ok = false 
    } 
    conter = conter + 1 
}