[wxWidgets] DeviceContexts um Bilder anzuzeigen?



  • Hallo zusammen,

    ich beschäftige mich mit wxWidgets und habe da eine Frage, auf die ich nach recht langer Suche leider noch keine befriedigende Antwort gefunden habe. Daher versuche ich mal mein Glück hier im Forum.

    Mein Programm soll folgendes können:

    Ich habe den Client-Bereich meines Fensters in 3 Teile aufgeteilt. Links sind ein paar Knöpfe, etc, in der Mitte und rechts sollen Bilder angezeigt werden. Dabei kann man über die Knöpfe Dinge, wie zum Beispiel eine Skalierung des Bildes vornehmen. In der Mitte ist eine Vorschau, wie das Bild anschließend aussieht und rechts ist das Originalbild zum Vergleich.

    Wie würdet ihr dieses Problem angehen? Mit DeviceContexts? Mit StaticBitmaps?

    Ich muss sagen, dass ich leider etwas verwirrt bin und die Erleuchtung noch suche.

    Der Stand der Dinge ist momentan, dass ich das über den PaintEvent mache aber dann lädt er das Bild ja zum Beispiel beim Skalieren des Fensters jedes mal neu, was ja eigentlich Quatsch ist.

    Ich denke es wäre besser die Bilder über einen MemoryDC anzuzeigen... diesen bekomme ich aber leider nicht visualisiert 😞

    Also die Frage nochmal kompakt:

    Wie zeige ich am besten BMPs, JPGs, usw an?

    Schöne Grüße,
    Simon



  • Ich mach's so. Vielleicht hülft es dir ja weiter:

    void wxGDPdfPage::OnPaint (wxPaintEvent& event)
    {
       wxPaintDC dc(this);
    
       wxRegionIterator upd(GetUpdateRegion());
       if (!upd) return;   // Aus irgendeinem Grund will das Scrolled Win auch die Seiten neu Zeichnen, die gar nicht sichtbar sind.
    
       if (!m_bmp) {
          dc.SetBackground(wxBrush(wxColour(255, 255, 255)));
          dc.Clear();
    
          m_bmp = new wxBitmap(m_cx, m_cy, 24);
    
          {
             wxMemoryDC dcMem;
             dcMem.SelectObject(*m_bmp);
    
             m_doc->render(dcMem, m_page);
    
             dcMem.SelectObject(wxNullBitmap);
          }
       }
    
       if (m_bmp) dc.DrawBitmap(*m_bmp, 0, 0);
    }
    


  • Schonmal Danke für die schnelle Hilfe!

    Also das Problem ist teilweise gelöst. Soll heißen, dass von dem Bild nun mehr dargestellt wird, wenn man das Fenster vergrößert. Das scheint mir aber eindeutig zu viele Ressourcen zu fressen, da es ruckelt (was es auf einem modernen Rechner bei sowas eigentlich nicht sollte 😉 ).

    Mein Code sieht wie folgt aus: Habe ich da elementare Fehler gemacht?

    void PnlPhaseDistribution::OnPaint (wxPaintEvent& event){
        wxPaintDC dcDummy(this);
        wxPaintDC dc (display);
    
        wxRegionIterator upd(GetUpdateRegion());
        if (!upd) return;   // Aus irgendeinem Grund will das Scrolled Win auch die Seiten neu Zeichnen, die gar nicht sichtbar sind.
    
        wxBitmap m_bmp;
        wxString filename = parentMod->getFirstSourceFile();
    
        m_bmp.LoadFile(filename, wxBITMAP_TYPE_ANY);
    
        wxMemoryDC dcMem;
        dcMem.SelectObject(m_bmp);
    
        dcMem.SelectObject(wxNullBitmap);
    
        dc.DrawBitmap(m_bmp, 0, 0);
    }
    

    Dankeschön 🙂

    Edit:
    So, ich habe es jetzt glaube ich endlich verstanden. Ein Fehler war natürlich, das Bild bei jedem PaintEvent neu von der Platte zu laden. Das habe ich geändert und jetzt funktioniert es auch wunderbar. Mein Code sieht nun so aus:

    void PnlPhaseDistribution::OnPaint (wxPaintEvent& event){
        wxPaintDC dcDummy(this);
        wxPaintDC dc (display);
    
        wxRegionIterator upd(GetUpdateRegion());
        if (!upd) return;
    
        dc.DrawBitmap(bmpTest, 0, 0);
    }
    
    1. Der MemoryDC ist doch nur notwendig, wenn ich das Bild maipulieren möchte, oder?

    2. Wie würde ich jetzt vorgehen, wenn ich das Bild verändern, zum Beispiel per Knopfdruck alle Pixel um einen Schritt verschieben, möchte? Schreibe ich dann eine Methode, die das macht und erstelle am Ende ein PaintEvent, mit dem ich dann den OnPaint Handler aufrufe?


  • Mod

    evtl. mal einen BufferedPaintDC ausprobieren. Ansonsten musst du evtl. auch das Bild in Kacheln aufteilen, und dann jehweils nur die sichtbaren Kacheln anzeigen.



  • Also das Anzeigen der Bilder funktioniert jetzt schonmal so, wie ich mir das vorgestellt habe, vielen Dank.

    Leider ist jetzt noch ein kleines Problem im Weg:
    Wenn ich scrolle (die Bilder sind zu groß für meine Fenster), wird zwar verschoben, aber die Daten, die eigentlich neu kommen sollten, kommen nicht. Es wird also mit der Hintergrundfarbe aufgefüllt.

    Wenn ich jetzt das Fenster verkleinere und den nichtgefüllten Bereich "überdecke", dann wieder auf ursprüngliche Größe ausdehne, ist das Bild so gezeichnet, wie es sein sollte. Daher vermute ich mal, dass ich irgendwie nach dem Scrollen nochmal neu zeichnen lassen muss...

    Ich hoffe, mein Problem ist hier klar geworden. Wie kann ich es denn lösen?

    Das ist mein OnPaint handler für ein Panel, das u.a. das wxScrolledWindow display enthält, in das das Bild gezeichnet werden soll.

    void PnlPhaseDistribution::OnPaint (wxPaintEvent& event){
        wxPaintDC dcDummy(this);
        wxPaintDC dc (display);
        display->DoPrepareDC(dc);
    
        dc.DrawBitmap(*displayBMP, 0, 0);
    }
    

    Und hier werden die Scrollbars eingestellt, wenn das Panel im Programm angezeigt werden soll.

    // Zeigt das Panel PhaseDistribution an und bereitet die Daten vor
    void Modeller::DoPhaseDistribution(){
        wxString filename = getFirstSourceFile();
        if (filename != wxT("")){
            wxBitmap* bmp = new wxBitmap(filename, wxBITMAP_TYPE_ANY);
            pnlPhaseDistribution->setDisplayBMP(bmp);   // Uebergibt das Bild, welches angezeigt werden soll
            wxScrolledWindow* scrlWdw = pnlPhaseDistribution->getDisplay();
            scrlWdw->SetScrollbars(10, 10, bmp->GetWidth()/10, bmp->GetHeight()/10);
        } else {
            wxMessageBox(wxT("No source files added"));
        }
        showPanel(PHASE_DISTRIBUTION);
    }
    

    Ich bin für jede Hilfe dankbar.


Anmelden zum Antworten