- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在看似微不足道的设置中,我遇到了一个无法消除的可选NSTextField和NSColorPanel之间的不良相互作用,这使我发疯。
设置如下:在一个窗口中,我有一个可选的多行标签(实际上是一个NSTextField)和一个NSColorWell。
Color Well允许用户在GUI中为几何对象着色;它与文本无关。当然,点击好颜色会激活它,即调出共享的NSColorPanel并将颜色很好地连接到它。
文本字段完全独立于GUI中的彩色对象,并向用户显示数据。它是只读的,即不可编辑。由于数据是按列组织的,因此我使用选项卡进行文本格式设置,并使用NSTextField的setAttributedStringValue:
方法显示数据。
乍一看,一切都可以在如此简单的设置中按预期进行。
但是有一个难题:我希望用户能够复制文本字段中的数据以在其他地方进行处理。因此,NSTextField必须是可选的。并将其设置为selectable
是问题开始的地方:
当用户单击可选文本字段以选择文本时,窗口的字段编辑器将接管工作,结果,属性文本的所有选项卡设置都将丢失,文本将被混合。防止这种情况的通常方法是将NSTextField的allowsEditingTextAttributes
属性设置为YES
。如果执行此操作,则用户选择文本时将保留选项卡格式。但是现在NSColorPanel(如果可见)也无意间也切换为文本颜色(始终为黑色),并且如果颜色处于活动状态(连接到NSColorPanel),它将保持活动状态,从而将所有几何GUI对象的颜色更改为黑色。哎哟!
我找不到将NSTextField的selectable
和allowsEditingTextAttributes
属性设置为YES
的方法,但是仍然阻止它与NSColorPanel通信。
显而易见的替代方法是,即使将allowsEditingTextAttributes
设置为NO
,也可以保留选定文本的选项卡格式(根据需要将颜色面板与文本字段断开连接)。但是我也没有成功,尽管我真的不明白为什么:
我的想法是将所需的选项卡设置为文本字段的字段编辑器的defaultParagraphStyle
。因此,我设置了一个定制的字段编辑器:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
NSArray *myTabs = @[
[[NSTextTab alloc] initWithType:NSRightTabStopType location:100],
[[NSTextTab alloc] initWithType:NSRightTabStopType location:200],
[[NSTextTab alloc] initWithType:NSRightTabStopType location:300]
];
NSMutableParagraphStyle *myParagraphStyle = [[NSMutableParagraphStyle defaultParagraphStyle] mutableCopy];
[myParagraphStyle setTabStops:myTabs];
myFieldEditor = [NSTextView new]; // myFieldEditor is an instance variable
[myFieldEditor setDefaultParagraphStyle:myParagraphStyle];
[window setDelegate:self];
[window fieldEditor:YES forObject:myTextField];
}
windowWillReturnFieldEditor:toObject:
委托方法中的文本字段中激活它:
- (id)windowWillReturnFieldEditor:(NSWindow *)sender toObject:(id)client
{
if (client == myTextField) return myFieldEditor;
return nil;
}
@implementation myTextFieldCell
- (NSText *)setUpFieldEditorAttributes:(NSText *)textObj
{
NSTextView *newTextObj = (NSTextView*)[super setUpFieldEditorAttributes:textObj];
NSLog(@"STYLE: %@", [newTextObj defaultParagraphStyle]);
return newTextObj;
}
@end
2017-11-02 11:51:07.432 Demo[94807:303] STYLE: Alignment 4, LineSpacing 0, ParagraphSpacing 0, ParagraphSpacingBefore 0, HeadIndent 0, TailIndent 0, FirstLineHeadIndent 0, LineHeight 0/0, LineHeightMultiple 0, LineBreakMode 0, Tabs (
100R,
200R,
300R
), DefaultTabInterval 0, Blocks (null), Lists (null), BaseWritingDirection -1, HyphenationFactor 0, TighteningFactor 0.05, HeaderLevel 0
allowsEditingTextAttributes
属性设置为
YES
,则在选择文本时会保留选项卡格式,但是GUI中我的彩色对象无意间变成了黑色。如果将
allowsEditingTextAttributes
属性设置为
NO
,则彩色面板的行为应达到预期,但是一旦选择文本,选项卡格式就会丢失。
最佳答案
好的,因此我得到了@Willeke(感谢!)在他对我的问题的评论中的建议:使用NSTextView而不是NSTextField来实现我的多行标签。
我将首先总结一下为什么似乎无法使用NSTextField来完成我想做的事情,然后再使用NSTextView解决方案。
为什么NSTextField不起作用
如前所述,我解决方案的想法是为NSTextField自定义字段编辑器,设置所需的制表位,这样就不必将NSTextField的allowsEditingTextAttributes
属性设置为YES
(这会无意中将文本字段耦合到颜色面板)。我希望,这样可以在我在文本字段中选择文本并激活字段编辑器时保留属性字符串的段落样式的制表位。
广泛的测试表明,此操作不可行有以下几个原因:
正如@Willeke指出的那样,将NSTextView的usesFontPanel
属性设置为NO
也会断开文本视图与颜色面板的连接(根据需要)。但是,这不适用于作为NSTextField字段编辑器的NSTextView,因为在这种情况下,此设置始终被NSTextField的allowsEditingTextAttributes
属性覆盖:如果allowsEditingTextAttributes
为YES
,则字体和彩色面板是不考虑usesFontPanel
的值而耦合的;如果值为NO
,则字体和彩色面板是不考虑usesFontPanel
值的耦合的。
无论如何,使用自定义字段编辑器的制表位而不是使用我的属性字符串的段落样式的制表位(需要allowsEditingTextAttributes
为YES
)的想法无论如何都不会起作用,因为制表位会停止设置显然,无论allowsEditingTextAttributes
属性的值如何,NSTextField都会始终完全忽略字段编辑器。 NSTextField始终使用均匀间隔的默认制表位。
从激烈的谷歌搜索来看,另一个变体-将allowsEditingTextAttributes
设置为YES
但以某种方式修改NSColorPanel使其仍然不连接到NSTextField-如果不使用NSColorPanel的私有方法,则无法实现。
如何使用NSTextView实施解决方案
尽管实例化嵌入在剪辑视图和滚动视图中的完整NSTextView只是为了获得文本字段的功能似乎有些矫kill过正,但最终,它是最简单(甚至唯一可能)的解决方案。
要使滚动视图消失,您必须基本上取消选中IB中NSScrollView的“属性”检查器中的所有内容,尤其是“显示垂直滚动条”。将“绘制背景”和边框类型设置为所需的外观;如果您想模仿多行标签(就像我一样),请取消选中“绘制背景”,然后选择不可见的边框类型。在嵌入式NSTextView的“属性”检查器中,还要取消选中“可选”以外的所有属性,尤其是“使用字体面板”。
确保NSTextView的大小足以容纳完整的内容字符串,以避免意外的滚动效果并固定文本位置。如果您的内容字符串以行制动器结尾,则您需要有足够的空间在其下方留空行。如果您没有取消选中“绘制背景”,并且看起来不理想,请不要绘制NSScrollView或NSTextView的背景,为NSScrollView选择不可见的边框,然后在其下放置所需大小和外观的NSBox 。
您现在可以使用以下方式设置属性内容字符串:
[[myTextView textStorage] setAttributedString:myAttributedString];
editable
属性设置为
NO
,但这确实起作用。
refusesFirstResponder
属性设置为
YES
。但是NSTextView不继承自NSControl,因此没有此属性。因此,最后,我们必须对NSTextView进行子类化,以添加
refusesFirstResponder
属性。
becomeFirstResponder
,如下所示:
- (BOOL)becomeFirstResponder
{
if (!_refusesFirstResponder) return [super becomeFirstResponder];
NSEvent *event = [NSApp currentEvent];
if ([event type] == NSLeftMouseDown || [event type] == NSRightMouseDown) return [super becomeFirstResponder];
NSView *validKeyView = ([event modifierFlags] & NSShiftKeyMask)? [[[self previousValidKeyView] previousValidKeyView] previousValidKeyView] : [self nextValidKeyView];
[[NSOperationQueue mainQueue] addOperationWithBlock:^{[[self window] makeFirstResponder:validKeyView];}];
return NO;
}
refusesFirstResponder
是
NO
,我们只返回super的实现。
YES
,我们将检查NSTextView是否由于鼠标单击而成为第一响应者。如果是这样,我们还可以简单地返回super的实现,从而允许使用鼠标选择文本。
NO
,拒绝成为第一响应者。确定上一个键视图有些棘手,因为最接近的上一个键视图是我们不想要或不需要的嵌入式NSClipView,但是必须使用,因为Interface Builder不提供“纯” NSTextView。然后是嵌入的NSScrollView,然后才是我们真正想要的上一个键视图。
makeFirstResponder:
,而必须将其推迟到运行循环的下一个迭代中。
refusesFirstResponder
,我们仍然必须模仿NSTextField的行为,以在失去第一响应者状态时取消所有文本选择。我们可以在NSText委托方法中做到这一点。假设我们不需要其他委托功能,则可以使子类成为自己的委托,并添加以下委托方法:
- (void)textDidEndEditing:(NSNotification*)notification
{
[[notification object] setSelectedRange:NSMakeRange(UINT64_MAX, 0)];
}
setAttributedString:
便捷方法。
#import <Cocoa/Cocoa.h>
IB_DESIGNABLE
@interface MyTextFieldLikeTextView : NSTextView <NSTextViewDelegate>
@property IBInspectable BOOL refusesFirstResponder;
- (void)setAttributedString:(NSAttributedString*)attributedString;
@end
#import "MyTextFieldLikeTextView.h"
@implementation MyTextFieldLikeTextView
- (void)awakeFromNib
{
[self setDelegate:self];
}
- (BOOL)becomeFirstResponder
{
if (!_refusesFirstResponder) return [super becomeFirstResponder];
NSEvent *event = [NSApp currentEvent];
if ([event type] == NSLeftMouseDown || [event type] == NSRightMouseDown) return [super becomeFirstResponder];
NSView *validKeyView = ([event modifierFlags] & NSShiftKeyMask)? [[[self previousValidKeyView] previousValidKeyView] previousValidKeyView] : [self nextValidKeyView];
[[NSOperationQueue mainQueue] addOperationWithBlock:^{[[self window] makeFirstResponder:validKeyView];}];
return NO;
}
- (void)textDidEndEditing:(NSNotification*)notification
{
[[notification object] setSelectedRange:NSMakeRange(UINT64_MAX, 0)];
}
- (void)setAttributedString:(NSAttributedString*)attributedString
{
[[self textStorage] setAttributedString:attributedString];
}
@end
关于cocoa - 可选的NSTextField和NSColorPanel –如何打破它们不希望的相互作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47075982/
我打算在 AngularJS 中尝试一个项目,其中所有组件都将使用 Polymer 开发。现在在开始这个项目之前,我有几个疑问: 在使用 Angular 服务获取数据后,我可以更新 Polymer 组
假设我有多个线程正在从文件中读取,并且我想确保在任何时间点只有一个线程正在从文件中读取。 实现这一点的一种方法是使用 mvar :: MVar ()并确保如下互斥: thread = do ..
对于只有因子列的给定数据框,我想列出数据中没有出现的最多 m 个属性的所有因子组合。下面是一个简单的例子: d cc unlist(cc, recursive=F) -> cc length(cc)
对于相关图,我希望有一个光学正方形图(x 和 y 的像素长度相同),但 x 和 y 也有一定的轴限制。我可以分别获取这两个,但不能同时获取: import matplotlib.pyplot as p
对于相关图,我希望有一个光学正方形图(x 和 y 的像素长度相同),但 x 和 y 也有一定的轴限制。我可以分别获取这两个,但不能同时获取: import matplotlib.pyplot as p
关闭。这个问题是opinion-based .它目前不接受答案。 想改善这个问题吗?更新问题,以便可以通过 editing this post 用事实和引文回答问题. 7年前关闭。 Improve t
我是一名优秀的程序员,十分优秀!