我需要在WPF中绘制大量的2D元素,例如线条和多边形.他们的立场也需要不断更新.
我在这里看了很多答案,主要建议使用DrawingVisual或覆盖OnRender函数.为了测试这些方法,我实现了一个渲染10000个椭圆的简单粒子系统,我发现使用这两种方法绘制性能仍然非常糟糕.在我的电脑上,我每秒钟不能超过5-10帧.当你考虑我使用其他技术可以轻松地平滑地抽取50万个粒子时,这是完全不可接受的.
所以我的问题是,我是否违反了WPF的技术限制,或者我错过了什么?还有其他我可以使用的东西吗?欢迎任何建议.
这里是我试过的代码
MainWindow.xaml的内容:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="500" Width="500" Loaded="Window_Loaded">
<Grid Name="xamlGrid">
</Grid>
</Window>
Run Code Online (Sandbox Code Playgroud)
MainWindow.xaml.cs的内容:
using System.Windows.Threading;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
EllipseBounce[] _particles;
DispatcherTimer _timer = new DispatcherTimer();
private void Window_Loaded(object sender, RoutedEventArgs e)
{
//particles with Ellipse Geometry
_particles = new EllipseBounce[10000];
//define area particles can bounce around in
Rect stage = new Rect(0, 0, 500, …Run Code Online (Sandbox Code Playgroud) 我正在使用WPF创建大量文本DrawText,然后将它们添加到单个文本中Canvas.
我需要在每个MouseWheel事件中重绘屏幕并且我意识到性能有点慢,所以我测量了创建对象的时间并且它不到1毫秒!
那可能是什么问题呢?很久以前,我想我读到的地方实际上是Rendering花费时间,而不是创建和添加视觉效果.
这是我用来创建文本对象的代码,我只包含了基本部分:
public class ColumnIdsInPlan : UIElement
{
private readonly VisualCollection _visuals;
public ColumnIdsInPlan(BaseWorkspace space)
{
_visuals = new VisualCollection(this);
foreach (var column in Building.ModelColumnsInTheElevation)
{
var drawingVisual = new DrawingVisual();
using (var dc = drawingVisual.RenderOpen())
{
var text = "C" + Convert.ToString(column.GroupId);
var ft = new FormattedText(text, cultureinfo, flowdirection,
typeface, columntextsize, columntextcolor,
null, TextFormattingMode.Display)
{
TextAlignment = TextAlignment.Left
};
// Apply Transforms
var st = new ScaleTransform(1 / scale, …Run Code Online (Sandbox Code Playgroud) 我有一个应用程序依赖于深度缩放图像(从PNG转换为各种规模的JPG金字塔),我们使用DeepZoomTools.dll.这是依赖于PresentationCore.dll并且多年来一直运行良好.
在KB4040972和KB4040973的推出之后,从PNG到JPG的转换生成(取决于坐标)黑色图像而不是它应包含的图像.
如果以下代码在控制台或桌面应用程序中运行,则可以正常运行.
如果在高权限SYSTEM帐户下运行(例如,从任务计划程序),它只能起作用.
我创建了一个重现问题的项目,代码如下:
public static void TestConvert2(string strFileName, string strOutFileName) {
JpegBitmapEncoder jpegBitmapEncoder = new JpegBitmapEncoder();
jpegBitmapEncoder.QualityLevel = 1 + (int) Math.Round(0.95 * 99.0);
BitmapEncoder encoder = jpegBitmapEncoder;
Int32Rect inputRect = new Int32Rect(0, 0, 255, 255);
Rect outputRect = new Rect(0, 0, 255, 255);
Uri bitmapUri = new Uri(strFileName, UriKind.RelativeOrAbsolute);
BitmapDecoder bitmapDecoder = BitmapDecoder.Create(bitmapUri,
BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad);
bitmapDecoder = BitmapDecoder.Create(bitmapUri, BitmapCreateOptions.IgnoreImageCache, BitmapCacheOption.None);
BitmapSource inputFrame = (BitmapSource) bitmapDecoder.Frames[0];
BitmapSource source1 = (BitmapSource) new CroppedBitmap(inputFrame, inputRect);
DrawingVisual drawingVisual = new DrawingVisual(); …Run Code Online (Sandbox Code Playgroud) 我必须将TextBox中的文本呈现为WriteableBitmap.此代码运行良好,但其中的文本模糊或消除锯齿.关于如何保持别名和清晰的任何想法?
text = new FormattedText(tb.Text,
new CultureInfo("de-de"),
FlowDirection.LeftToRight,
new Typeface(tb.FontFamily, FontStyles.Normal, tb.FontWeight, new FontStretch()),
tb.FontSize,
tb.Foreground);
drawingContext = dv.RenderOpen();
drawingContext.DrawText(text, Pos);
drawingContext.Close();
rtb.Render(dv);
rtb.CopyPixels(new Int32Rect(0, 0, rtb.PixelWidth, rtb.PixelHeight), wb.BackBuffer, wb.BackBufferStride * wb.PixelHeight, wb.BackBufferStride);
Run Code Online (Sandbox Code Playgroud)
我发现的不起作用:
TextOptions.SetTextFormattingMode(dv, TextFormattingMode.Display);
TextOptions.SetTextRenderingMode(dv, TextRenderingMode.Aliased);
Run Code Online (Sandbox Code Playgroud)
要么
RenderOptions.SetBitmapScalingMode(dv, BitmapScalingMode.NearestNeighbor);
RenderOptions.SetEdgeMode(dv, EdgeMode.Aliased);
Run Code Online (Sandbox Code Playgroud) writeablebitmap formatted-text rendertargetbitmap drawingvisual
所以我使用以下代码从输入表单中获取现有图像,文本,然后将输入表单中的文本放到现有图像上并将其另存为新图像:
using (FileStream output = new FileStream(match_outputFile, FileMode.Create))
{
BitmapImage bitmap = new BitmapImage(new Uri(match_sourceFile, UriKind.Relative));
DrawingVisual visual = new DrawingVisual();
using (DrawingContext image = visual.RenderOpen())
{
image.DrawImage(bitmap, new Rect(0, 0, bitmap.PixelWidth, bitmap.PixelHeight));
buildText(image, "text1", this.text1.Text);
buildText(image, "text2", this.text2.Text);
buildText(image, "text3", this.text3.Text);
}
RenderTargetBitmap target = new RenderTargetBitmap(bitmap.PixelWidth, bitmap.PixelHeight, bitmap.DpiX, bitmap.DpiY, PixelFormats.Default);
target.Render(visual);
BitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(target));
encoder.Save(output);
}
Run Code Online (Sandbox Code Playgroud)
如您所见,它调用以下函数来绘制文本:
private void buildText(DrawingContext image, string settings, string input)
{
string[] setting = (Properties.Settings.Default[settings].ToString()).Split(',');
FormattedText text = new FormattedText( …Run Code Online (Sandbox Code Playgroud) 我目前正在制作一个自定义画布,并且我必须添加一个表,所以我认为dataGrid会很好.所以我想从"Datagrid"创建一个" 表",用户可以在运行时将一个表添加到画布.
直到现在,我已经尝试使用列表填充DataGrid并成功.
如何在运行时将列添加到Datagrid,以便在运行时使用文本框从用户获取列数和标题值,并基于文本框的值,datagrid应添加列和标题值.
实际上我想开发一个表,其中用户传递no的列和列标题,并且应该生成表.
要么
"你能否建议我使用DrawingVisual类"绘制"表格"
它是GraphicsTable类的一部分
//Custom Classes "DrawingCanvas & GraphicsTable"
public void CreateDataGrid(GraphicsTable graphicsTable, DrawingCanvas drawingCanvas)
{
dt = new DataGrid();
dt.Name = "Data";
dt.ItemsSource = person();
dt.AllowDrop = true;
dt.AutoGenerateColumns = true;
dt.Height = graphicsTable.Rectangle.Height;
dt.Width = graphicsTable.Rectangle.Width;
drawingCanvas.Children.Add(dt);
Canvas.SetTop(dt, graphicsTable.Rectangle.Top);
Canvas.SetLeft(dt, graphicsTable.Rectangle.Left);
dt.Width = dt.Width;
dt.Height = dt.Height;
dt.Focus();
}
//I have just tried to add dome dummy data to the datagrid.
public List<Person> person()
{
List<Person> peep = new List<Person>();
peep.Add(new …Run Code Online (Sandbox Code Playgroud) 我创建了一个最小的项目,以便在WPF中使用DrawingVisuals进行"开始"(到目前为止非常初学者).
我的项目仅包含主窗口的XAML和代码.这个项目的唯一目的是打开一个窗口,显示一些填充可用空间的"信号噪音".
MainWindow.xaml是这样的:
<Window x:Class="MinimalPlotter.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MinimalPlotter"
Title="MainWindow" Width="1200" Height="800"
WindowStartupLocation="CenterScreen">
<Canvas Height="500" Width="700" x:Name="drawingArea" Margin="50" Background="Gray">
<local:VisualHost Canvas.Top="0" Canvas.Left="0" x:Name="host" Width="700" Height="500" />
</Canvas>
</Window>
Run Code Online (Sandbox Code Playgroud)
代码背后是这样的:
namespace MinimalPlotter
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
public class VisualHost : FrameworkElement
{
public VisualHost()
{
int h = (int)this.Height;
int w = (int)this.Width;
Random random = new Random();
double r;
DrawingVisual path = new DrawingVisual();
StreamGeometry g = new StreamGeometry();
StreamGeometryContext cr …Run Code Online (Sandbox Code Playgroud)