wxScrolledWindow do not scroll to focused wxTextCtrl Topic is solved

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Harsh
Knows some wx things
Knows some wx things
Posts: 32
Joined: Tue Apr 13, 2021 5:03 am

Re: wxScrolledWindow do not scroll to focused wxTextCtrl

Post by Harsh » Fri Apr 23, 2021 8:21 pm

PB wrote:
Fri Apr 23, 2021 7:51 pm
I am stupid so I have no idea how that fixes the issue here, which boils down to "a control does not scroll into view after getting focus"?
Tomorrow I will post whole code.

If next row present then just call Navigate NO AddRow here.
If row below visual rect Then Scroll by one step.

PB
Part Of The Furniture
Part Of The Furniture
Posts: 3042
Joined: Sun Jan 03, 2010 5:45 pm

Re: wxScrolledWindow do not scroll to focused wxTextCtrl

Post by PB » Sat Apr 24, 2021 7:21 am

Scrolling and navigating is not an issue, that is easy do deal with.

I meant scrolling into view when focused, regardless of the method (keyboard, mouse...).

Harsh
Knows some wx things
Knows some wx things
Posts: 32
Joined: Tue Apr 13, 2021 5:03 am

Re: wxScrolledWindow do not scroll to focused wxTextCtrl

Post by Harsh » Sat Apr 24, 2021 7:43 am

PB wrote:
Fri Apr 23, 2021 7:51 pm
I am stupid so I have no idea how that fixes the issue here, which boils down to "a control does not scroll into view after getting focus"?

Code: Select all

#include <wx/wx.h>
#include <wx/scrolwin.h>

class MyFrame : public wxFrame
{
	private:
        wxPanel *panel,*p;
        wxBoxSizer *vbox,*vbox1,*hbox;
        wxTextCtrl *txt;
        wxScrolledWindow *sw;
        
        wxRect rect;
        int flag=0,flag1=0;
        wxButton *btn;
		
	void OnKeyDown(wxKeyEvent &event){
		event.Skip();
		txt=(wxTextCtrl*)event.GetEventObject();
		if(event.GetKeyCode()==8){
			txt->Navigate(wxNavigationKeyEvent::IsBackward);
		}else if(event.GetKeyCode()==13){
			if(txt->GetName()=="ROW"){
				if(!txt->GetParent()->GetNextSibling()){
					AddRow(0);
				}else{
					p=wxDynamicCast(txt->GetParent()->GetNextSibling(),wxPanel);
				}
				sw->GetViewStart(&flag,&flag1);
				rect=p->GetRect();
				flag=rect.GetY()+rect.GetHeight();
				rect=sw->GetRect();
				if(flag>rect.GetHeight()){
					flag1++;
					sw->Scroll(0,flag1);
				}
			}
			txt->Navigate(wxNavigationKeyEvent::IsForward);
		}
	}
	void AddRow(int ind){
		p=new wxPanel(sw);
		hbox=new wxBoxSizer(wxHORIZONTAL);

		for(int i=0;i<9;i++){
			txt=new wxTextCtrl(p,wxID_ANY,wxT(""),wxDefaultPosition,wxSize(5,25),wxTE_PROCESS_ENTER);
			txt->Bind(wxEVT_KEY_DOWN,&MyFrame::OnKeyDown,this);
			hbox->Add(txt,1,wxEXPAND|wxALL,5);
		}
		txt=new wxTextCtrl(p,1,wxString::Format(wxT("%i"),ind),wxDefaultPosition,wxSize(5,25),wxTE_PROCESS_ENTER);
		txt->SetName("ROW");
		txt->Bind(wxEVT_KEY_DOWN,&MyFrame::OnKeyDown,this);
		hbox->Add(txt,1,wxEXPAND|wxALL,5);
		p->SetSizer(hbox);

		vbox1->Add(p,0,wxEXPAND);
		vbox1->Layout();
		sw->FitInside();
	}
	public:
		MyFrame() : wxFrame(NULL, wxID_ANY, "Test")
		{
			panel=new wxPanel(this);
			vbox=new wxBoxSizer(wxVERTICAL);

			vbox->Add(new wxTextCtrl(panel,wxID_ANY,wxT("")));
			vbox->Add(new wxTextCtrl(panel,wxID_ANY,wxT("")));

			sw=new wxScrolledWindow(panel);
			sw->SetScrollRate(35,35);
			vbox1=new wxBoxSizer(wxVERTICAL);
			sw->SetSizer(vbox1);
			sw->FitInside();
			for(flag=0;flag<100;flag++){
				AddRow(flag);
			}
			vbox->Add(sw,1,wxEXPAND|wxALL,5);

			vbox->Add(new wxTextCtrl(panel,wxID_ANY,wxT("")));
			vbox->Add(new wxTextCtrl(panel,wxID_ANY,wxT("")));
			vbox->Add(new wxTextCtrl(panel,wxID_ANY,wxT("")));
			vbox->Add(new wxTextCtrl(panel,wxID_ANY,wxT("")));
			panel->SetSizer(vbox);
		}
};

