wxScrolledWindow is slow when scrolling through long text
wxScrolledWindow is slow when scrolling through long text
Hi,
I have a wxScrolledWindow widget that has a number of wxStaticText widgets with long texts. On Windows (GTK doesn't have this problem), the scrolling would become slow when going through texts that have a somehow big number of lines. How can I make it faster? Is there a way to enable hardware acceleration when scrolling?
I have a wxScrolledWindow widget that has a number of wxStaticText widgets with long texts. On Windows (GTK doesn't have this problem), the scrolling would become slow when going through texts that have a somehow big number of lines. How can I make it faster? Is there a way to enable hardware acceleration when scrolling?
Re: wxScrolledWindow is slow when scrolling through long text
One case, wxStaticText calc its size to fit the text by default, try wxST_NO_AUTORESIZE.MJaoune wrote: ↑Tue Oct 15, 2019 1:37 am Hi,
I have a wxScrolledWindow widget that has a number of wxStaticText widgets with long texts. On Windows (GTK doesn't have this problem), the scrolling would become slow when going through texts that have a somehow big number of lines. How can I make it faster? Is there a way to enable hardware acceleration when scrolling?
Re: wxScrolledWindow is slow when scrolling through long text
But that only happens once, am I right? Or does it keep happening as long as wxScrolledWindow scrolls through text?
So wxStaticText keeps thinking it is being redrawn when it is scrolled through?
Re: wxScrolledWindow is slow when scrolling through long text
Boundbox size should be calculated only once, because, when scrolling though the bound rect of the displaying part of wxStaticText changes,
the bound rect of wxStaticText should not change.
It's easy to test.
For the case that the whole wxStaticText is being re-rendered, better to debug with the wx source code.
Re: wxScrolledWindow is slow when scrolling through long text
How many wxStaticText are there?
It could be this unresolved problem: http://trac.wxwidgets.org/ticket/15766
It could be this unresolved problem: http://trac.wxwidgets.org/ticket/15766
Use the source, Luke!
Re: wxScrolledWindow is slow when scrolling through long text
About 10-20, some of them are short texts, some are long... It is also slow on Windows 7, so that ticket might not be related I guess.doublemax wrote: ↑Tue Oct 15, 2019 6:08 am How many wxStaticText are there?
It could be this unresolved problem: http://trac.wxwidgets.org/ticket/15766
Tried it, doesn't fix the problem.
Re: wxScrolledWindow is slow when scrolling through long text
I agree.MJaoune wrote: ↑Tue Oct 15, 2019 9:06 amAbout 10-20, some of them are short texts, some are long... It is also slow on Windows 7, so that ticket might not be related I guess.doublemax wrote: ↑Tue Oct 15, 2019 6:08 am How many wxStaticText are there?
It could be this unresolved problem: http://trac.wxwidgets.org/ticket/15766
Can you show the code?
Use the source, Luke!
Re: wxScrolledWindow is slow when scrolling through long text
Sorry, the code is long and somehow private.
What I want to know is, does everything inside wxScrolledWindow keep getting redrawn even while scrolling? Can I set the "refresh rate" of a wxWindow component?
The redrawing is done according to the monitor's refresh rate? For example if I am working on a 60Hz monitor, the components will get redrawn 60 times per second?
My final question, is "painting" just another term for "redraw"?
Re: wxScrolledWindow is slow when scrolling through long text
Can you extract just the code that fills the scrolledwindow with wxStaticTexts and fill them with dummy strings? It should be possible to reproduce the issue in a minimal sample. If not, maybe there are other parts in your application that are responsible.Sorry, the code is long and somehow private.
Whenever a new part of the window is scrolled into view, the OS will generate a paint event and the control must redraw itself. But normally no layout should happen, so this should all be fast. You can not limit the refresh rate, especially since you're using standard controls and no custom paint event handler.What I want to know is, does everything inside wxScrolledWindow keep getting redrawn even while scrolling? Can I set the "refresh rate" of a wxWindow component?
Use the source, Luke!
Re: wxScrolledWindow is slow when scrolling through long text
Another solution, draw the texts in EVT_PAINT handler directly.
It's not hard,faster than wxStaticText that works properly.
However, the probem should be investigated, it may be a bug of efficiency, even related to other controls that is not obvious in common use.
I'll dig it.
It's not hard,faster than wxStaticText that works properly.
However, the probem should be investigated, it may be a bug of efficiency, even related to other controls that is not obvious in common use.
I'll dig it.
Re: wxScrolledWindow is slow when scrolling through long text
modifed samples/minimal, not slowdoublemax wrote: ↑Tue Oct 15, 2019 12:10 pmI agree.MJaoune wrote: ↑Tue Oct 15, 2019 9:06 amAbout 10-20, some of them are short texts, some are long... It is also slow on Windows 7, so that ticket might not be related I guess.doublemax wrote: ↑Tue Oct 15, 2019 6:08 am How many wxStaticText are there?
It could be this unresolved problem: http://trac.wxwidgets.org/ticket/15766
Can you show the code?
param:
- wxStaticText count: 20
- rows per wxStaticText: 100
- cols per wxStaticText: 10
- Windows 10
- wxWidget dev almost latest
BTW, found a bug, if set cols per wxStaticText to 100 with other params unchanged, nothing displays.
Code: Select all
/////////////////////////////////////////////////////////////////////////////
// Name: minimal.cpp
// Purpose: Minimal wxWidgets sample
// Author: Julian Smart
// Modified by:
// Created: 04/01/98
// Copyright: (c) Julian Smart
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// ============================================================================
// declarations
// ============================================================================
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
// for all others, include the necessary headers (this file is usually all you
// need because it includes almost all "standard" wxWidgets headers)
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
// ----------------------------------------------------------------------------
// resources
// ----------------------------------------------------------------------------
// the application icon (under Windows it is in resources and even
// though we could still include the XPM here it would be unused)
#ifndef wxHAS_IMAGES_IN_RESOURCES
#include "../sample.xpm"
#endif
#include <sstream>
// ----------------------------------------------------------------------------
// private classes
// ----------------------------------------------------------------------------
// Define a new application type, each program should derive a class from wxApp
class MyApp : public wxApp
{
public:
// override base class virtuals
// ----------------------------
// this one is called on application startup and is a good place for the app
// initialization (doing it here and not in the ctor allows to have an error
// return: if OnInit() returns false, the application terminates)
virtual bool OnInit() wxOVERRIDE;
};
class MyPanel : public wxScrolledWindow
{
public:
MyPanel(wxWindow * parent,
wxWindowID winid = wxID_ANY,
const wxPoint & pos = wxDefaultPosition,
const wxSize & size = wxDefaultSize,
long style = wxScrolledWindowStyle,
const wxString & name = wxPanelNameStr) :
wxScrolledWindow(parent, winid, pos, size, style, name)
{
SetScrollRate(10, 10);
wxFlexGridSizer * pSizer_0 = new wxFlexGridSizer(2, 5, 5);
constexpr int nStaticTextCount = 20;
constexpr int nRowsInStaticText = 100;
constexpr int nColsInStaticText = 10;
for (int i = 0; i < nStaticTextCount; ++i)
{
wxStaticText * pST = new wxStaticText(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSIMPLE_BORDER);
{ // fill it
std::ostringstream oss;
for (int row = 0; row < nRowsInStaticText; ++row)
{
for (int col = 0; col < nColsInStaticText; ++col)
{
oss << "TestStaticText" << i << ' ';
}
oss << "\n";
}
pST->SetLabel(oss.str());
}
pSizer_0->Add(pST);
}
SetSizer(pSizer_0);
}
};
// Define a new frame type: this is going to be our main frame
class MyFrame : public wxFrame
{
public:
// ctor(s)
MyFrame(const wxString& title);
// event handlers (these functions should _not_ be virtual)
void OnQuit(wxCommandEvent& event);
void OnAbout(wxCommandEvent& event);
private:
// any class wishing to process wxWidgets events must use this macro
wxDECLARE_EVENT_TABLE();
};
// ----------------------------------------------------------------------------
// constants
// ----------------------------------------------------------------------------
// IDs for the controls and the menu commands
enum
{
// menu items
Minimal_Quit = wxID_EXIT,
// it is important for the id corresponding to the "About" command to have
// this standard value as otherwise it won't be handled properly under Mac
// (where it is special and put into the "Apple" menu)
Minimal_About = wxID_ABOUT
};
// ----------------------------------------------------------------------------
// event tables and other macros for wxWidgets
// ----------------------------------------------------------------------------
// the event tables connect the wxWidgets events with the functions (event
// handlers) which process them. It can be also done at run-time, but for the
// simple menu events like this the static method is much simpler.
wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU(Minimal_Quit, MyFrame::OnQuit)
EVT_MENU(Minimal_About, MyFrame::OnAbout)
wxEND_EVENT_TABLE()
// Create a new application object: this macro will allow wxWidgets to create
// the application object during program execution (it's better than using a
// static object for many reasons) and also implements the accessor function
// wxGetApp() which will return the reference of the right type (i.e. MyApp and
// not wxApp)
wxIMPLEMENT_APP(MyApp);
// ============================================================================
// implementation
// ============================================================================
// ----------------------------------------------------------------------------
// the application class
// ----------------------------------------------------------------------------
// 'Main program' equivalent: the program execution "starts" here
bool MyApp::OnInit()
{
// call the base class initialization method, currently it only parses a
// few common command-line options but it could be do more in the future
if ( !wxApp::OnInit() )
return false;
// create the main application window
MyFrame *frame = new MyFrame("Minimal wxWidgets App");
// and show it (the frames, unlike simple controls, are not shown when
// created initially)
frame->Maximize();
frame->Show(true);
// success: wxApp::OnRun() will be called which will enter the main message
// loop and the application will run. If we returned false here, the
// application would exit immediately.
return true;
}
// ----------------------------------------------------------------------------
// main frame
// ----------------------------------------------------------------------------
// frame constructor
MyFrame::MyFrame(const wxString & title)
: wxFrame(NULL, wxID_ANY, title)
{
// set the frame icon
SetIcon(wxICON(sample));
#if wxUSE_MENUS
// create a menu bar
wxMenu * fileMenu = new wxMenu;
// the "About" item should be in the help menu
wxMenu * helpMenu = new wxMenu;
helpMenu->Append(Minimal_About, "&About\tF1", "Show about dialog");
fileMenu->Append(Minimal_Quit, "E&xit\tAlt-X", "Quit this program");
// now append the freshly created menu to the menu bar...
wxMenuBar * menuBar = new wxMenuBar();
menuBar->Append(fileMenu, "&File");
menuBar->Append(helpMenu, "&Help");
// ... and attach this menu bar to the frame
SetMenuBar(menuBar);
#else // !wxUSE_MENUS
// If menus are not available add a button to access the about box
wxSizer * sizer = new wxBoxSizer(wxHORIZONTAL);
wxButton * aboutBtn = new wxButton(this, wxID_ANY, "About...");
aboutBtn->Bind(wxEVT_BUTTON, &MyFrame::OnAbout, this);
sizer->Add(aboutBtn, wxSizerFlags().Center());
SetSizer(sizer);
#endif // wxUSE_MENUS/!wxUSE_MENUS
#if wxUSE_STATUSBAR
// create a status bar just for fun (by default with 1 pane only)
CreateStatusBar(2);
SetStatusText("Welcome to wxWidgets!");
#endif // wxUSE_STATUSBAR
wxBoxSizer * pSizer_0 = new wxBoxSizer(wxVERTICAL);
MyPanel * pPanel = new MyPanel(this, wxID_ANY);
pSizer_0->Add(pPanel, 1, wxEXPAND);
SetSizer(pSizer_0);
}
// event handlers
void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
{
// true is to force the frame to close
Close(true);
}
void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
{
wxMessageBox(wxString::Format
(
"Welcome to %s!\n"
"\n"
"This is the minimal wxWidgets sample\n"
"running under %s.",
wxVERSION_STRING,
wxGetOsDescription()
),
"About wxWidgets minimal sample",
wxOK | wxICON_INFORMATION,
this);
}
Re: wxScrolledWindow is slow when scrolling through long text
Thanks Ronald for the demo code. I was too lazy to write it myself
I don't see any slowdown either.
@MJaoune:
How do you place the controls, do you also use sizers?
Do you have a scroll- or mouse event handler that could be responsible for the slow down?
I don't see any slowdown either.
@MJaoune:
How do you place the controls, do you also use sizers?
Do you have a scroll- or mouse event handler that could be responsible for the slow down?
Use the source, Luke!
Re: wxScrolledWindow is slow when scrolling through long text
There is the wxScrolledWindow which has a vertical wxBoxSizer, this sizer holds a random number of custom wxWindow widgets. Those custom wxWindow widgets each has a vertical wxBoxSizer which includes the texts ordered vertically. Due to wxWidgets' wxStaticText wrapping bugs for RTL languages, I need to add the wxStaticText in a custom wxWindow which has a wxBoxSizer inside to align it properly.
Does having many wxBoxSizers cause such an issue?
Why if I use event.Skip(false) in an EVT_PAINT, the wxWindow would still get painted normally? Why can't I stop the wxWindow from getting painted in an EVT_PAINT?
Re: wxScrolledWindow is slow when scrolling through long text
If the parent window paints on the child window, add style wxCLIP_CHILDREN to the parent.
But generally wxCLIP_CHILDREN is used to avoid flicker, so it has little chance to help.
Re: wxScrolledWindow is slow when scrolling through long text
Please create a minimal sample that mimics the same setup. These "custom wxWindow widgets" definitely sound suspicious.There is the wxScrolledWindow which has a vertical wxBoxSizer, this sizer holds a random number of custom wxWindow widgets. Those custom wxWindow widgets each has a vertical wxBoxSizer which includes the texts ordered vertically. Due to wxWidgets' wxStaticText wrapping bugs for RTL languages, I need to add the wxStaticText in a custom wxWindow which has a wxBoxSizer inside to align it properly.
Use the source, Luke!