8

そのため、線からボックス、画像まで、さまざまなものを描画するために winForms .CreateGraphics を使用しました。とても丁寧で対応もよかったです。

C#でWPFを学ぼうとしています

WPF を使用すると、四角形オブジェクトをキャンバスに「追加」して、それらを適切に表示できることがわかりました。ただし、私は何十万もの四角形を時々描画しており、描画速度が非常に遅くなる可能性があり、四角形の 1 つでも移動すると UI の動きが鈍くなります。

winForms の要素に直接ペイントするのはそれほど高速ではありませんでしたが、どれだけペイントしても一貫していました。

WPFでこれを行うのと同様の解決策はありますか?

に linq を追加しようとしましたがSystem.Drawing、これによりGraphicsオブジェクトが得られましたが、試した wpf 要素には.CreateGraphics()メソッドがありません。

4

4 に答える 4

6

WPF は、WinForms とは異なるグラフィックス操作モデルを使用します。

WinForms を使用すると、画面上のピクセルを直接編集できます。ピクセルが描画されると、四角形の概念が失われます。ピクセルの描画は非常に高速な操作です。

WPF では、画面上のピクセルを制御していません。DirectDraw です。DirectDraw は、ベクター ベースの合成エンジンです。ピクセルを描画しません。ベクトル形状 (またはビジュアル) を定義します。画像が画面にレンダリングされた後でも、形状または長方形の概念は保持されます。他の長方形と重なる新しい長方形を追加すると、他のすべての長方形を再描画する必要があります。これは、パフォーマンスが低下している可能性があります。これは、WinForms を使用している場合には発生しません。

OnRender をオーバーライドすることで、WPF のパフォーマンスを少し改善できます。Rectangle オブジェクトのオーバーヘッドをカットして、ビジュアルを直接提供できます。ただし、まだ画面にピクセルを描画していません。DirectDraw がイメージをレンダリングするために使用する形状を定義しています。この点で、OnRender の名前は少し誤解を招く可能性があります。

WPF でアプリケーションのパフォーマンスを向上させるための多くのトリックを見つけることができると確信しています。ピクセルをペイントする方法はまだありますが、それは WPF の要点を少し打ち負かしています。

何千もの長方形を必要とする何をしていますか?

于 2011-05-11T18:14:14.537 に答える
3

前述のように、WPF は保持されたグラフィック手法を使用するため、実際にはメモリ内に 100,000 個の Rectangle オブジェクトを作成し、それらすべてを描画します。スローダウンは、おそらくガベージ コレクションと一般的なメモリの問題が原因です。

OnRender メソッドのオーバーライドとは別に、ここで調べられることがいくつかあります。

  1. おなじみの GDI メソッドを使用してバックグラウンド スレッドで画像に四角形を描画し、結果を WPF WriteableBitmap に書き込みます。

  2. D3DImage を使用して、ハードウェア アクセラレーションを活用します。これには、DirectX (または Direct2D) ライブラリの知識が必要です。このアプローチに興味がある場合は、SlimDx を調べることをお勧めします。

于 2011-05-11T18:00:19.177 に答える
3

問題は、WPF が何千ものグラフィック オブジェクトをレンダリングできないことではなく、アイテムの作成と追加が WPF オブジェクト階層を超えている可能性が高いことです。結局、すべてのグラフィカルな作業に GPU を使用します。

「Visual」クラスにできるだけ近いオブジェクトを追加する必要があります。後者の「UIElement」に基づいてオブジェクトを追加し始めるとすぐに、オブジェクトを描画するだけでなく、オブジェクトごとにユーザーのクリック、ホバーなどを追跡するよう WPF に要求します。 .

于 2011-05-11T18:40:25.487 に答える
3

OnRenderをオーバーライドするコントロールを作成し、そこで描画を行う必要があります。別のコントロールに描画する方法はありませんが、コントロール自体を描画することはできます。

また、WPF は保持されたグラフィックスを使用することに注意してください。そのため、何かを変更した場合は、必要に応じてビジュアルを無効にする必要があります。

編集:

何かのようなもの:

public class MyControl : Control {

    public MyControl() {
       this.Rects = new ObservableCollection<Rect>();
       // TODO: attach to CollectionChanged to know when to invalidate visual
    }

    public ObservableCollection<Rect> Rects { get; private set; }

    protected override void OnRender(DrawingContext dc) {
        SolidColorBrush mySolidColorBrush  = new SolidColorBrush();
        mySolidColorBrush.Color = Colors.LimeGreen;
        Pen myPen = new Pen(Brushes.Blue, 10);

        foreach (Rect rect in this.Rects)
            dc.DrawRectangle(mySolidColorBrush, myPen, rect);
    }
}
于 2011-05-11T17:45:24.643 に答える