GTK3 / wxStaticText size
GTK3 / wxStaticText size
Hello,
my application uses a lot of wxStaticText with custom fonts. All works fine in Windows, macOS and GTK2. Unfortunately in GTK3 all the wxStaticText are to small (text doesn't fit) and the problem is immediately resolved after resizing the main window. It can also be fixed by calling Layout() on the window at a later point (calling Layout() directly at the end of the function that creates all the wxStaticText does not make a difference).
A lot of people seemed to have similar issues and there was a bug related to that in wxWidgets that was fixed in 2016. I first used wxWidgets 3.0.4 (the one that comes with Ubuntu 18.04 LTS) but I figures out that the fix was not ported back to the 3.0 series. So I downloaded/build/installed wxWidgets 3.1.2 and compiled against that version: No difference
Any advice how to resolve that issue? I tried calling Layout and Refresh each and everywhere but nothing changes. I'm using the default GTK 3.22 that comes with Ubuntu 18.04 LTS
Best regards
Stefan
my application uses a lot of wxStaticText with custom fonts. All works fine in Windows, macOS and GTK2. Unfortunately in GTK3 all the wxStaticText are to small (text doesn't fit) and the problem is immediately resolved after resizing the main window. It can also be fixed by calling Layout() on the window at a later point (calling Layout() directly at the end of the function that creates all the wxStaticText does not make a difference).
A lot of people seemed to have similar issues and there was a bug related to that in wxWidgets that was fixed in 2016. I first used wxWidgets 3.0.4 (the one that comes with Ubuntu 18.04 LTS) but I figures out that the fix was not ported back to the 3.0 series. So I downloaded/build/installed wxWidgets 3.1.2 and compiled against that version: No difference
Any advice how to resolve that issue? I tried calling Layout and Refresh each and everywhere but nothing changes. I'm using the default GTK 3.22 that comes with Ubuntu 18.04 LTS
Best regards
Stefan
Re: GTK3 / wxStaticText size
I did some further testing: The patch was later replaced by a much simpler solution according to the git logs.
I tried the last version with the original patch (9bb5d0435a4cce5bcb7b3956cb730f59c37ea5f6): problem is different: Sizes are still wrong, but text is not cut off, but painted over the borders.
Again, one simple resize of the window fixes everything. Any ideas?
I tried the last version with the original patch (9bb5d0435a4cce5bcb7b3956cb730f59c37ea5f6): problem is different: Sizes are still wrong, but text is not cut off, but painted over the borders.
Again, one simple resize of the window fixes everything. Any ideas?
Re: GTK3 / wxStaticText size
Hi,
As you say, this sounds very similar to https://trac.wxwidgets.org/ticket/17585. Did you test using the 'minimal' patch from comment 3?
Failing that, your idea of calling Layout() is correct; if a resize works, so should a Layout(). Make sure you call it on the correct 'top-level' window though: if the parent of your statictexts is e.g. a wxPanel, do pPanel->Layout(). If that fails too, possible workarounds are to call Layout() after a delay from e.g. CallAfter(); or try wxWindow::PostSizeEvent. However these are all things that I tried for https://trac.wxwidgets.org/ticket/17585 so they probably won't work for you either .
Finally, if you can reproduce the failing behaviour with that comment 3 patch built against git HEAD, you should report this on wxTrac.
Regards,
David
As you say, this sounds very similar to https://trac.wxwidgets.org/ticket/17585. Did you test using the 'minimal' patch from comment 3?
With which DE, and on X11 or Wayland?I'm using the default GTK 3.22 that comes with Ubuntu 18.04 LTS
It was, and would have been in wx3.0.4.but I figures out that the fix was not ported back to the 3.0 series.
wx3.1.2 was released last December. There have been lots of commits since, so you need to test using wx3.1.3, git HEAD.So I downloaded/build/installed wxWidgets 3.1.2
Failing that, your idea of calling Layout() is correct; if a resize works, so should a Layout(). Make sure you call it on the correct 'top-level' window though: if the parent of your statictexts is e.g. a wxPanel, do pPanel->Layout(). If that fails too, possible workarounds are to call Layout() after a delay from e.g. CallAfter(); or try wxWindow::PostSizeEvent. However these are all things that I tried for https://trac.wxwidgets.org/ticket/17585 so they probably won't work for you either .
Finally, if you can reproduce the failing behaviour with that comment 3 patch built against git HEAD, you should report this on wxTrac.
Regards,
David
Re: GTK3 / wxStaticText size
Cinnamon, X11With which DE, and on X11 or Wayland?
The original patch was replaced, 3.0.4 already has the later version, that's why I thought it was not in there.It was, and would have been in wx3.0.4.
CallAfter does the trick, this add the end of the function that creates the static texts does not work:
Code: Select all
panel->Layout();
Layout();
Code: Select all
CallAfter([&] { panel->Layout(); Layout(); });
Re: GTK3 / wxStaticText size
This is still completely broken for me on Ubuntu 20.04 with wxGTK 3.1.4 from
Edit: I tried this unofficial version because the one shipped with Ubuntu didn't work, either...
None of the suggested workarounds make a difference. Any wxStaticText with a non-default font size is wrong. I have tried to call Layout() on everything from the main wxFrame to Show(false/true) of the wxPanel containing the labels. Any other ideas?
Code: Select all
deb https://repos.codelite.org/wx3.1.4/ubuntu/ focal universe
Code: Select all
jpo@jpo-virtual-machine:~$ apt list --installed | fgrep wx
WARNING: apt does not have a stable CLI interface. Use with caution in scripts.
libwxbase3.1-0-unofficial3/stable,now 3.1.4-1.focal amd64 [installiert]
libwxbase3.1unofficial3-dev/stable,now 3.1.4-1.focal amd64 [installiert]
libwxgtk3.1-0-unofficial3/stable,now 3.1.4-1.focal amd64 [installiert]
libwxgtk3.1unofficial3-dev/stable,now 3.1.4-1.focal amd64 [installiert]
wx-common/stable,now 3.1.4-1.focal amd64 [installiert]
wx3.1-headers/stable,now 3.1.4-1.focal amd64 [installiert]
wx3.1gtk2-headers/stable,now 3.1.4-1.focal amd64 [installiert]
Re: GTK3 / wxStaticText size
I have created a small test case that mimics what my program does:
Code: Select all
#include <wx/wx.h>
#include <wx/simplebook.h>
class MyApp : public wxApp
{
public:
virtual bool OnInit();
};
class MyFrame : public wxFrame
{
protected:
wxSimplebook* m_simplebook1;
wxPanel* m_panel1;
wxStaticText* m_staticText1;
wxPanel* m_panel2;
wxStaticText* m_staticText2;
wxButton* m_button1;
int m_book_page;
// Virtual event handlers, overide them in your derived class
virtual void OnButtonClick(wxCommandEvent& event) {
m_book_page = (m_book_page == 0) ? 1 : 0;
m_simplebook1->ChangeSelection(m_book_page);
}
public:
MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size);
};
wxIMPLEMENT_APP(MyApp);
bool MyApp::OnInit()
{
MyFrame* frame = new MyFrame("Hello World", wxPoint(50, 50), wxSize(450, 340));
frame->Show(true);
return true;
}
MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
: wxFrame(NULL, wxID_ANY, title, pos, size)
{
this->SetSizeHints(wxDefaultSize, wxDefaultSize);
wxBoxSizer* bSizer1;
bSizer1 = new wxBoxSizer(wxVERTICAL);
m_simplebook1 = new wxSimplebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0);
m_panel1 = new wxPanel(m_simplebook1, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
wxBoxSizer* bSizer2;
bSizer2 = new wxBoxSizer(wxVERTICAL);
m_staticText1 = new wxStaticText(m_panel1, wxID_ANY, wxT("Panel 1"), wxDefaultPosition, wxDefaultSize, 0);
m_staticText1->Wrap(-1);
m_staticText1->SetFont(wxFont(15, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString));
bSizer2->Add(m_staticText1, 0, wxALL, 5);
m_panel1->SetSizer(bSizer2);
m_panel1->Layout();
bSizer2->Fit(m_panel1);
m_simplebook1->AddPage(m_panel1, wxT("a page"), false);
m_panel2 = new wxPanel(m_simplebook1, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
wxBoxSizer* bSizer3;
bSizer3 = new wxBoxSizer(wxVERTICAL);
m_staticText2 = new wxStaticText(m_panel2, wxID_ANY, wxT("Panel 2"), wxDefaultPosition, wxDefaultSize, 0);
m_staticText2->Wrap(-1);
m_staticText2->SetFont(wxFont(20, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString));
bSizer3->Add(m_staticText2, 0, wxALL, 5);
m_panel2->SetSizer(bSizer3);
m_panel2->Layout();
bSizer3->Fit(m_panel2);
m_simplebook1->AddPage(m_panel2, wxT("a page"), false);
bSizer1->Add(m_simplebook1, 1, wxEXPAND | wxALL, 5);
m_button1 = new wxButton(this, wxID_ANY, wxT("Switch"), wxDefaultPosition, wxDefaultSize, 0);
bSizer1->Add(m_button1, 0, wxALL, 5);
this->SetSizer(bSizer1);
this->Layout();
this->Centre(wxBOTH);
// Connect Events
m_button1->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(MyFrame::OnButtonClick), NULL, this);
m_book_page = m_simplebook1->GetSelection();
}
Re: GTK3 / wxStaticText size
How is that a "small" test case? Small maybe, but not minimal. Is the wxSimpleBook relevant for the problem? Probably not. What about the buttons? I would suspect that a single wxPanel with 3 wxStaticTexts should be sufficient to show the issue.
Use the source, Luke!
Re: GTK3 / wxStaticText size
I think the wxSimpleBook is relevant. The first panel shows the text correctly after a switch forward/backward. The second panel (e.g. the one that is invisible when the window is created) never sizes the text properly.
The code is a little bit verbose because it comes from wxFormBuilder...
Re: GTK3 / wxStaticText size
It's horrible indeed. Please remove *all* Fit() and Layout() calls. What happens on the "broken" page when you resize the frame manually?The code is a little bit verbose because it comes from wxFormBuilder...
Use the source, Luke!
Re: GTK3 / wxStaticText size
I did as you asked:
Code: Select all
#include <wx/wx.h>
#include <wx/simplebook.h>
class MyApp : public wxApp
{
public:
virtual bool OnInit();
};
class MyFrame : public wxFrame
{
protected:
wxSimplebook* m_simplebook1;
wxPanel* m_panel1;
wxStaticText* m_staticText1;
wxPanel* m_panel2;
wxStaticText* m_staticText2;
wxButton* m_button1;
int m_book_page;
// Virtual event handlers, overide them in your derived class
virtual void OnButtonClick(wxCommandEvent& event) {
m_book_page = (m_book_page == 0) ? 1 : 0;
m_simplebook1->ChangeSelection(m_book_page);
}
public:
MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size);
};
wxIMPLEMENT_APP(MyApp);
bool MyApp::OnInit()
{
MyFrame* frame = new MyFrame("Hello World", wxPoint(50, 50), wxSize(450, 340));
frame->Show(true);
return true;
}
MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
: wxFrame(NULL, wxID_ANY, title, pos, size)
{
this->SetSizeHints(wxDefaultSize, wxDefaultSize);
wxBoxSizer* bSizer1;
bSizer1 = new wxBoxSizer(wxVERTICAL);
m_simplebook1 = new wxSimplebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0);
m_panel1 = new wxPanel(m_simplebook1, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
wxBoxSizer* bSizer2;
bSizer2 = new wxBoxSizer(wxVERTICAL);
m_staticText1 = new wxStaticText(m_panel1, wxID_ANY, wxT("Panel 1"), wxDefaultPosition, wxDefaultSize, 0);
m_staticText1->Wrap(-1);
m_staticText1->SetFont(wxFont(15, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString));
bSizer2->Add(m_staticText1, 0, wxALL, 5);
m_panel1->SetSizer(bSizer2);
m_simplebook1->AddPage(m_panel1, wxT("a page"), false);
m_panel2 = new wxPanel(m_simplebook1, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
wxBoxSizer* bSizer3;
bSizer3 = new wxBoxSizer(wxVERTICAL);
m_staticText2 = new wxStaticText(m_panel2, wxID_ANY, wxT("Panel 2"), wxDefaultPosition, wxDefaultSize, 0);
m_staticText2->Wrap(-1);
m_staticText2->SetFont(wxFont(30, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString));
bSizer3->Add(m_staticText2, 0, wxALL, 5);
m_panel2->SetSizer(bSizer3);
m_simplebook1->AddPage(m_panel2, wxT("a page"), false);
bSizer1->Add(m_simplebook1, 1, wxEXPAND | wxALL, 5);
m_button1 = new wxButton(this, wxID_ANY, wxT("Switch"), wxDefaultPosition, wxDefaultSize, 0);
bSizer1->Add(m_button1, 0, wxALL, 5);
this->SetSizer(bSizer1);
this->Centre(wxBOTH);
// Connect Events
m_button1->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(MyFrame::OnButtonClick), NULL, this);
m_book_page = m_simplebook1->GetSelection();
}
Everything is fine under Win10, btw.
Re: GTK3 / wxStaticText size
I usually don't work under Linux, but i have a faint memory that window creation under GTK is somehow delayed compared to window creation under Windows. I assume the Layout is calculated before the wxStaticText is aware of its new font size. I thought there was an open ticket about this on http://trac.wxwidgets.org/ but i couldn't find it.
I found a workaround by invalidating the sizes of all windows on page switch. Unfortunately this leads to flickering as the re-layout happens when the page is already visible. Maybe you can find a way to improve on that, i'll post my current test code below.
Please check trac again for open tickets regarding this issue, and if you can't find one, please open a new one.
I found a workaround by invalidating the sizes of all windows on page switch. Unfortunately this leads to flickering as the re-layout happens when the page is already visible. Maybe you can find a way to improve on that, i'll post my current test code below.
Please check trac again for open tickets regarding this issue, and if you can't find one, please open a new one.
Code: Select all
#include <wx/wx.h>
#include <wx/simplebook.h>
static void InvalidateBestSizeRecursively( wxWindow *win )
{
if( !win ) return;
win->InvalidateBestSize();
for ( wxWindowList::compatibility_iterator node = win->GetChildren().GetFirst();
node;
node = node->GetNext() )
{
wxWindow *child = node->GetData();
InvalidateBestSizeRecursively( child );
}
}
class MyApp : public wxApp
{
public:
virtual bool OnInit();
};
class MyFrame : public wxFrame
{
protected:
wxSimplebook* m_simplebook1;
wxPanel* m_panel1;
wxSizer *page1Sizer;
wxStaticText* m_staticText1;
wxPanel* m_panel2;
wxSizer *page2Sizer;
wxStaticText* m_staticText2;
wxButton* m_button1;
int m_book_page;
// Virtual event handlers, overide them in your derived class
virtual void OnButtonClick(wxCommandEvent& event) {
m_book_page = (m_book_page == 0) ? 1 : 0;
m_simplebook1->ChangeSelection(m_book_page);
CallAfter( [this] {
InvalidateBestSizeRecursively( m_simplebook1->GetCurrentPage() );
//Layout(); // not sufficient
//m_simplebook1->Layout(); // not sufficient
wxSizer *pageSizer = m_simplebook1->GetCurrentPage()->GetSizer();
if (pageSizer) pageSizer->Layout();
});
}
public:
MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size);
};
wxIMPLEMENT_APP(MyApp);
bool MyApp::OnInit()
{
MyFrame* frame = new MyFrame("Hello World", wxPoint(50, 50), wxSize(450, 340));
frame->Show(true);
return true;
}
MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
: wxFrame(NULL, wxID_ANY, title, pos, size)
{
wxFont font15(15, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
wxFont font20(20, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);
m_simplebook1 = new wxSimplebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0);
// page 1
m_panel1 = new wxPanel(m_simplebook1, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
page1Sizer = new wxBoxSizer(wxVERTICAL);
m_staticText1 = new wxStaticText(m_panel1, wxID_ANY, wxT("Panel 1"), wxDefaultPosition, wxDefaultSize, 0);
m_staticText1->SetFont(font15);
m_staticText1->SetBackgroundColour(*wxRED);
page1Sizer->Add(m_staticText1, 0, wxALL, 5);
wxStaticText *st = new wxStaticText(m_panel1, wxID_ANY, wxT("Panel 1"), wxDefaultPosition, wxDefaultSize, 0);
st->SetFont(font15);
st->SetBackgroundColour(*wxGREEN);
page1Sizer->Add(st, 0, wxALL, 5);
m_panel1->SetSizer(page1Sizer);
m_simplebook1->AddPage(m_panel1, wxT("a page"), false);
// page 2
m_panel2 = new wxPanel(m_simplebook1, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
page2Sizer = new wxBoxSizer(wxVERTICAL);
m_staticText2 = new wxStaticText(m_panel2, wxID_ANY, wxT("Panel 2"), wxDefaultPosition, wxDefaultSize, 0);
m_staticText2->SetFont(font20);
m_staticText2->SetBackgroundColour(*wxRED);
page2Sizer->Add(m_staticText2, 0, wxALL, 5);
st = new wxStaticText(m_panel2, wxID_ANY, wxT("Panel 2"), wxDefaultPosition, wxDefaultSize, 0);
st->SetFont(font20);
st->SetBackgroundColour(*wxGREEN);
page2Sizer->Add(st, 0, wxALL, 5);
m_panel2->SetSizer(page2Sizer);
m_simplebook1->AddPage(m_panel2, wxT("a page"), false);
mainSizer->Add(m_simplebook1, 1, wxEXPAND | wxALL, 5);
m_button1 = new wxButton(this, wxID_ANY, wxT("Switch"), wxDefaultPosition, wxDefaultSize, 0);
mainSizer->Add(m_button1, 0, wxALL, 5);
SetSizer(mainSizer);
// Connect Events
m_button1->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(MyFrame::OnButtonClick), NULL, this);
}
Use the source, Luke!
Re: GTK3 / wxStaticText size
Hi,
Regards,
David
That's right. One workaround that I've used is to Bind() wxEVT_IDLE in the top-level window ctor. The event-handler then checks the frame size; when that's sane (e.g. >20,20) it does whatever is appropriate, then Unbind()s itself.I have a faint memory that window creation under GTK is somehow delayed compared to window creation under Windows.
Regards,
David
Re: GTK3 / wxStaticText size
Thanks for taking the time to look into this. The test application is almost right (the first page is broken until a switch or manual size change). My much larger real application reacts strangely: The pages are broken the first time I activate them, but are perfectly fine the second time...doublemax wrote: ↑Thu Apr 15, 2021 4:19 pm I usually don't work under Linux, but i have a faint memory that window creation under GTK is somehow delayed compared to window creation under Windows. I assume the Layout is calculated before the wxStaticText is aware of its new font size. I thought there was an open ticket about this on http://trac.wxwidgets.org/ but i couldn't find it.
I found a workaround by invalidating the sizes of all windows on page switch. Unfortunately this leads to flickering as the re-layout happens when the page is already visible. Maybe you can find a way to improve on that, i'll post my current test code below.
Please check trac again for open tickets regarding this issue, and if you can't find one, please open a new one.
Re: GTK3 / wxStaticText size
David,DavidHart wrote: ↑Thu Apr 15, 2021 5:08 pm Hi,
That's right. One workaround that I've used is to Bind() wxEVT_IDLE in the top-level window ctor. The event-handler then checks the frame size; when that's sane (e.g. >20,20) it does whatever is appropriate, then Unbind()s itself.I have a faint memory that window creation under GTK is somehow delayed compared to window creation under Windows.
Regards,
David
I found this bug report: http://trac.wxwidgets.org/ticket/16088
It was closed 3 days ago and the fix should be in 3.1.5. Are you planning to provide 3.1.5 packages in your repository?
Re: GTK3 / wxStaticText size
Well spotted!I found this bug report: http://trac.wxwidgets.org/ticket/16088
I've been busy with other things, so I've not started yet; but yes, it will happen.Are you planning to provide 3.1.5 packages in your repository?