2010-05-27 42 views
1

我遇到了問題Tiling rectangles seamlessly in WPF中描述的問題,但對那裏給出的答案並不滿意。無縫地在WPF中平鋪矩形,同時保持子像素精度?

我正在繪製一個條形圖,通過繪製大量的矩形彼此相鄰。根據包含它們的畫布的比例尺,由於子像素呈現的結果,其中一些可能會出現小間隙。

我從上面的問題中學到了如何使我的矩形適合屏幕像素,消除了這種效應。

不幸的是,我的圖表可能顯示的方式比像素多。除了微小的差距(表現爲色彩飽和度的週期性變化)之外,這種效果很好。如果我用屏幕像素捕捉每個條,但大多數條會消失,所以我正在尋找另一種解決方案。

在此先感謝!

回答

2

導致問題的

亞像素的形狀使用像素內alpha混合。不幸的是,沒有alpha混合算法,導致矩形在鄰接時無縫混合。

例如,如果:

  • 的背景顏色是白色
  • 前景顏色是黑色,並且
  • 你有兩個矩形,單個像素的每個覆蓋一半

每個矩形都會被塗成黑色,並具有5​​0%的不透明度。第一個將白色像素轉換爲灰色。第二個將它轉換成深灰色,但不是黑色。如果這些矩形在相鄰像素中保持黑色,則會在黑色中看到深灰色像素。

兩種類型的解決方案

一般有兩種方法來解決這個問題:

  1. 使用單一幾何定義所有的矩形,或
  2. 強制初始渲染成在足夠高的分辨率下,用戶不會看到問題。

如何使用一個單一的幾何

如果你只是有一組矩形,您可以創建一個簡單的控制是繪製在整個矩形集合包含的組合形狀單一的PathGeometry。爲了說明這個想法,如果你有彼此不同的高度的旁邊兩個矩形,就像這樣:

<Path Data="M0,0 L0,2 L1.5,2 L1.5,4 L3,4 L3,0 Z" Fill="Red" /> 

來實現一個實用的方法:

<Rectangle Canvas.Left="0" Canvas.Top="0" Width="1.5" Height="2" Fill="Red" /> 
<Rectangle Canvas.Left="1.5" Canvas.Top="0" Width="1.5" Height="4" Fill="Red" /> 

你可以用一個單一的PathGeometry這樣使它這是:

  • 用透明刷油漆的矩形所以他們會點擊,但不visable
  • 添加路徑C以Z順序在矩形下面控制
  • 使用構建幾何的轉換器將Path控件的Data屬性綁定到數據源。

如果您使用的是佈局系統來定位你的矩形,你可以改爲希望通過渲染裝飾器計算的第一個組合的路徑,並在當每個矩形創建裝飾器,然後使用一個AdornerLayer休息不可見。

上面假設很容易從源數據生成PathGeometry。對於更復雜的場景,可以對Path控件進行子類化以在其父項的可視化樹中搜索指定的形狀,並使用一般的Geometricl算法計算表示它們並沒有多餘邊的PathGeometry。

如果您的矩形將具有多種顏色,則可以對每種顏色使用多個Path控件,或者可以構造一個Drawing對象並顯示該對象。

這裏是代碼的結構構造的PathGeometry:

var geo = new PathGeometry(); 
var figure = new PathFigure(); 
var segment = new PolyLineSegment(); 
segment.Points.Add(...); 
segment.Points.Add(...); 
segment.Points.Add(...); 
segment.Points.Add(...); 
segment.Points.Add(...); 
figure.Segments.Add(segment); 
geo.Figures.Add(figure); 

如何強制初始渲染是在高分辨率

要強制在更高的分辨率渲染:

  1. 內部構建您的圖表比您想要顯示它大幾倍,例如通過將它包裝在ViewBox中。
  2. 使用VisualBrush或RenderTargetBitmap強迫你的圖表上分別呈現
  3. 添加彩繪與VisualBrush一個Rectangle你的UI

注意,通常WPF是聰明的關於在實際所需的分辨率渲染時你使用ViewBrush,但可以通過讓實際的圖表以實際大小顯示在屏幕上來欺騙,但是之後會被父級控件剪裁,因此實際上並沒有看到太大的版本。

RenderTargetBitmap不存在這個問題,當然,因爲您指定了您想要的分辨率,但知道何時重新呈現位圖可能會非常棘手。如果您只重新渲染數據更改,則可以使用事件,但如果希望進行任何視覺更改以觸發重新渲染,則更難。

+0

很好的答案,謝謝! – Jens 2010-06-02 08:42:33

1

Target 4.0, use layout rounding(博客文章與演示)。

+0

感謝您的意見。我其實已經嘗試過了,但它的行爲與我之前使用GridLineSet的方法完全相同,即每個條的寬度至少爲1像素。 – Jens 2010-05-27 13:40:25

+0

@Jens不知道除此之外。聽起來更像是一個設計問題(比像素更棒,對我來說聽起來不好)。您可能會考慮在特定點以下切斷小節,讓用戶放大正常子像素酒吧的位置,以便更容易處理時尚。 – Will 2010-05-27 15:22:36