强制 NSView 程序化重绘

7

我的应用有两种不同的状态,每种状态都将用一个NSView来表示。

因此,每次只会显示一个视图,问题在于当我在视图之间切换时,应用程序直到我手动调整窗口大小后才会显示新状态!

我搜索了这个问题并提出了不止一种解决方案,但是没有一种适用于我:

[myView setNeedsDisplay:YES];
[myView display];
[[myView.window contentView] setNeedsDisplay:YES];


[mySubView1 setHidden:YES]; || [mySubView1 removeFromSuperView];

我甚至将myView定义为Outlet,但仍然没有效果。

这是我的代码:

if (appState == 1) {

    [self.splitView setFrameSize:CGSizeMake(self.splitView.frame.size.width, self.view.frame.size.height - 250)];

    [self.mySubView1 setHidden:NO];
    [self.mySubView2 setHidden:YES];

    [self.mySubView2 removeFromSuperview];
    [self.mySubView1 addSubview:self.inCallView];
}
else
{
    [self.splitView setFrameSize:CGSizeMake(self.splitView.frame.size.width, self.view.frame.size.height - 70)];

    [self.mySubView1 setHidden:YES];
    [self.mySubView2 setHidden:NO];

    [self.mySubView1 removeFromSuperview];
    [self.mySubView2 addSubview:self.chatHeaderView];
}
// I need to redraw here
[self.view setNeedsDisplay:YES];
[self.mySubView1 setNeedsDisplay:YES];
[self.mySubView2 setNeedsDisplay:YES];
// and nothing happened until I resize my window manually 

3
setNeedsDisplay:YES 是正确的方法。 - trojanfoe
我尝试了一下,可惜没有成功 :( - Ahmed Khalaf
请使用它,并在您使用它的代码中展示,其他人可以从那里获取,我相信。 - trojanfoe
2个回答

9
我发现了,代码本身没有问题,不需要调用任何重绘方法,唯一的问题是任何UI操作都必须在主线程中完成

所以最终代码将会是:

dispatch_async( dispatch_get_main_queue(), ^{
    if (appState == 1) {
        [self.splitView setFrameSize:CGSizeMake(self.splitView.frame.size.width, self.view.frame.size.height - 250)];

        [self.mySubView1 setHidden:NO];
        [self.mySubView2 setHidden:YES];
    }
    else
    {
        [self.splitView setFrameSize:CGSizeMake(self.splitView.frame.size.width, self.view.frame.size.height - 70)];

        [self.mySubView1 setHidden:YES];
        [self.mySubView2 setHidden:NO];
    }
});

谢谢,各位。

2
进行子视图的删除或添加操作将自动调用setNeedsDisplay:YES,因此手动调用它没有效果并不奇怪。
一些需要检查的事项:
  1. 检查您的视图属性是否为nil值。我看到您正在删除视图,这将导致其父视图释放它,如果您没有使用强属性(或其他位置)保留它,则会被解除分配。
  2. 确保您没有与自动布局对抗。暂时关闭自动布局以确认它不会导致问题。
  3. 您只设置了框架大小。您需要确保它也具有预期的原点。
另外,如果您要删除视图,则不需要打扰调用setHidden:

谢谢Brad,我再次检查了您的所有要点;并且我想告诉您,当我手动调整窗口大小时,一切都很好(窗口会自动重绘)。是的,没有必要使用setHidden-我会将其删除-。再次感谢 :) - Ahmed Khalaf
不,问题是我必须手动调整窗口大小才能得到结果。这意味着它不是nil;自动布局和原点也正如预期的那样。我只想重新绘制它,而不需要让用户改变窗口大小。 - Ahmed Khalaf

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接