绘制大量半透明矩形,wpf和GDI哪个效率高?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了绘制大量半透明矩形,wpf和GDI哪个效率高?相关的知识,希望对你有一定的参考价值。

可能绘制大约3万个矩形,另外还有一些圆形和不规则图形(自定义顶点)。
用GDI+的 FillRectangle 或者 WPF的Shapes.Rectangle 哪个效率高?
不需要移动,但经常要更换新的一批图形。
可能绘制大约3万个矩形,另外还有一些圆形和不规则图形(如三角六角之类的)。
用GDI+的 FillRectangle 或者 WPF的Shapes.Rectangle 哪个效率高?
不需要移动,但经常要更换新的一批图形,所以效率很重要。
计划的是:
如果用GDI,大致上重绘BITMAP,
如果用WPF,则可能需要清空List<Shapes> , 然后再重绘。
不知道还有其他更好的解决方案不?

GDI性能肯定没WPF的DirectX快是肯定的。但是用Rectangle其实也不快。

建议你用WPF的DrawingContext,你只需要记录矩形的属性,需要画出来的时候用DrawingContext画一遍就好了追问

初步尝试,绘制20000个矩形
1、用GDI,需要140ms,另外。把Bitmap转为BitmapImage需要额外的100ms
2、用Rectangle,约需要500ms,
3、用visual +DrawingContext,需要14000ms,而且刷新明显迟钝。不知道是不是算法有问题??

追答

你不会每次需要的时候都重新用DrawingContext绘制出来吧……需要的时候再画,比如矩形变化的时候。

不清楚你的变化频率如何,如果像游戏那样的变化频率,你每次frame刷新的时候都用DrawingContext,那么底层的缓存就根本没用了。

追问

我需要是从数据库查询出20000个数据,包括坐标和颜色,生成一个图片。当然这20000个点可能随查询条件的改变而改变。

我优化了代码:


绘图部分需要95ms,后面转化部分需要350ms,共计450ms左右。还是比GDI慢一点。

追答

DrawingContext不是为线性图形绘制做优化的。

你这样只不过是输出一个Bitmap而已,建议你使用流图形输出,参考这里:http://msdn.microsoft.com/en-us/library/system.windows.media.streamgeometry.aspx

追问

谢谢老兄的内心帮助!

按您的建议对流进行测试。

 

执行时间是45ms左右。的确快很多。但是有两个问题:

一:每个方格的颜色是不一样的。按这个方法,似乎先按颜色分别绘制,这样要增加额外的开销。

二:致命问题,由于geometry里面内容太多,导致绘制好之后,调整窗口大小等可能需要重绘的操作都出现迟钝,影响用户体验的迟钝。

如果要改善这点,要把myPath转为image之类的,不知道如何高效转?

追答

你说你经常要更新新的一批图形,那么这种效率是最高的了,因为缓存对于这种大量更新的图形没有一点儿用处。

能想到的优化方式就是绘制前进行算法方面的优化,就跟游戏一样,计算场景中那些在前景哪些在背景,被遮挡的在背景的元素就不进行绘制了,筛选出需要绘制的图形这样速度就会快很多。

参考技术A 首先你需要考虑用户端的电脑配置情况如何。目前WPF对显卡和内存的要求高。如果你的用户使用中的电脑不怎么样,那还是使用GDI吧。

WPF将矩形宽度和高度绑定到主对话框

【中文标题】WPF将矩形宽度和高度绑定到主对话框【英文标题】:WPF Binding Rect Width and Height to the main Dialog 【发布时间】:2019-12-16 17:55:09 【问题描述】:

如何正确地将矩形的宽度和高度绑定到对话框本身的边界?这样绘制的矩形总是覆盖整个窗口的客户空间。

现在每当我使用我的绑定代码(目前已被注释掉)时,它似乎都无法正确调整矩形的大小。它应该显示一个带有透明窗口切口的大对话框。

XML

<Window x:Class="WpfSnipping.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfSnipping"
        mc:Ignorable="d"
        Title="MainWindow" 
        Height="500" 
        Width="500"
        AllowsTransparency="True" 
        WindowStyle="None" 
        Topmost="True"
        Background="Transparent">

    <Window.Resources>
        <local:RectConverter x:Key="RectConverter"></local:RectConverter>
    </Window.Resources>

    <Grid x:Name="MainGrid">
        <Canvas >
            <Path Stroke="Black" Fill="White" Opacity=".3">
                <Path.Data>
                    <CombinedGeometry GeometryCombineMode="Exclude">
                        <CombinedGeometry.Geometry1>
                            <RectangleGeometry Rect="0,0,300,300">
                                <!--<RectangleGeometry.Rect>
                                    <MultiBinding Converter="StaticResource RectConverter">
                                        <Binding ElementName="MainGrid" Path="Width"/>
                                        <Binding ElementName="MainGrid" Path="Height"/>
                                    </MultiBinding>
                                </RectangleGeometry.Rect>-->
                            </RectangleGeometry>
                        </CombinedGeometry.Geometry1>
                        <CombinedGeometry.Geometry2>
                            <RectangleGeometry Rect="50,50,100,100">
                            </RectangleGeometry>
                        </CombinedGeometry.Geometry2>
                    </CombinedGeometry>
                </Path.Data>
            </Path>
        </Canvas>
    </Grid>
</Window>

cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfSnipping

    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    
        public MainWindow()
        
            InitializeComponent();
        
    

    public class RectConverter : IMultiValueConverter
    
        #region IMultiValueConverter Members

        public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        
            return new System.Windows.Rect(0, 0, (double)values[0], (double)values[1]);
        

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
        
            throw new NotImplementedException();
        

        #endregion
    

【问题讨论】:

如果您删除 `Rect="0,0,300,300"',它应该会占用您想要的所有空间。不确定你想要什么。 【参考方案1】:

绑定到ActualWidthActualHeight,因为只要MainGrid 的大小发生变化,这些依赖属性就会更新:

<RectangleGeometry.Rect>
    <MultiBinding Converter="StaticResource RectConverter">
        <Binding ElementName="MainGrid" Path="ActualWidth"/>
        <Binding ElementName="MainGrid" Path="ActualHeight"/>
    </MultiBinding>
</RectangleGeometry.Rect>

【讨论】:

以上是关于绘制大量半透明矩形,wpf和GDI哪个效率高?的主要内容,如果未能解决你的问题,请参考以下文章

unity部分模型半透明了怎么办

在 HTML5 画布中绘制鼠标移动的半透明线

htmlcss和js原生写一个模态弹出框,顺便解决父元素半透明子元素不透明效果

delphi 怎样绘制半透明窗体,只让窗体背景半透明,而窗体里面的控件 不透明

利用cv2.rectangle()绘制矩形框(python)

VB6 GDI+进阶通过拼接圆弧和线绘制圆角矩形