NSControl 在全屏模式下附加到 NSView 的 NSView 上闪烁

发布于 2024-11-29 04:20:37 字数 5392 浏览 1 评论 0原文

设置:

  1. 我的应用程序有背景视图,使用enterFullScreenMode:withOptions:将其设置为全屏模式。
  2. 对于这些背景视图,我使用removeFromSuperviewaddSubview:内容视图移动为子视图。
  3. 此外,还有一个首选项视图,我将其添加到内容视图,如前所述。
    首选项视图来自 XIB,包含 NSControls,例如复选框、圆形幻灯片、组合框......

整个设置要复杂得多,这使得发布非常困难代码在这里。不过,如果您要求的话,我会添加一些部分。

问题:
当我选择首选项视图上的任何控件时,元素会闪烁。这意味着复选框会消失并重新出现。 我已经尝试解决在视图的 viewDidMoveToSuperview 方法中运行 setNeedsDisplay:setNeedsLayoutmakeKeyAndOrderFront: 的问题。然而,没有任何帮助。我能做些什么?


编辑1: 我截取了应用程序的屏幕截图,以便您可以看到发生了什么。


编辑2:
这是 PreferencesViewController.h

//  PreferencesViewController.h

#import <Cocoa/Cocoa.h>
#import "SlideShowModelProtocol.h"
#import "DisplayInfoController.h"

@interface PreferencesViewController : NSViewController {
    id<SlideShowModelProtocol> m_localModel;
    DisplayInfoController* m_displayInfoController;
}

@property (readonly) id<SlideShowModelProtocol> localModel;
@property (readwrite, assign) IBOutlet DisplayInfoController* displayInfoController;

- (void)moveViewToSuperview:(NSView*)superview;
- (void)showOnView:(NSView*)superview;
- (void)removeViewFromSuperview;
- (BOOL)viewHasSuperview;
- (void)updateModelSettings;
- (IBAction)cancelView:(id)sender;
- (IBAction)confirmView:(id)sender;

@end

...以及实现 PreferencesViewController.m

//  PreferencesViewController.m

#import "PreferencesViewController.h"
#import "ApplicationController.h"
#import "DisplayInfo.h"


@interface PreferencesViewController()

- (void)centerViewOnSuperview;
- (void)loadModel;

@end

@implementation PreferencesViewController


- (id)init {
    self = [super initWithNibName:@"PreferencesView" bundle:nil];
    if (self != nil) {
        m_localModel = nil;
        m_displayInfoController = nil; // Assigned in Interface Builder.
    }
    return self;
}

@synthesize localModel = m_localModel;
@synthesize displayInfoController = m_displayInfoController;

- (void)loadModel {
    [self willChangeValueForKey:@"localModel"];
    // Retrieve deep copy of the model.
    m_localModel = [[[ApplicationController sharedController] model] copyWithZone:nil];
    // Reset the table view selection as saved in the model.
    NSIndexSet* selectionIndices = [NSIndexSet indexSetWithIndex:[[m_localModel selectedScreenIndex] unsignedIntegerValue]];
    [[m_displayInfoController displayInfoTableView] selectRowIndexes:selectionIndices byExtendingSelection:NO];
    [self didChangeValueForKey:@"localModel"];
}

/**
    Moves and positions the view on the given superview (aka another screen).
    @param superview A superview.
 */
- (void)showOnView:(NSView*)superview {
    [self moveViewToSuperview:superview];
    [self centerViewOnSuperview];
}

/**
    Moves the view on the given superview.
    @param superview A superview (In full screen mode a background view).
 */
- (void)moveViewToSuperview:(NSView*)superview {
    if ([[self view] superview] == superview) {
        return;
    }
    [self loadModel];
    [[self view] removeFromSuperview];
    [superview addSubview:[self view]];
}

- (void)removeViewFromSuperview {
    [[self view] removeFromSuperview];
}


