【发布时间】:2013-03-10 07:49:39
【问题描述】:
我有一个<Grid>,其中包含一些垂直和水平的<Line>s。我希望网格可以随窗口大小缩放,并保持其纵横比,因此它包含在 <Viewbox Stretch="Uniform"> 中。
但是,我也希望线条始终以 1 像素的宽度呈现,所以我使用:
Line line = new Line();
line.SetValue(RenderOptions.EdgeModeProperty, EdgeMode.Aliased);
// other line settings here...
这使线条的初始外观很理想,但是一旦您开始调整窗口大小,就会开始拉伸/缩放,线条再次变成 1 和 2 像素厚的混合体。
有什么方法可以让线条始终保持 1 像素粗,并且还允许调整窗口/网格的大小?
更新 - 根据 Clemens 的建议使用路径几何
@Clemens - 感谢您强调线条和路径之间的渲染差异。当我尝试使用您的示例重新编写代码时,我有一种下沉的感觉,我正在为自己挖掘更多的漏洞,并没有真正掌握整个概念(完全是我的错,不是你的错,我只是 WPF 的新手) .
我将添加一些屏幕截图来说明以下说明:
我正在制作一个游戏板(用于Go 的游戏,以防有助于理解布局)。我有一个 9x9 的网格,我打算通过简单地将椭圆添加到特定的网格单元来放置游戏部件。
然而,要在棋盘上绘制底层线,我需要在棋盘上绘制与单元格中间相交的线(在 Go 中,棋子放置在交叉点上,而不是单元格的中间)。
很可能是我采取了完全错误的方法,请随时告诉我从一条不同的路线重新开始,而不是在当前结构中四处乱窜。
到目前为止,我就是这样做的(由于坐标的计算方式,我正在以编程方式添加路径。不确定是否可以全部在 XAML 中完成):
XAML:
<Grid MinHeight="400" MinWidth="400" ShowGridLines="False" x:Name="boardGrid">
<Grid.Resources>
<ScaleTransform x:Key="transform"
ScaleX="{Binding ActualWidth, ElementName=boardGrid}"
ScaleY="{Binding ActualHeight, ElementName=boardGrid}" />
</Grid.Resources>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<!-- more rows, 9 in total -->
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<!-- more columns, 9 in total -->
</Grid.ColumnDefinitions>
<!-- example game pieces -->
<Ellipse Stroke="Black" Fill="#333333" Grid.Row="3" Grid.Column="2" />
<Ellipse Stroke="#777777" Fill="#FFFFFF" Grid.Row="4" Grid.Column="4" />
</Grid>
C#:
int cols = 9;
int rows = 9;
// Draw horizontal lines
for (int row = 0; row < rows; row++)
{
var path = new System.Windows.Shapes.Path();
path.Stroke = Brushes.Black;
path.StrokeThickness = 1;
path.SetValue(RenderOptions.EdgeModeProperty, EdgeMode.Aliased);
Grid.SetRow(path, row);
Grid.SetColumnSpan(path, cols);
Grid.SetZIndex(path, -1);
double cellWidth = boardGrid.ColumnDefinitions[0].ActualWidth;
double cellHeight = boardGrid.RowDefinitions[0].ActualHeight;
double x1 = (cellWidth / 2) / boardGrid.ActualWidth;
double y1 = (cellHeight / 2) / boardGrid.ActualHeight;
double x2 = ((cellWidth * cols) - (cellWidth / 2)) / boardGrid.ActualWidth;
double y2 = (cellHeight / 2) / boardGrid.ActualHeight;
path.Data = new LineGeometry(new Point(x1, y1),
new Point(x2, y2),
(ScaleTransform)boardGrid.TryFindResource("transform"));
boardGrid.Children.Add(path);
}
// Similar loop code follows for vertical lines...
这是我在使用上面的代码时得到的
这几乎就是我想要的样子。它又为我提出了 2 个问题:
1) 我是否采用了正确的方法来计算 x1、x2、y1 和 y2 值,方法是将它们除以总板宽度以创建一个介于 0 和 1 之间的数字,以便随后可以将 ScaleTransform 应用于它们?
2) 现在我不再使用Viewbox,如何实现固定比例缩放?如果我放大我的窗口,板会不成比例地伸展(见下图)。 (不过,它不再对线条进行抗锯齿处理,这很棒。)
我知道这将成为一个单一的帖子。非常感谢您的耐心和回复。
【问题讨论】:
-
请张贴截图。
-
我已经编辑了问题并添加了屏幕截图。
-
查看我编辑的答案,了解如何实现统一缩放。
标签: c# wpf antialiasing viewbox