原文:WPF 线段Line过长渲染出现的问题

在使用WPF的时候,可以做一个实验,在canvas里添加一条线段Line,StrokeThickness属性设置为1,然后通过放大canvas或者调整line起终点,将线段变得很长,你会发现一个奇怪的问题:线段不见了。当你把StrokeThickness设置成2时,它又出现了。

CodeProject和StackOverFlow上也有人提出过类似的问题:

==========================================================================================================================================

http://www.codeproject.com/Questions/192350/Elements-disappearing-on-large-Canvas 

I have a large Canvas which can be scrolled horizontally. My Canvas contains little lines (StrokeThickness = 1) positioned uniformly. 

When I scroll to right the lines start to disappear and appear when reaching an horizontal offset of 8.000.000 (more or less). How can I fix it?
 
Here an example. 10 lines to left, 10 lines to right. The first lines are visible while the last ones are partially visible (5 visible, 5 not).

<Window x:Class="WpfApplication.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Grid>
<ScrollViewer HorizontalScrollBarVisibility="Visible">
<Canvas Width="15000000">
<Line Canvas.Left="0" X1="0" X2="0" Y1="0" Y2="100" Stroke="Black" StrokeThickness="1" />
<Line Canvas.Left="5" X1="0" X2="0" Y1="0" Y2="100" Stroke="Black" StrokeThickness="1" />
<Line Canvas.Left="10" X1="0" X2="0" Y1="0" Y2="100" Stroke="Black" StrokeThickness="1" />
<Line Canvas.Left="15" X1="0" X2="0" Y1="0" Y2="100" Stroke="Black" StrokeThickness="1" />
<Line Canvas.Left="20" X1="0" X2="0" Y1="0" Y2="100" Stroke="Black" StrokeThickness="1" />
<Line Canvas.Left="25" X1="0" X2="0" Y1="0" Y2="100" Stroke="Black" StrokeThickness="1" />
<Line Canvas.Left="30" X1="0" X2="0" Y1="0" Y2="100" Stroke="Black" StrokeThickness="1" />
<Line Canvas.Left="35" X1="0" X2="0" Y1="0" Y2="100" Stroke="Black" StrokeThickness="1" />
<Line Canvas.Left="40" X1="0" X2="0" Y1="0" Y2="100" Stroke="Black" StrokeThickness="1" />
<Line Canvas.Left="45" X1="0" X2="0" Y1="0" Y2="100" Stroke="Black" StrokeThickness="1" />
<Line Canvas.Left="14999950" X1="0" X2="0" Y1="0" Y2="100" Stroke="Black" StrokeThickness="1" />
<Line Canvas.Left="14999955" X1="0" X2="0" Y1="0" Y2="100" Stroke="Black" StrokeThickness="1" />
<Line Canvas.Left="14999960" X1="0" X2="0" Y1="0" Y2="100" Stroke="Black" StrokeThickness="1" />
<Line Canvas.Left="14999965" X1="0" X2="0" Y1="0" Y2="100" Stroke="Black" StrokeThickness="1" />
<Line Canvas.Left="14999970" X1="0" X2="0" Y1="0" Y2="100" Stroke="Black" StrokeThickness="1" />
<Line Canvas.Left="14999975" X1="0" X2="0" Y1="0" Y2="100" Stroke="Black" StrokeThickness="1" />
<Line Canvas.Left="14999980" X1="0" X2="0" Y1="0" Y2="100" Stroke="Black" StrokeThickness="1" />
<Line Canvas.Left="14999985" X1="0" X2="0" Y1="0" Y2="100" Stroke="Black" StrokeThickness="1" />
<Line Canvas.Left="14999990" X1="0" X2="0" Y1="0" Y2="100" Stroke="Black" StrokeThickness="1" />
<Line Canvas.Left="14999995" X1="0" X2="0" Y1="0" Y2="100" Stroke="Black" StrokeThickness="1" />
</Canvas>
</ScrollViewer>
</Grid>
</Window>