- (void)centerViewOnSuperview {
    NSRect superviewFrame = self.view.superview.frame;
    NSRect viewFrame = self.view.frame;
    float viewFrameWidth = viewFrame.size.width;
    float viewFrameHeight = viewFrame.size.height;
    float xPos = 0.5f * superviewFrame.size.width - 0.5f * viewFrameWidth;
    float yPos = 0.5f * superviewFrame.size.height - 0.5f * viewFrameHeight;
    NSRect frame = NSMakeRect(xPos, yPos, viewFrameWidth, viewFrameHeight);
    [self.view setFrame:frame];
}

- (BOOL)viewHasSuperview {
    return [[self view] superview] != nil;
}

- (void)updateModelSettings {
    id<SlideShowModelProtocol> globalModel = [[ApplicationController sharedController] model];
    [globalModel setFadeDuration:[m_localModel fadeDuration]];
    [globalModel setStayDuration:[m_localModel stayDuration]];
    [globalModel setStartWithFirst:[m_localModel startWithFirst]];
    [globalModel setSortingMode:[m_localModel sortingMode]];
    [globalModel setAnimationIsActive:[m_localModel animationIsActive]];
    [globalModel setSelectedScreenIndex:[m_localModel selectedScreenIndex]];
    [globalModel setPanAmount:[m_localModel panAmount]];
    [globalModel setZoomAmount:[m_localModel zoomAmount]];
    [globalModel setZoomFactor:[m_localModel zoomFactor]];
}

#pragma mark -
#pragma mark UserInterface

- (IBAction)cancelView:(id)sender {
    [[ApplicationController sharedController] hidePreferencesViewModelSettingsUpdated:NO];
}

- (IBAction)confirmView:(id)sender {
    ApplicationController* applicationController = [ApplicationController sharedController];
    if ([[applicationController model] isEqualToModel:m_localModel]) {
        [self cancelView:sender];
        return;
    }
    [self updateModelSettings];
    [applicationController hidePreferencesViewModelSettingsUpdated:YES];
}

@end

The setup:

  1. My application has background views that are set into full screen mode using enterFullScreenMode:withOptions:.
  2. To these background views I move a content view as a subview using removeFromSuperview and addSubview:.
  3. Further, there is a preferences view that I add to the content view as described before.
    The preferences view comes from a XIB and contains NSControls like checkboxes, circular slides, combo box, ...

The whole setup is much more complicated which makes it very difficult to post code here. Nevertheless, I will add some parts if you request them.

The problem:
When I select any of the controls on the preferences view the elements flicker. That means the checkbox for example disappears and reappears.
I already tried to solve the problem running setNeedsDisplay:, setNeedsLayout or makeKeyAndOrderFront: in the viewDidMoveToSuperview method of the view. Though, nothing helped. What can I do?


Edit 1:
I took a screen capture of the application so you can see what happens.


Edit 2:
Here is the PreferencesViewController.h:

//  PreferencesViewController.h

#import <Cocoa/Cocoa.h>
#import "SlideShowModelProtocol.h"
#import "DisplayInfoController.h"

@interface PreferencesViewController : NSViewController {
    id<SlideShowModelProtocol> m_localModel;
    DisplayInfoController* m_displayInfoController;
}

@property (readonly) id<SlideShowModelProtocol> localModel;
@property (readwrite, assign) IBOutlet DisplayInfoController* displayInfoController;

- (void)moveViewToSuperview:(NSView*)superview;
- (void)showOnView:(NSView*)superview;
- (void)removeViewFromSuperview;
- (BOOL)viewHasSuperview;
- (void)updateModelSettings;
- (IBAction)cancelView:(id)sender;
- (IBAction)confirmView:(id)sender;

@end

... and the implementation PreferencesViewController.m:

//  PreferencesViewController.m

#import "PreferencesViewController.h"
#import "ApplicationController.h"
#import "DisplayInfo.h"


@interface PreferencesViewController()

- (void)centerViewOnSuperview;
- (void)loadModel;

@end

@implementation PreferencesViewController


- (id)init {
    self = [super initWithNibName:@"PreferencesView" bundle:nil];
    if (self != nil) {
        m_localModel = nil;
        m_displayInfoController = nil; // Assigned in Interface Builder.
    }
    return self;
}

@synthesize localModel = m_localModel;
@synthesize displayInfoController = m_displayInfoController;

