I think there are several issues with your code, the main is that you are probably not redrawing the panel when needed (i.e., in its paint event handler) and then lose the bitmap.
E.g., here is a simple unoptimized example of implementing a panel that has a bitmap filling it (without maintaining the bitmap proportions), please notice that it uses wxImage::Rescale() instead of supposedly (much) faster wxDC::StretchBlit() to achieve better quality of the scaled bitmap. Truth to be told scaled bitmaps, particularly those produced artificially (i.e., computer drawings) look bad when rescaled regardless.
Code: Select all
#include <wx/wx.h>
#include <wx/filename.h>
class BitmapPanel : public wxPanel
{
public:
BitmapPanel(wxWindow* parent, const wxBitmap& bitmap = wxNullBitmap)
: wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxFULL_REPAINT_ON_RESIZE),
m_bitmap(bitmap)
{
SetBackgroundStyle(wxBG_STYLE_PAINT);
Bind(wxEVT_PAINT, &BitmapPanel::OnPaint, this);
}
void SetBitmap(const wxBitmap& bitmap)
{
m_bitmap = bitmap;
m_scaledBitmap = wxNullBitmap;
Update(); Refresh();
}
private:
wxBitmap m_bitmap, m_scaledBitmap;
static wxBitmap RescaleBitmap(const wxBitmap& bitmap, const wxSize& newSize)
{
if ( !bitmap.IsOk() )
return wxNullBitmap;
const wxImage image = bitmap.ConvertToImage();
return wxBitmap(image.Scale(newSize.GetWidth(), newSize.GetHeight(), wxIMAGE_QUALITY_HIGH));
}
void OnPaint(wxPaintEvent&)
{
wxPaintDC dc(this);
dc.SetBackground(*wxBLACK_BRUSH);
dc.Clear();
if ( !m_bitmap.IsOk() )
return;
const wxSize dcSize = dc.GetSize();
if ( !m_scaledBitmap.IsOk() || m_scaledBitmap.GetSize() != dcSize )
m_scaledBitmap = RescaleBitmap(m_bitmap, dcSize);
dc.DrawBitmap(m_scaledBitmap, 0, 0, true);
}
};
class MyFrame : public wxFrame
{
public:
MyFrame() : wxFrame(NULL, wxID_ANY, "Test")
{
const int borderAround = FromDIP(10);
wxBoxSizer* bSizer = new wxBoxSizer(wxVERTICAL);
wxButton* button = new wxButton(this, wxID_ANY, "Load image file...");
bSizer->Add(button, wxSizerFlags().Expand().Border(wxALL, borderAround));
button->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &MyFrame::OnLoadImageFile, this);
m_bitmapPanel = new BitmapPanel(this);
bSizer->Add(m_bitmapPanel, wxSizerFlags().Expand().Proportion(1).Border(wxALL, borderAround));
SetSizer(bSizer);
}
private:
BitmapPanel* m_bitmapPanel;
void OnLoadImageFile(wxCommandEvent&)
{
static wxString fileName;
wxImage image;
fileName = wxFileSelector("Choose Image to Load", "", fileName, "",
"Image files (*.jpg;*.png;*.tga;*.bmp;*.tiff;*.gif;*.ico;*.pcx)| *.jpg;*.png;*.tga;*.bmp;*.tiff;*.gif;*.ico;*.pcx",
wxFD_OPEN | wxFD_FILE_MUST_EXIST, this);
if ( fileName.empty() )
return;
if ( image.LoadFile(fileName) )
{
m_bitmapPanel->SetBitmap(wxBitmap(image));
SetTitle(wxString::Format("Simple Image Viewer (%s: %d x %d pixels)",
wxFileName(fileName).GetFullName(), image.GetWidth(), image.GetHeight()));
}
}
};
class MyApp : public wxApp
{
public:
virtual bool OnInit()
{
wxInitAllImageHandlers();
(new MyFrame())->Show();
return true;
}
}; wxIMPLEMENT_APP(MyApp);
- bitmappanel.png (38.67 KiB) Viewed 1949 times
The simpler variant of OnPaint() using wxDC::StretchBlit could look like this
Code: Select all
void BitmapPanel::OnPaint(wxPaintEvent&)
{
wxPaintDC dc(this);
dc.SetBackground(*wxBLACK_BRUSH);
dc.Clear();
if ( !m_bitmap.IsOk() )
return;
wxMemoryDC mdc(m_bitmap);
dc.StretchBlit(wxPoint(0, 0), dc.GetSize(), &mdc, wxPoint(0,0), mdc.GetSize(), wxCOPY, true);
}