Scrolling
Jump to navigation
Jump to search
Scrolling widgets
#include "wx/wx.h"
#include <iostream>
class ScrolledWidgetsPane : public wxScrolledWindow
{
public:
ScrolledWidgetsPane(wxWindow* parent, wxWindowID id) : wxScrolledWindow(parent, id)
{
// the sizer will take care of determining the needed scroll size
// (if you don't use sizers you will need to manually set the viewport size)
wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL);
// add a series of widgets
for (int w=1; w<=120; w++)
{
wxButton* b = new wxButton(this, wxID_ANY, wxString::Format(wxT("Button %i"), w));
sizer->Add(b, 0, wxALL, 3);
}
this->SetSizer(sizer);
// this part makes the scrollbars show up
this->FitInside(); // ask the sizer about the needed size
this->SetScrollRate(5, 5);
}
};
// A sample app that adds the scrolled pane to a frame to make this code runnable
class MyApp: public wxApp
{
wxFrame *frame;
public:
bool OnInit()
{
wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
frame = new wxFrame((wxFrame *)NULL, -1, wxT("Scrolling Widgets"), wxPoint(50,50), wxSize(650,650));
ScrolledWidgetsPane* my_image = new ScrolledWidgetsPane(frame, wxID_ANY);
sizer->Add(my_image, 1, wxEXPAND);
frame->SetSizer(sizer);
frame->Show();
return true;
}
};
IMPLEMENT_APP(MyApp)
Scrolling a render / an image
Scrolling a render (e.g. an image) can be done using a wxScrolledWindow, like in the following example :
#include "wx/wx.h"
#include <iostream>
class ScrolledImageComponent : public wxScrolledWindow
{
wxBitmap* bitmap;
int w,h;
public:
ScrolledImageComponent(wxWindow* parent, wxWindowID id, wxString image_path) : wxScrolledWindow(parent, id)
{
wxImage image(image_path);
if(!image.IsOk())
{
wxMessageBox(wxT("there was an error loading the image"));
return;
}
w = image.GetWidth();
h = image.GetHeight();
/* init scrolled area size, scrolling speed, etc. */
SetScrollbars(1,1, w, h, 0, 0);
bitmap = new wxBitmap( image );
}
~ScrolledImageComponent()
{
delete bitmap;
}
void OnDraw(wxDC& dc)
{
/* render the image - in a real app, if your scrolled area
is somewhat big, you will want to draw only visible parts,
not everything like below */
dc.DrawBitmap(*bitmap, 0, 0, false);
// also check wxScrolledWindow::PrepareDC
}
};
class MyApp: public wxApp
{
wxFrame *frame;
public:
bool OnInit()
{
wxInitAllImageHandlers();
wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
frame = new wxFrame((wxFrame *)NULL, -1, wxT("Scrolling an Image"), wxPoint(50,50), wxSize(650,650));
ScrolledImageComponent* my_image = new ScrolledImageComponent(frame, wxID_ANY, wxT("my_image.jpg") );
sizer->Add(my_image, 1, wxALL | wxEXPAND, 120);
frame->SetSizer(sizer);
frame->Show();
return true;
}
};
IMPLEMENT_APP(MyApp)
If you render lots of stuff, you will want to use wxScrolledWindow::GetViewStart along with the size of the scrolled window to render only the parts which are visible, in order to maintain good performance.
Synchronizing 2 scrolled panes
The question is often asked, here is a way to do it
#include "wx/wx.h"
#include <iostream>
class ScrolledImageComponent : public wxScrolledWindow
{
wxBitmap* bitmap;
int w,h;
ScrolledImageComponent* m_peer;
public:
ScrolledImageComponent(wxWindow* parent, wxWindowID id, wxString image_path) : wxScrolledWindow(parent, id)
{
m_peer = NULL;
wxImage image(image_path);
if(!image.IsOk())
{
wxMessageBox(wxT("there was an error loading the image"));
return;
}
w = image.GetWidth();
h = image.GetHeight();
/* init scrolled area size, scrolling speed, etc. */
SetScrollbars(1,1, w, h, 0, 0);
bitmap = new wxBitmap( image );
Connect(wxID_ANY, wxEVT_SCROLLWIN_THUMBTRACK, wxScrollWinEventHandler(ScrolledImageComponent::onScroll), NULL, this);
Connect(wxID_ANY, wxEVT_SCROLLWIN_THUMBRELEASE, wxScrollWinEventHandler(ScrolledImageComponent::onScroll), NULL, this);
Connect(wxID_ANY, wxEVT_SCROLLWIN_LINEUP, wxScrollWinEventHandler(ScrolledImageComponent::onScroll), NULL, this);
Connect(wxID_ANY, wxEVT_SCROLLWIN_LINEDOWN, wxScrollWinEventHandler(ScrolledImageComponent::onScroll), NULL, this);
}
~ScrolledImageComponent()
{
delete bitmap;
}
void SetPeer(ScrolledImageComponent* other)
{
m_peer = other;
}
void onScroll(wxScrollWinEvent& evt)
{
if (m_peer != NULL)
{
m_peer->Scroll(GetScrollPos(wxHORIZONTAL), GetScrollPos(wxVERTICAL));
}
evt.Skip(); // let the event go
}
void OnDraw(wxDC& dc)
{
/* render the image - in a real app, if your scrolled area
is somewhat big, you will want to draw only visible parts,
not everything like below */
dc.DrawBitmap(*bitmap, 0, 0, false);
// also check wxScrolledWindow::PrepareDC
}
};
class MyApp: public wxApp
{
wxFrame *frame;
public:
bool OnInit()
{
wxInitAllImageHandlers();
wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
frame = new wxFrame((wxFrame *)NULL, -1, wxT("Scrolling an Image"), wxPoint(50,50), wxSize(650,650));
ScrolledImageComponent* my_image = new ScrolledImageComponent(frame, wxID_ANY, wxT("my_image.jpg") );
sizer->Add(my_image, 1, wxALL | wxEXPAND, 5);
ScrolledImageComponent* my_image2 = new ScrolledImageComponent(frame, wxID_ANY, wxT("my_image.jpg") );
sizer->Add(my_image2, 1, wxALL | wxEXPAND, 5);
my_image->SetPeer(my_image2);
my_image2->SetPeer(my_image);
frame->SetSizer(sizer);
frame->Show();
return true;
}
};
IMPLEMENT_APP(MyApp)