FWIW, the code below works for me as expected, i.e., after pressing <Enter> in the last text control, a new text control is added, focused, and scrolled into view. After adding a new control, m_scrolled->FitInside() must be called before textCtrl->Focus().
Code: Select all
#include <wx/wx.h>
#include <wx/scrolwin.h>
class MyFrame : public wxFrame
{
public:
MyFrame() : wxFrame(nullptr, wxID_ANY, "Test")
{
m_scrolledPanel = new wxScrolledWindow(this, wxID_ANY);
m_scrolledPanelSizer = new wxBoxSizer(wxVERTICAL);
for ( size_t i = 0; i < 5; ++i )
AddTextCtrl(false);
Bind(wxEVT_TEXT_ENTER, &MyFrame::OnTextEnter, this);
m_scrolledPanel->SetSizer(m_scrolledPanelSizer);
m_scrolledPanel->FitInside();
m_scrolledPanel->SetScrollRate(8, 8);
SetClientSize(FromDIP(wxSize(200, 100)));
}
private:
wxScrolledWindow* m_scrolledPanel{nullptr};
wxBoxSizer* m_scrolledPanelSizer{nullptr};
size_t m_textCtrlCount{0};
void AddTextCtrl(bool focus)
{
wxTextCtrl* textCtrl = new wxTextCtrl(m_scrolledPanel, wxID_ANY,
wxString::Format("wxTextCtrl #%zu", ++m_textCtrlCount),
wxDefaultPosition, wxDefaultSize,
wxTE_PROCESS_ENTER);
m_scrolledPanelSizer->Add(textCtrl, wxSizerFlags().Expand().Border());
m_scrolledPanel->FitInside();
if ( focus )
textCtrl->SetFocus();
}
void OnTextEnter(wxCommandEvent& event)
{
wxWindow* window = dynamic_cast<wxWindow*>(event.GetEventObject());
if ( !window->GetNextSibling() ) // last control, add a new one
AddTextCtrl(true);
else // just go to the next control
window->Navigate();
}
};
class MyApp : public wxApp
{
public:
bool OnInit() override
{
(new MyFrame())->Show();
return true;
}
}; wxIMPLEMENT_APP(MyApp);
wxWidgets 3.1.5, Windows 10.
EDIT
Sorry, I missed that you are not adding a single focusable control but a panel with child controls.
In this case, scrolling is not automatic; however, scrolling manually still seems to work for me in this example code:
Code: Select all
#include <wx/wx.h>
#include <wx/scrolwin.h>
class MyFrame : public wxFrame
{
public:
MyFrame() : wxFrame(nullptr, wxID_ANY, "Test")
{
m_scrolledPanel = new wxScrolledWindow(this, wxID_ANY);
m_scrolledPanelSizer = new wxBoxSizer(wxVERTICAL);
for ( size_t i = 0; i < 3; ++i )
AddTextCtrls(false);
Bind(wxEVT_TEXT_ENTER, &MyFrame::OnTextEnter, this);
m_scrolledPanel->SetSizer(m_scrolledPanelSizer);
m_scrolledPanel->FitInside();
m_scrolledPanel->SetScrollRate(8, 8);
SetClientSize(FromDIP(wxSize(600, 200)));
}
private:
wxScrolledWindow* m_scrolledPanel{nullptr};
wxBoxSizer* m_scrolledPanelSizer{nullptr};
size_t m_textPanelCount{0};
void AddTextCtrls(bool focus)
{
wxPanel* panel = new wxPanel(m_scrolledPanel);
wxBoxSizer* panelSizer = new wxBoxSizer(wxHORIZONTAL) ;
wxTextCtrl* textCtrl = nullptr;
++m_textPanelCount;
for ( size_t i = 0; i < 3; ++i )
{
textCtrl = new wxTextCtrl(panel, wxID_ANY,
wxString::Format("wxTextCtrl #%zu.%zu", m_textPanelCount, i + 1),
wxDefaultPosition, wxDefaultSize,
wxTE_PROCESS_ENTER);
panelSizer->Add(textCtrl, wxSizerFlags().Expand().Border());
}
panel->SetSizer(panelSizer);
m_scrolledPanelSizer->Add(panel, wxSizerFlags().Expand().Border());
m_scrolledPanel->FitInside();
if ( focus )
{
panel->SetFocus();
m_scrolledPanel->Scroll(0, panel->GetPosition().y);
}
}
void OnTextEnter(wxCommandEvent& event)
{
wxWindow* window = dynamic_cast<wxWindow*>(event.GetEventObject());
if ( !window->GetNextSibling() && // the last control on the last
!window->GetParent()->GetNextSibling() ) // panel, add a new panel
{
AddTextCtrls(true);
}
else // just go to the next control
{
window->Navigate();
}
}
};
class MyApp : public wxApp
{
public:
bool OnInit() override
{
(new MyFrame())->Show();
return true;
}
}; wxIMPLEMENT_APP(MyApp);
But in your case, do you really need to add a panel as the parent of text controls, instead of adding them as direct children of the wxScrolledWindow?
Obviously, scrolling into view when adding new controls is just a part of the issue. A control should also be scrolled into view whenever it gets focused, which does not happen in the code above. This seems like a deficit in wxScrolledWindow, and I would ask in wx-users if there is a simple solution to this, instead of dealing with it in the user code.
I wonder if it is related to this code:
https://github.com/wxWidgets/wxWidgets/ ... .cpp#L1098