- (void)loadModel {
    [self willChangeValueForKey:@"localModel"];
    // Retrieve deep copy of the model.
    m_localModel = [[[ApplicationController sharedController] model] copyWithZone:nil];
    // Reset the table view selection as saved in the model.
    NSIndexSet* selectionIndices = [NSIndexSet indexSetWithIndex:[[m_localModel selectedScreenIndex] unsignedIntegerValue]];
    [[m_displayInfoController displayInfoTableView] selectRowIndexes:selectionIndices byExtendingSelection:NO];
    [self didChangeValueForKey:@"localModel"];
}

/**
    Moves and positions the view on the given superview (aka another screen).
    @param superview A superview.
 */
- (void)showOnView:(NSView*)superview {
    [self moveViewToSuperview:superview];
    [self centerViewOnSuperview];
}

/**
    Moves the view on the given superview.
    @param superview A superview (In full screen mode a background view).
 */
- (void)moveViewToSuperview:(NSView*)superview {
    if ([[self view] superview] == superview) {
        return;
    }
    [self loadModel];
    [[self view] removeFromSuperview];
    [superview addSubview:[self view]];
}

- (void)removeViewFromSuperview {
    [[self view] removeFromSuperview];
}


- (void)centerViewOnSuperview {
    NSRect superviewFrame = self.view.superview.frame;
    NSRect viewFrame = self.view.frame;
    float viewFrameWidth = viewFrame.size.width;
    float viewFrameHeight = viewFrame.size.height;
    float xPos = 0.5f * superviewFrame.size.width - 0.5f * viewFrameWidth;
    float yPos = 0.5f * superviewFrame.size.height - 0.5f * viewFrameHeight;
    NSRect frame = NSMakeRect(xPos, yPos, viewFrameWidth, viewFrameHeight);
    [self.view setFrame:frame];
}

- (BOOL)viewHasSuperview {
    return [[self view] superview] != nil;
}

- (void)updateModelSettings {
    id<SlideShowModelProtocol> globalModel = [[ApplicationController sharedController] model];
    [globalModel setFadeDuration:[m_localModel fadeDuration]];
    [globalModel setStayDuration:[m_localModel stayDuration]];
    [globalModel setStartWithFirst:[m_localModel startWithFirst]];
    [globalModel setSortingMode:[m_localModel sortingMode]];
    [globalModel setAnimationIsActive:[m_localModel animationIsActive]];
    [globalModel setSelectedScreenIndex:[m_localModel selectedScreenIndex]];
    [globalModel setPanAmount:[m_localModel panAmount]];
    [globalModel setZoomAmount:[m_localModel zoomAmount]];
    [globalModel setZoomFactor:[m_localModel zoomFactor]];
}

#pragma mark -
#pragma mark UserInterface

- (IBAction)cancelView:(id)sender {
    [[ApplicationController sharedController] hidePreferencesViewModelSettingsUpdated:NO];
}

- (IBAction)confirmView:(id)sender {
    ApplicationController* applicationController = [ApplicationController sharedController];
    if ([[applicationController model] isEqualToModel:m_localModel]) {
        [self cancelView:sender];
        return;
    }
    [self updateModelSettings];
    [applicationController hidePreferencesViewModelSettingsUpdated:YES];
}

@end

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

浅浅 2024-12-06 04:20:37

正如我的帖子的评论中已经告诉我的,我创建了一个新的 PreferencesViewTest.xib 并逐步添加了 GUI 控件。我还添加了绑定、控制器等。一切工作正常——没有闪烁。然后我将RETURN指定为Interface Builder中OK按钮的等效键。我再次启动应用程序来检查行为......它闪烁!我通过从确定按钮中删除等效键来仔细检查以前的PreferencesView.xib的现象......它不会闪烁! - 疯狂的狗屎。但为什么..?

As already told in the comments to my post I created a new PreferencesViewTest.xib and added the GUI controls step by step. I also added the bindings, controllers and so on. Everything worked fine - no flickering. Then I assigned RETURN as the key equivalent for the OK button in Interface Builder. I started the application once again to check the behavior .... it flickers! I double checked the phenomenon with the former PreferencesView.xib by removing the key equivalent from the OK button .... it does not flicker! - Crazy shit. But why..?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文