wxPaintDC mit DrawBitmap



  • Hallo Leute,
    ich bin grade an meine forscherischen Grenzen gestoßen und muss
    doch mal um Hilfe bitten.
    Ich habe vor kurzem Angefangen mit wxWidgets rumzuspielen und das
    Meiste klappt auch wunderbar. Jetzt wollte ich ein kleines Fenster machen
    mit 3 wxButtons und ein Hintergrundbild, welches unter den Buttons liegen
    soll.
    Nun hab ich rumgelesen und nachgelesen und nachgeforscht und habe dann
    schließlich ein bisschen rumgebastelt mit wxDC, welches dann ein wxBitmap
    auf mein Fenster malen soll (mit DrawBitmap). Hat nicht funktioniert. Dann
    habe ich aus wxDC wxPaintDC gemacht. Hat immer noch nicht geklappt.
    Danach hab ich gelesen, dass das Panel auf dem die Buttons liegen das Bild
    verdeckt. Also hab ich die Knöpfe und das Panel auskommentiert. Hat immer
    noch kein Bild angezeigt. Dann hab ich noch irgendwo ein wenig Quellcode
    zusammengesucht mit diversen Buffern die ich nicht versteh. Hat immer noch
    nicht gefunzt.

    Jetzt muss ich fragen: Wie krieg ich da mein Bild rein, oder noch besser
    wie krieg ich das Bild rein und Buttons drauf?

    // base.cpp
    
    #include <wx/wx.h>
    #include "base.h"
    #include <iostream>
    
    IMPLEMENT_APP(MyApp)
    bool MyApp::OnInit(){
    	wxImage::AddHandler( new wxPNGHandler );
    	BasicFrame *frame =
    		new BasicFrame(wxT("Willkommen"),50,50,200,250);
    	frame->Show(TRUE);
    	SetTopWindow(frame);
    	return TRUE;
    }
    
    BasicFrame::BasicFrame(
    					   const wxChar *title,
    					   int xpos, int ypos,
    					   int width, int height)
    					   : wxFrame ( (wxFrame *) NULL,
    					   -1, title,
    					   wxPoint(xpos,ypos),
    					   wxSize(width,height),wxDEFAULT_FRAME_STYLE){
    						   SetMinSize(wxSize(200,250));
    						   SetMaxSize(wxSize(200,250));
    						   Centre(wxBOTH);
    
    						   wxBitmap background(wxT("BackgroundMenu.png"),wxBITMAP_TYPE_PNG);
    	                     //panel = new wxPanel ( this, wxID_ANY, wxDefaultPosition,wxDefaultSize);
    						   wxPaintDC dc(this);
    						   dc.DrawBitmap(background, 100, 100 );
    			             /*button = new wxButton (panel, wxID_OK, wxT("Starten"),wxPoint(55,30), wxDefaultSize);
    						   button2 = new wxButton (panel, wxID_ABOUT, wxT("Optionen"),wxPoint(55,70), wxDefaultSize);
    						   button3 = new wxButton (panel, wxID_ADD, wxT("Beenden"),wxPoint(55,110), wxDefaultSize);*/
    						   CreateStatusBar(1);
    }
    

    Es kommt kein Fehler, leider passiert aber auch nichts.
    Es wäre sehr nett, wenn mir da jemand unter die Arme greifen könnte 🙂



  • Dieser Thread wurde von Moderator/in SeppJ aus dem Forum C++ (auch C++0x) in das Forum Andere GUIs - Qt, GTK+, wxWidgets verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • Du kannst wxPaintDC nur im Paint-Event-Handler benutzen! Anderenfalls musst du wxClientDC hernehmen (wovon ich aber abrate).
    Ausserdem solltest du in Betracht ziehen, Sizer zu verwenden anstatt die Widgets selbst zu positionieren (siehe wxWidgets Dokumentation fuer weiter Info).

    Hier ein Beispiel, wie man das Problem mit einem Paint-Event-Handler loesen kann:

    #include <wx/wx.h>
    
    class App : public wxApp
    {
    public:
    	bool OnInit();
    };
    
    wxIMPLEMENT_APP(App);
    
    class Frame : public wxFrame
    {
    public:
    	Frame() : wxFrame(NULL, wxID_ANY, wxT("Bild mit Buttons")),
    		m_Bitmap(wxT("BackgroundMenu.png"), wxBITMAP_TYPE_PNG)
    	{
    		wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL);		// erstellt vertikalen Sizer, d.h. alle Widgets werden jetzt vertikal von oben nach unten hinzugefuegt
    		sizer->Add(new wxButton(this, wxID_OK, wxT("&Starten")), 0, wxALIGN_CENTER|wxALL, 10);
    		sizer->Add(new wxButton(this, wxID_ABOUT, wxT("&Optionen")), 0, wxALIGN_CENTER|wxALL, 10);
    		sizer->Add(new wxButton(this, wxID_ADD, wxT("&Beenden")), 0, wxALIGN_CENTER|wxALL, 10);
    		SetSizer(sizer);	// sizer setzen
    	}
    private:
    	wxBitmap m_Bitmap;
    
    	void OnPaint(wxPaintEvent&);	// Paint-Event-Handler
    
    	DECLARE_EVENT_TABLE()
    };
    
    BEGIN_EVENT_TABLE(Frame, wxFrame)
    	EVT_PAINT(Frame::OnPaint)
    END_EVENT_TABLE()
    
    void Frame::OnPaint(wxPaintEvent&)
    {
    	wxPaintDC PaintDC(this);	// muss immer erstellt werden - egal ob du's brauchst oder nicht
    	if (m_Bitmap.IsOk())
    		PaintDC.DrawBitmap(m_Bitmap, 0, 0);	// zeige Bitmap, wenn es erfolgrecih geladen wurde
    }
    
    bool App::OnInit()
    {
    	wxImage::AddHandler(new wxPNGHandler);
    
    	Frame* f = new Frame;
    	f->Show();
    
    	return true;
    }
    


  • Vielen Dank!
    Funktioniert einwandfrei!

    Darauf muss ich aber noch eine weitere Frage stellen, da ich das mit dem
    Event Table noch nicht so ganz verinnerlicht habe.
    Wie kann ich denn z.B. durch das Drücken eines Buttons das malen des Bitmaps
    auslösen? Weil über den die Event Tabelle lässt sich das ja schlecht machen,
    wenn wxPaintDC ein Paint Event Handler benötigt (habe bis jetzt Events nur über
    die Event Tabelle, z.B. EVT_BUTTON, abgefangen und weiß nicht wie es anders geht).

    Mit freundlichen Grüßen
    Xenowar



  • Der Paint-Event-Handler wird immer dann aufgerufen, wenn das Clientfeld des Fensters/Widget "beschaedigt" wird (z.B. durch aendern der Groesse) oder wenn du den Paint-Event selbst generierst (durch senden des Events mit ProcessWindowEvent oder im Falle des PAINT-Events ganz einfach durch die Funktion Refresh()).
    D.h. alles was du machen musst ist eine bool-Variable zu setzen und dann ein PAINT-Event senden:

    ...
    class Frame
    {
    ...
    bool m_ShowBitmap;
    };
    
    ...
    EVT_BUTTON(wxID_OK, Frame::OnButton)
    ...
    
    void Frame::OnPaint(wxPaintEvent&)
    {
    	wxPaintDC PaintDC(this);	// muss immer erstellt werden - egal ob du's brauchst oder nicht
    	if (m_ShowBitmap && m_Bitmap.IsOk())	// Bitmap wird nur gezeigt, wenn m_ShowBitmap true ist
    		PaintDC.DrawBitmap(m_Bitmap, 0, 0);	// zeige Bitmap, wenn es erfolgrecih geladen wurde
    }
    
    void Frame::OnButton(wxCommandEvent&)
    {
    	m_ShowBitmap = !m_ShowBitmap;	// Wert umkehren
    	Refresh();	// neu zeichnen erzwingen
    }
    
    ...
    

    Die "Event Tables" ist nur eine Moeglichkeiten Event-Handler zu setzen. Das ganze laesst sich auch dynamisch machen mit Connect() (oder seit 2.9 mit Bind()), z.B. koenntest du statt des Event Tables auch das im Konstruktor vom Frame machen:

    Connect(wxEVT_PAINT, wxPaintEventHandler(Frame::OnPaint));
    Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(Frame::OnButton));
    

    Das hat den Vorteil, dass du zur Laufzeit den Event-Handler noch aendern kannst (wers braucht). Ich selbst verwende aber nur Event Tables...



  • Ein weiteres mal, vielen Dank!
    Heute hab ich einiges über die Funktionsweise von wxWidgets gelernt!


Anmelden zum Antworten