尝试在运行时更改 CroppedBitmap 的 SourceRect
当我尝试在运行时更改 CroppedBitmap 的 SourceRect 属性时,没有任何反应。 没有错误,并且属性值实际上没有改变。
我正在尝试制作精灵动画。 我有一个包含精灵表的 BitmapSource,它是一个包含精灵不同姿势网格的单个位图。 然后我有一个 CroppedBitmap,它以 spritesheet 作为其源,还有一个 SourceRect,它从 spritesheet 中提取其中一个姿势。 在运行时,当我想要制作动画时,我尝试更改 CroppedBitmap 的 SourceRect 属性,以从较大的位图中拉出不同的姿势; 但是,如上所述,新的财产价值根本不存在。 这是最奇怪的事情。
下面是一些示例 XAML:
<UserControl.Resources>
<BitmapImage x:Key="spritesheet" UriSource="Sprites/elf.png"/>
</UserControl.Resources>
<Image>
<Image.Source>
<CroppedBitmap x:Name="image" Source="{StaticResource spritesheet}"
SourceRect="240 640 240 320"/>
</Image.Source>
</Image>
代码隐藏尝试执行此操作:
var newRect = new Int32Rect(...);
Debug.WriteLine(" Before: " + image.SourceRect);
Debug.WriteLine("Assigning new value: " + newRect);
image.SourceRect = newRect;
Debug.WriteLine(" After: " + image.SourceRect);
这给了我这个调试输出:
Before: 240,640,240,320
Assigning new value: 240,0,240,320
After: 240,640,240,320
所以它实际上将新矩形(Y=0)分配到属性中; 没有例外; 但之后,属性值根本没有改变(Y 仍然是 640)。
关于为什么会发生这种情况以及如何解决它有什么想法吗?
When I try to change a CroppedBitmap's SourceRect property at runtime, nothing happens. There's no error, and the property value doesn't actually get changed.
I'm trying to do sprite animation. I have a BitmapSource that contains a spritesheet, which is a single bitmap containing a grid of different poses for the sprite. Then I have a CroppedBitmap that has the spritesheet as its Source, and a SourceRect that pulls one of the poses out of the spritesheet. At runtime, when I want to animate, I'm trying to change the CroppedBitmap's SourceRect property, to pull a different pose out of the larger bitmap; but, as noted above, the new property value simply doesn't stick. It's the weirdest thing.
Here's some sample XAML:
<UserControl.Resources>
<BitmapImage x:Key="spritesheet" UriSource="Sprites/elf.png"/>
</UserControl.Resources>
<Image>
<Image.Source>
<CroppedBitmap x:Name="image" Source="{StaticResource spritesheet}"
SourceRect="240 640 240 320"/>
</Image.Source>
</Image>
And the codebehind tries to do this:
var newRect = new Int32Rect(...);
Debug.WriteLine(" Before: " + image.SourceRect);
Debug.WriteLine("Assigning new value: " + newRect);
image.SourceRect = newRect;
Debug.WriteLine(" After: " + image.SourceRect);
That gives me this debug output:
Before: 240,640,240,320
Assigning new value: 240,0,240,320
After: 240,640,240,320
So it's actually assigning the new rectangle (with Y=0) into the property; there's no exception; but afterward, the property value simply didn't change (Y is still 640).
Any ideas about why this happens, and how to fix it?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我最终找到了答案。 从 CroppedBitmap 的文档中:
只是为了好玩,我尝试在我的方法中添加 BeginInit()..EndInit() 调用,看看是否可以会使其可修改。 毫不奇怪,我得到了 InvalidOperationException(“无法多次设置初始化状态”)。
所以 CroppedBitmap 实际上是不可变的。(但是他们忽略了自己的 Freezable 系统,该系统会抛出异常来告诉我我做错了什么,并实现了更多令人惊讶。)
这意味着,不能继续更改 SourceRect 属性。 我需要为 spritesheet 中的每个子图像创建一个单独的 CroppedBitmap 实例。
I eventually found the answer. From the documentation for CroppedBitmap:
Just for fun, I tried adding BeginInit()..EndInit() calls in my method, to see if that would make it modifiable. Not surprisingly, I got an InvalidOperationException ("Cannot set the initializing state more than once").
So CroppedBitmap is effectively immutable. (But they ignored their own Freezable system, which would have thrown an exception to tell me I was doing something wrong, and implemented something more surprising instead.)
Which means, no-go on changing the SourceRect property. I'll need to create a separate CroppedBitmap instance for each sub-image within the spritesheet.
这是处理此问题的另一种方法:
不要使用
CroppedBitmap
,而是使用完整的源图像,但是:image.RenderTransform
来调整可视区域。Image.Clip
,以避免显示不需要的图像部分。这意味着您不需要不断制作新的
CroppedBitmaps
,只需调整变换即可。在我的测试中,我发现无论哪种方式,速度都没有差异。
为了完整起见,我将如何调整您的代码以执行我的建议:
然后,稍后执行与调整
SourceRect
等效的调用是:Here is an alternate way to deal with this:
Instead of using a
CroppedBitmap
, use the full source image, but:image.RenderTransform
to adjust the viewable area.Image.Clip
if necessary, to avoid showing portions of the image that are unwanted.This means that you don't need to keep making new
CroppedBitmaps
, you can just adjust the transform.In my testing, I saw no difference in speed doing it either way.
For completeness, here's how I'd adjust your code to do what I'm suggesting:
Then the later call to do the equivalent of adjusting the
SourceRect
is:以下是使用
IMultiValueConverter
的方法:性能可能较差。
Here is a way using
IMultiValueConverter
:Potentially poor perf.