Jak jak najefektywniej rysować grafikę w WPF
Tworzę narzędzie, które w dużej mierze opiera się na drzewach węzłów wykresowych. Obecna implementacja jest wykonywana w Javie i portuję ją do ogólnego kodu bazującego na C#, więc może być używana przez różne implementacje renderowania, a także dlatego, że chcę użyć mocy WPF dla przyjaznego dla użytkownika interfejsu.
Po przejrzeniu całego dnia natknąłem się na różne metody rysowania grafiki wektorowej przez WPF.
Ten facet mówi o różnych warstwach w programistach WPF wybierz z. Ponieważ chcę używać WPF wyłącznie do jego renderowania na początku, chcę pracować nad "warstwą wizualną".
Wtedy natknąłem się na takie rzeczy jak: DrawingVisual , GeometryDrawing , Framework / UIElement / Shapes
Jestem nieco przytłoczony różnymi implementacjami, które w końcu robią to samo na zupełnie inne sposoby.
Biblioteka Graph-Node została już przeportowana do C# z całą logiką (w tym kolizją wykrywanie i przeciąganie myszką). Jak to robi się z myślą o graficznych rendererach (jak XNA, SlimDX, OpenTK itp.), jaki byłby najlepszy pod względem wydajności sposób implementacji renderera WPF (jak w, będzie rysować to, co biblioteka grafu każe mu rysować?
Zasadniczo otrzymana Kontrola WPF działa jak płótno, ale musi być SUPER lekka i nie mieć żadnych schludnych funkcji WPF, poza tym zapewnia mi sposób na rysowanie moich okręgów, linii i innych kształtów :)
EDIT:
W zasadzie chcę wiedzieć: jaka jest droga? Czy Mogę rozszerzyć Canvas jako "Host" dla mojej grafiki, a następnie dodać własną implementację interfejsu użytkownika? Albo mogę mieć jedną klasę, która może narysować wszystko (jak w, jeden mega super ultra graphic). Podobnie jak nadpisywanie OnPaint w GDI lub metoda Paint w Javie (która daje obiekt graficzny do robienia wszystkiego).
3 answers
Polecam lekturę Optymalizacja wydajności: grafika 2D i obrazowanie (Martwy link -- czytelny przez Internet Archive) -
Zasadniczo, Drawing
obiekty będą lżejsze niż Shapes
, ogólnie. To jest prawdopodobnie to, czego chcesz użyć.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-02 22:09:19
Ogólnie rzecz biorąc, lepszą wydajność uzyskuje się dzięki usługom niższego poziomu. W WPF
oznacza to rodzinę obiektów Drawing
. Wszystko co dostajesz to: Drawing
, DrawingGroup
, GeometryDrawing
, GlyphRunDrawing
, ImageDrawing
, i VideoDrawing
. Są one jednak wystarczające dla wszystkich potrzeb. Używanie tych typów jest bardzo przyjazne dla WPF, ponieważ Drawing
jest jednostką koncepcyjną, którą WPF wymienia z akceleratorem GPU, prawdopodobnie zachowując go i zarządzając nim tam, jeśli to możliwe. Działa to, ponieważ Drawing
wyraża się w kategoriach przenośnego rysunku wektorowego prymitywy.
Gdy jednak zaczniesz przebudowywać swoją aplikację wokół Drawings
, możesz potrzebować trochę interakcji z kodem wyższego poziomu, który nadal opiera się na UIElement
, FrameworkElement
, itd. Jedną z rzeczy, której nie znalazłem wbudowanego w WPF, jest prosty sposób na owinięcie rysunku jako frameworka w możliwie najniższy możliwy sposób. DrawingVisual
nie jest kompletnym rozwiązaniem, ponieważ wywodzi się tylko z Visual
- co oznacza, że nadal wymaga elementu hostingowego.
Następująca klasa będzie hostuje dowolny WPF Drawing
bezpośrednio bez użycia pośredniego DrawingVisual
. Dodałem wsparcie dla FrameworkElement
'S Margin
właściwości (bez kary wydajności, jeśli nieużywane), ale niewiele więcej. Dzięki pojedynczemu wątkowi renderowania WPF można bezpiecznie i łatwo buforować pojedynczy obiekt TranslateTransform w celu implementacji marginesu. Polecam dostarczyć tylko rysunki, które zostały zamrożone; w rzeczywistości w wersji, której używam, mam do tego prawo w konstruktorze.
public class DrawingElement : FrameworkElement
{
static readonly TranslateTransform tt_cache = new TranslateTransform();
public DrawingElement(Drawing drawing)
{
this.drawing = drawing;
}
readonly Drawing drawing;
TranslateTransform get_transform()
{
if (Margin.Left == 0 && Margin.Top == 0)
return null;
tt_cache.X = Margin.Left;
tt_cache.Y = Margin.Top;
return tt_cache;
}
protected override Size MeasureOverride(Size _)
{
var sz = drawing.Bounds.Size;
return new Size
{
Width = sz.Width + Margin.Left + Margin.Right,
Height = sz.Height + Margin.Top + Margin.Bottom,
};
}
protected override void OnRender(DrawingContext dc)
{
var tt = get_transform();
if (tt != null)
dc.PushTransform(tt);
dc.DrawDrawing(drawing);
if (tt != null)
dc.Pop();
}
};
[[23]} [edit:] to też przydatne przy wstawianiu WPF Drawing
do właściwości InlineUIContainer.Child
(tzn. przy użyciu TextBlock.InlinesCollection
do bardziej bogatego formatowania zawartości bloku tekstowego).Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-01 20:31:47
Losowanie wydaje się być słusznym wyborem:
DrawingVisual to lekka Klasa rysunku, która służy do renderowanie kształtów, obrazów lub tekstu. Ta klasa jest uważana za lekką ponieważ nie zapewnia układu ani obsługi zdarzeń, co poprawia jego wydajność. Z tego powodu rysunki są idealne dla tła i Clipart.
Source: Using DrawingVisual Objects
Więc to wydaje się być absolutnie to, o co prosisz, Płótno SUPER lekki.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-09 19:44:54