Grafische Elemente zeichnen auf unendliche Zeichenfläche

  • VB.NET

Es gibt 49 Antworten in diesem Thema. Der letzte Beitrag () ist von FlyingEagle.

    Grafische Elemente zeichnen auf unendliche Zeichenfläche

    Hallo,

    ich suche etwas, von dem ich nicht genau weiß unter welchen Begrifflichkeiten man da am besten etwas findet.

    Vorweg, ich weiß prinzipiell wie man mit GDI(+) Images, Bitmaps oder Linien etc. zeichnet, und ich weiß auch wann CreateGraphics und wann e.Graphics verwendet ;)

    Ich möchte in einer Anwendung eine Zeichenfläche zur Verfügung stellen, welche sich z.b. beim nach links-scrollen autom. erweitert - dito in alle anderen richtungen.
    und natürlich performant bleibt ;)
    wie kann man da am besten vorgehen?

    Zum Zeichnen von Objekten:
    Ich zeichne eine beliebiges Objekt (nicht zwingend nur ein einfaches Rechteck) und möchte dieses nun auf der Fläche bewegen und ggfs. in der Größe anpassen. ich habe hier meine Objekte jeweils in eine Klasse gepackt (cObjekt) und zeichne dort das Objekt mit Übergabe der graphics neu sobald ich auf dem Formular was neuzeichne.
    je mehr Objekte je langsamer :(

    Wie kann ich verhindern alles neuzuzeichnen, wenn ich z.b. nur ein Objekt verschiebe, ohne das ein anderes direkt davon tangiert wird (z.B. durch Anzeige das das verschobene Objekt am vorhandenen Objekt andockt)?

    wenn ich z.b. den Ansatz verfolge, das Objekt zu zeichnen (und zwar beim Start und dann nur bei Resize) und dann nur die gezeichnete Image verwende, habe ich aber das Problem, wie zeichne ich dann z.B. Greifer an das Objekt um z.B. die Größe zu verändern.

    Hoffe ihr könnt mir hierbei etwas Licht ins Dunkle bringen.

    Danke und Grüße
    Willkommen im Forum. :thumbup:

    FlyingEagle schrieb:

    wie kann man da am besten vorgehen?
    So was:

    VB.NET-Quellcode

    1. Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    2. Dim bmp = New Bitmap(10000, 1000) ' Deine "unendliche" Größe
    3. Using g = Graphics.FromImage(bmp)
    4. g.Clear(Color.Azure)
    5. g.DrawString("bla", New Font("Arial", 100), Brushes.Black, New Point(50, 50))
    6. End Using
    7. bmp.Save("c:\Temp\Test.png", Imaging.ImageFormat.Png)
    8. End Sub
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Hi
    sehe ich nicht so. Besser wäre es meiner Meinung nach tatsächlich, alle gezeichneten Objekte in Klassen abzulegen (so auch Punktlisten, etc.) und anschließend jene zu zeichnen, die gezeichnet werden müssen.
    Verwende eine System.Drawing.Drawing2D.Matrix, um die Transformation für die Darstellung auf dem Steuerelement zu erzeugen. Wenn sich ein dargestelltes Objekt ändert und das eine Änderung der Darstellung bewirkt, muss das Steuerelement dort neugezeichnet werden, wo sich das dargestellte Objekt befindet. Dies kannst du bspw. über ein Event an das Steuerelement übergeben, das dann für sich Invalidate aufrufen kann. Es müssen dann halt alle Elemente neugezeichnet werden, die sich im neugezeichneten Bereich befinden.

    Viele Grüße
    ~blaze~

    ~blaze~ schrieb:

    Verwende eine System.Drawing.Drawing2D.Matrix, um die Transformation für die Darstellung auf dem Steuerelement zu erzeugen. Wenn sich ein dargestelltes Objekt ändert und das eine Änderung der Darstellung bewirkt, muss das Steuerelement dort neugezeichnet werden, wo sich das dargestellte Objekt befindet.

    Sorry, aber das verstehe ich gar nicht ;)
    jo, das ist auch wirklich eine eigentümliche Auflistung.
    Im Projekt genutzt wird ihr ListChanged - Event, damit, wenn sich die Anzahl ändert, das Label mit dem Counter aktualisiert wern kann.

    Würde ich heutzutage mit einer ObservableCollection(Of T) lösen - gabs damals noch nicht.
    Oder hätte ich vmtl. auch mit einer BindingList(Of T) machen können - kannte ich damals wohl noch nicht.
    den Satz verstehe ich nicht.

    Oder nur halb. So mal ins Blaue: Eine Klasse kann ihre Events nur selbst auslösen.
    Man kann besondere Methoden dranbasteln, um sie auch von aussen dazu zu bringen, aber das ist nicht Sinn der Sache.
    Das Changed-Event soll feuern, wenn die Collection changed, nicht wenn ijemand von aussen es möchte, dasses feuert.
    ja schon richtig, wäre aber dennoch ein legitimer weg :)
    aber die observablecollection kannte ich noch nicht, werde ich mir mal genauer anschauen.
    als list of gibt es was vergleichbares aber nicht oder?

    Pseudo [_kann_ man auch in ner function kapseln ...]:

    liste.add ...
    list_changed_event
    ich hab echt probleme mit deim deutsch.

    Was soll das heissen?

    FlyingEagle schrieb:

    als list of gibt es was vergleichbares aber nicht oder?
    Es gibt List(Of T), aber die ist halt nicht observable. Daher nimmt man, wenn man eine observable List möchte, die ObservableCollection(Of T).
    Die beiden Klassen sind durchaus vergleichbar, nämlich sind beides unerhört nützliche Auflistungen, aber es gibt auch Unterschiede, v.a., dass halt die OC geeignete Events feuert und dadurch observable ist, aber ich denk, das versteht sich von selbst, oder?


    Dein Pseudo sagt mir gar nichts. Soll das Code sein? Wenn ja, was soll er bewirken?

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „ErfinderDesRades“ ()

    Lieber Erfinder,

    vielen dank für deine antworten, dann will ich mich mal klarer ausdrücken, auch wenn du schon alles richtig beantwortet hast ;)

    mein Pseudo meinte nix anderes als das man ein item/object in eine list/collection packt, irgendwo im code, und danach eben die ui manuell aktualisiert. somit quasi die OC etc. nicht nutzt bzw. nutzen muss/müsste.
    war nur ne rand-meinung...

    zur list-of, ja ich meine eben nicht eine liste als collection sonder direct den typ list-of-observable, ob es letzteres auch gibt ... gefunden habe ich nichts.

    zum thema OC, ich habe gerade im internet einen beitrag gefunden, da meint einer
    "The practical difference is that BindingList is for WinForms, and ObservableCollection is for WPF."
    Siehst du das auch so?

    vielen dank und bis dahin
    verstehe ich recht: Du hast ObservableCollection noch garnet gefunden? Solch findet man im ObjectBrowser - gugge VisualStudio richtig nutzen (Google ist nicht deine Mami)

    Was der im internet meint - keine Ahnung - hatter das iwie begründet, oder nur gemeint?
    Tatsache ist, dass ObservableCollection was neueres ist, und glaub einiges in Wpf ist damit vmtl. performanter.
    Aber ist mir niemals aufgefallen, dass das eine hier geht, und da nicht oder sowas.
    Die einfachste Lösung wäre doch eigentlich, einfach eine Bitmap zu nehmen, welche sich immer bei Bedarf erweitert. Die Alte kann man dann einfach schnell auf die neue BitBlt'en und fertig. Ist vielleicht nicht die allerbeste Lösung dafür aber einfach und sicher auch von der Performance her ok.

    ErfinderDesRades schrieb:

    Was der im internet meint - keine Ahnung - hatter das iwie begründet, oder nur gemeint?
    Tatsache ist, dass ObservableCollection was neueres ist, und glaub einiges in Wpf ist damit vmtl. performanter.
    Aber ist mir niemals aufgefallen, dass das eine hier geht, und da nicht oder sowas.


    stackoverflow.com/questions/42…ollection-and-bindinglist

    habe im anhang mal einen ersten versuch angefügt, leider noch mit tierisch flimmern und darauf begründet vermutlich auch die zähe performance.
    falls mal jemand lust hat, mag er mich gern auf meine fehler hinweisen.
    man soll pro reihe einen kreis auf einen anderen ziehen können und fallen lassen, danach wird eine verbindung zwischen diesen gezeichnet (die linien-funktion ist derzeit noch links nach rechts!).

    dieses kann ich gar nicht verwenden, da bekomme ich nur fehler

    VB.NET-Quellcode

    1. 'Me.DoubleBuffered = True
    2. 'SetStyle(ControlStyles.AllPaintingInWmPaint Or ControlStyles.OptimizedDoubleBuffer Or ControlStyles.UserPaint Or ControlStyles.ResizeRedraw, True)
    3. 'UpdateStyles()


    m.e. sollte beim ziehen am kreis nur ein S auftauchen, es taucht aber S und H auf ... blicke ich auch noch nicht so genau ... vermutlich werden auch dadurch noch mehr zeichnenoperationen ausgelöst.

    die observablecollection macht auch nur bedingt was sie soll, eigentlich sollte sie aus dem panel heraus feuern, macht sie aber nicht, stattdessen in der form addhandler eingefügt, da geht es.

    danke & grüße
    Dateien
    • PaintTest01.zip

      (30,96 kB, 180 mal heruntergeladen, zuletzt: )

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „FlyingEagle“ ()

    hallo,

    habe am wochenende nochmal ein wenig damit rumgespielt, ich habe immer wieder das problem, je mehr ich versuche mich der optimierung zu nähern, um so mehr code bekomme ich und um so mehr klemmt es dann an einer anderen stelle :(

    eigentlich will ich ja gar nicht so viel :)
    • kreise untereinander verbinden, linke mit rechter spalte, gleiche spalte ist verboten
    • die verbindungen zeichnen (verbindungstyp 1:1)
    • die namen der kreise anzeigen (idealerweise die linke spalte dann auch links)
    • bei klick einen der kreise selektieren, um z.b. eigenschaften etc mitzugeben, das verbundene element soll dann nebst verbindungsline hervorgehoben werden
    • beim überfahren mit der maus element hervorheben, das verbundene element soll dann nebst verbindungslinie hervorgehoben werden
      • schon hier flackert es in sich
    • beim ziehen zum verbinden soll das gerade überfahrene element hervorgehoben werden
    • kein flackern beim verschieben
    • perfomance steigern
    • alle elemente sollen ihrem status entsprechend farbig markiert werden
      • hover: orange
      • selektiert: grün
        • nur beim ziehen, nicht beim einmal-klick
      • linie hervorgehoben: rot
      • hervorgehobenes verbundenes element: gelb
    • springen des selektierten elements verhindern (irgendwo ist noch was beim neuseitzen der location bei klick im argen)

    das meiste geht ja auch, wenn nur das blöde flackern und neuzeichnen nicht wäre, dito mit der performance.

    hatte gerade noch so die idee, (geht ja primär im mousemove um das komplette neuzeichnen) das aktuell selektierte und zu verschiebende(n) objekt(e) in eine extra liste zu packen, und dann alle anderen in ruhe zu lassen und nur diese(s) neu zu zeichnen.
    hört sich erstmal prima an, aber wenn es dann darum geht ein überfahrenes drunterliegendes objekt hervorzuheben wird es für mich schon unlösbar :(
    allerdings fehlt mir da bisher der zündende gedanke wie ich das anstelle ohne weitere 1001 zeilen code zu produzieren, nix gegen code, aber je mehr code um so schwerer wartbar meine ich.

    habe meinen letzten versuch mal angehängt.

    vielen dank bis hierher

    Farben entfernt. Du willst doch, dass man deinen Post liest?! Außerdem ist die Farbe "Rot" der Moderation vorbehalten. ~Thunderbolt
    Dateien
    • PaintTest01.zip

      (34,89 kB, 166 mal heruntergeladen, zuletzt: )

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Thunderbolt“ ()

    @FlyingEagle Ich halte Dich für befähigt, Texte im Post bunt einzufärben.
    Bist Du der Meinung, dass sich Dein Post deshalb einfacher liest?
    Ich nicht.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!