class MyApp : public wxApp
{
public:
    bool OnInit() override
    {     
        (new MyFrame())->Show(true);               
        return true;
    }
};
IMPLEMENT_APP(MyApp);
* Text Case :
1. Bring VScroll in middle.
2. Click on last row's last text field.
3. Press Enter
4. Check if next row present txt->GetParent->GetNextSibling()
5. If present, call Navigate
6. If Not present Call AddRow
7. If Focused txt below scrolledWindow, if(scrolledWindow->GetHeight>(txt->GetY()+txt->GetHeight())
8. Get Current YScroll Position & increament it according to SetSCrollRate(xRate,yRate)
scrolledWindow(&x,&y)
scrolledWindow->Scroll(0,++y); (In my case yRate=txt.Height)

Harsh
Knows some wx things
Knows some wx things
Posts: 32
Joined: Tue Apr 13, 2021 5:03 am

Re: wxScrolledWindow do not scroll to focused wxTextCtrl

Post by Harsh » Sat Apr 24, 2021 7:45 am

PB wrote:
Fri Apr 23, 2021 4:14 pm
Out of curiousity, I tried if the autoscroll works when I use wxStaticBox instead of wxPanel as the parent of wxTextCtrls, which is then added to the wxScrolledWindow. It works, so the issue does not seem to be related to whether a wxTextCtrl is a direct child of the wxScrolled, its parent being a wxPanel may be the problem.

Code: Select all

#include <wx/wx.h>
#include <wx/scrolwin.h>
#include <wx/statbox.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_textGroupsCount{0};

    void AddTextCtrls(bool focus)
    {
        wxStaticBoxSizer* staticBoxSizer = nullptr;
        wxTextCtrl*       textCtrl = nullptr;

        staticBoxSizer = new wxStaticBoxSizer(wxHORIZONTAL, m_scrolledPanel,
                                wxString::Format("Panel #%zu", ++m_textGroupsCount));

        for ( size_t i = 0; i < 3; ++i )
        {
            textCtrl = new wxTextCtrl(staticBoxSizer->GetStaticBox(), wxID_ANY,
                                wxString::Format("wxTextCtrl #%zu.%zu", m_textGroupsCount, i + 1),
                                wxDefaultPosition, wxDefaultSize,
                                wxTE_PROCESS_ENTER);

            staticBoxSizer->Add(textCtrl, wxSizerFlags().Expand().Border());
        }

        m_scrolledPanelSizer->Add(staticBoxSizer, wxSizerFlags().Expand().Border());
        m_scrolledPanel->FitInside();

        if ( focus )
            staticBoxSizer->GetStaticBox()->SetFocus();
    }

    void OnTextEnter(wxCommandEvent& event)
    {
        wxWindow* window = dynamic_cast<wxWindow*>(event.GetEventObject());

        if ( !window->GetNextSibling() &&             // the last control in the last
             !window->GetParent()->GetNextSibling() ) // control group, add a new control group
        {
            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);
Once again, I would ask: Do the wxTextCtrls need to have an extra panel as their parent, cannot they be added as direct children of the wxScrolled?

I want to give other features in my app. Like hover effect to row, select row, pop-up menus etc.

User avatar
doublemax
Moderator
Moderator
Posts: 16022
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxScrolledWindow do not scroll to focused wxTextCtrl

Post by doublemax » Sat Apr 24, 2021 7:54 am

Harsh wrote:
Sat Apr 24, 2021 7:45 am
I want to give other features in my app. Like hover effect to row, select row, pop-up menus etc.
This sounds like you're re-inventing a control like wxListCtrl, wxDataViewCtrl or wxGrid. Are you aware of these classes?
Use the source, Luke!

Post Reply