Thanks,

 

部分回复:

Solution 1

Instead of using a canvas that's THAT frickin' wide, I'd be owner drawing only what's visible. You're just asking for trouble trying to do it this way. 

Since a monitor normally isn't any wider than about 2000 pixels, there's no point in making an image that's 15,000,000 pixels wide.

Solution 2

In this page http://connect.microsoft.com/VisualStudio/feedback/details/731467/disappearing-path-wp[^] you can find the reason of why the lines disappear.
I had the same problem, then i split the lines in function of its length

========================================================================================================================

http://stackoverflow.com/questions/9138891/long-lines-dont-render-correctly

I have a project with a canvas that the user can zoom and pan using the mouse. The origin is marked with a blue cross running through the canvas.

 As the user zooms in the line width of the markers is reduced to keep the them about 1 pixel wide on screen. However, after zooming in about 10x 

the origin lines abruptly disappear. It seems like the rendering engine is deciding that the line is too small to be displayed before applying the 

scaling transform.

What is strange is that when I do the same operation to a rectangle instead of a line I get the expected behavior (see the ScaleBox rectangle 

object in the code below). Any ideas on what is causing the problem and how to fix it would be welcome.

Here is the relevant XAML:

  <Canvas x:Name="MouseCapture" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="WhiteSmoke" >
<Canvas x:Name="ZoomPan">
<Canvas.RenderTransform >
<MatrixTransform x:Name="_zoomPanTransform" />
</Canvas.RenderTransform>
<Rectangle x:Name="ScaleBox" Width="100" Height="100" Canvas.Left="-50" Canvas.Top="-50" Stroke="Black"/>
<Line x:Name="YOrigin" X1="-5000" X2="5000" Y1="0" Y2="0" Stroke="Blue" />
<Line x:Name="XOrigin" X1="0" X2="0" Y1="-5000" Y2="5000" Stroke="Blue" />
</Canvas>
</Canvas>

And the code behind:

Private Sub ZoomControl_PreviewMouseWheel(sender As Object, e As System.Windows.Input.MouseWheelEventArgs) Handles MouseCapture.PreviewMouseWheel
Dim scale As Double
If e.Delta > 0 Then
scale = 0.95
Else
scale = 1 / 0.95
End If
Dim center As Point = e.GetPosition(MouseCapture)
Dim zoom As New ScaleTransform(scale, scale, center.X, center.Y)
_zoomPanTransform.Matrix *= zoom.Value
UpdateLineWidth()
End Sub Private Sub UpdateLineWidth()
ScaleBox.StrokeThickness = 1 / _zoomPanTransform.Matrix.M11
XOrigin.StrokeThickness = 1 / _zoomPanTransform.Matrix.M11
YOrigin.StrokeThickness = 1 / _zoomPanTransform.Matrix.M11
End Sub

Here is a screenshot when everything is working.

Here is a screenshot as 10x Zoom. The origin lines have disappeared abruptly, but the black box still shows up as expected. 

(Note that only one side of the black box is visible because the rest is outside the visible region because of the zoom.)

部分回复:

The problem was that the line was too long. If I reduce the length of the origin lines dynamically so that they are roughly the same length as the canvas, 

everything displays as expected. If the line gets to be 100x or so longer than the canvas they abruptly disappear. This is probably due to some rounding 

errors or optimization scheme.

=====================================================================================================================

从以上回复中我们可以找到一点信息:

http://connect.microsoft.com/VisualStudio/feedback/details/731467/disappearing-path-wp

问题:Path with linegeometry disappears

评论:

This is an interesting limit to the processing of WPF vector graphics - in both hardware and software. Empirically, it seems that horizontal or vertical lines 

are limited by some ratio related to their stroke thickness.

Here is a table I determined experimentally:

Stroke Thickness     Maximum Length (horizontal or vertical)

.07                 8750

.8                    100,000

.9                    112,500

1                     125,000

3                     375,000

5                     625,000

10                    1,250,000

100                 12,500,000

1000                 125,000,004

10000                 1,250,000,063

100000                12,500,000,255

This scenario seems to impact a very small number of customers, and there are a couple of workarounds:

1) Introduce a slight diagonal component dramatically increases the limit.

2) Break very long horizontal or vertical lines into pieces.

3) Tweak the thickness a bit.

We apologize for the inconvenience this issue has caused, and we hope you are still successful using WPF in your project.

============================================================================================================================

另外,我在MSDN上找到下面的资料,其中就提到了这一点注意事项:

MSDN: FrameworkElement. Width 属性

这是 FrameworkElement 上的三个用于指定宽度信息的属性之一。 另外两个是 MinWidth 和 MaxWidth。 如果这三个值之间存在冲突,则应用程序确定宽度的实际顺序是:首先必须采用 MinWidth;然后采用 MaxWidth;最后,如果这些值中的每个值都在限制之内,则采用 Width。 

此属性的返回值总是与为它设置的任何值相同。与之相反, ActualWidth 的值可能不同。 布局可能已经由于某个原因拒绝了建议的大小。另外,布局系统本身相对于属性系统的 Width 集以异步方式工作,因而可能尚未处理特定大小调整属性的更改。 

除了可接受的 Double 值以外,此属性还可以是 Double. NaN 。 此值可用来指定自动调整大小行为。在 XAML 中,可以将该值设置为字符串 "Auto"(不区分大小写)以启用自动调整大小行为。自动调整大小行为意味着元素将填满它可以利用的宽度。但请注意,特定控件通常通过它们的默认样式来提供默认值,以禁用自动调整大小行为,除非特地重新启用了该行为。

除了验证检查以外, Width 还有一个由布局系统实施的非确定性上限值(此值是一个非常大的数字,大于 Single. MaxValue ,但小于 Double. MaxValue )。 如果超出此上限值,元素将不会呈现,并且不会引发异常。不要将 Width 设置为一个远远大于任何可能的视觉显示的最大大小,否则有可能超出此非确定性上限。 

=============================================================================================================================

总的来说,问题出现的原因与WPF本身的机制有关,简单地分析就是因为line过长,超出了某个上限值,深层的原因还需要进一步了解。

WPF 线段Line过长渲染出现的问题的更多相关文章

  1. codeforces #345 (Div. 1) D. Zip-line (线段树+最长上升子序列)

    Vasya has decided to build a zip-line on trees of a nearby forest. He wants the line to be as long a ...

  2. Tunnel Warfare HDU - 1540(线段树最长连续区间)

    题意: 一条线上的点,D x是破坏这个点,Q x是表示查询以x所在的最长的连续的点的个数,R是恢复上一次破坏的点.   解析: 线段树结点 设置一个  lq记录区间左端点开始的最大连续个数,  rq ...

  3. HDU 3308 线段树 最长连续上升子序列 单点更新 区间查询

    题意: T个测试数据 n个数 q个查询 n个数 ( 下标从0开始) Q u v 查询 [u, v ] 区间最长连续上升子序列 U u v 把u位置改成v #include<iostream> ...

  4. Android OpenGL ES(九)绘制线段Line Segment .

    创建一个DrawLine Activity,定义四个顶点: float vertexArray[] = { -0.8f, -0.4f * 1.732f, 0.0f, -0.4f, 0.4f * 1.7 ...

  5. [WPF]DataGridHyperlinkColumn网址过长TextTrimming无效

    <DataGridHyperlinkColumn Binding="{Binding source}" Header="来源"> <DataG ...

  6. WPF 渲染级别 (Tier)

    在WPF中,显卡的功能相差很大.当WPF评估显卡时,它会考虑许多因素,包括显卡上的RAM数量.对像素着色器(piexl shader)的支持(计算每个像素效果的内置程序,如透明效果),以及对顶点着色器 ...

  7. WPF 渲染原理

    原文:WPF 渲染原理 在 WPF 最主要的就是渲染,因为 WPF 是一个界面框架.想用一篇博客就能告诉大家完整的 WPF 渲染原理是不可能的.本文告诉大家 WPF 从开发者告诉如何画图像到在屏幕显示 ...

  8. WPF 设置纯软件渲染

    最近看到有小伙伴说 WPF 使用硬件渲染,如何让 WPF 不使用硬件渲染,因为他觉得性能太好了.万一这个版本发布了,产品经理说下个版本要提升性能就不好了.于是就找到一个快速的方法,让程序不使用硬件渲染 ...

  9. WPF 基础 - 绘画 1) 线段、矩形、圆弧及填充色

    1. 绘画 1.1 图形类型 Line X1.Y1.X2.Y2,Stroke,StrokeThickness Rectangle 矩形 Ellipse 椭圆 Polygon 多边形(自动闭合) Pol ...

随机推荐

  1. html5绘图工具选择

    1. Chart.js 基于html5, 完全开源免费 功能过于简单,只有6种图,能满足小系统需求,使用简便,效果比较炫. http://www.bootcss.com/p/chart.js/ 2. ...

  2. 移动端页面输入法挡住input输入框的解决方法

    1,宽高用了百分比或者vw/vh布局的,input输入框的最外层父容器的可用JS动态设置为当前窗口的宽高(防止输入法的弹出令页面变形) 2,最外层父容器用了fixed定位的,不要用top:0;要用bo ...

  3. iphone越狱开发之Class-Dump

    刚刚开始接触ios越狱开发,现在开始纪录每天的点滴进展 装载请注明 http://www.cnblogs.com/xiongwj0910/archive/2012/08/16/2642988.html ...

  4. python 发送邮件短信封装

    发送邮件 需要开启163的smtp服务 import smtplib from email.mime.text import MIMEText class MailSender(): def __in ...

  5. Springmvc使用阿里巴巴的fastjson传输到前台中文乱码的解决方案,他娘的大家都少制造垃圾,学习过程将会多么快乐

    弄了大概七八个小时吧 都他妈比的抄来抄去,一分一秒的去试错 最终参考这个问题解决了乱码的情况https://bbs.csdn.net/topics/392169549 412 需要在springmvc ...

  6. maven打包时无法识别lombok中@Data生成的get set方法

    开发中使用了lombok,在使用maven编译打包时发现识别不了lombok通过注解@Data在实体类中生成的get,set方法.通过在网上的一篇博客找到了解决的办法,将maven-compiler- ...

  7. oracle-约束-序列

    概要图 一 约束 --问题:往表中插入数据的时候,可能出现一些问题,比如:重复插入数据,内容不对(性别) --如何保证数据库表中数据的完整性和一致性呢? 约束是强加在表上的规则或条件,确保数据库满足业 ...

  8. Data Lake Analytics IP白名单设置攻略

    当我们成功开通了 DLA 服务之后,第一个最想要做的事情就是登录 DLA 数据库.而登录数据库就需要一个连接串.下面这个页面是我们首次开通 DLA 之后的界面,在这里我们要创建一个服务访问点. 在上面 ...

  9. 模拟7题解 T1方程的解

    方程的解 [扩展欧几里德] 首先进行特判,两个小时基本想到了,除了a!=0,b==0,a*c<0这种情况 其次就是一般情况: 首先exgcd求出ax+by=GCD(a,b)的一组任意解 然后两边 ...

  10. 字符串的trim()用法

      trim() 方法会从一个字符串的两端删除空白字符.在这个上下文中的空白字符是所有的空白字符 (space, tab, no-break space 等) 以及所有行终止符字符(如 LF,CR). ...