GTK3 / wxStaticText size

Do you have a typical platform dependent issue you're battling with ? Ask it here. Make sure you mention your platform, compiler, and wxWidgets version.
stefan__o
Knows some wx things
Knows some wx things
Posts: 32
Joined: Mon Aug 04, 2014 12:55 am

GTK3 / wxStaticText size

Post by stefan__o »

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
stefan__o
Knows some wx things
Knows some wx things
Posts: 32
Joined: Mon Aug 04, 2014 12:55 am

Re: GTK3 / wxStaticText size

Post by stefan__o »

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?
DavidHart
Site Admin
Site Admin
Posts: 4252
Joined: Thu Jan 12, 2006 6:23 pm
Location: IoW, UK

Re: GTK3 / wxStaticText size

Post by DavidHart »

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?
I'm using the default GTK 3.22 that comes with Ubuntu 18.04 LTS
With which DE, and on X11 or Wayland?
but I figures out that the fix was not ported back to the 3.0 series.
It was, and would have been in wx3.0.4.
So I downloaded/build/installed wxWidgets 3.1.2
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.

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
stefan__o
Knows some wx things
Knows some wx things
Posts: 32
Joined: Mon Aug 04, 2014 12:55 am

Re: GTK3 / wxStaticText size

Post by stefan__o »

With which DE, and on X11 or Wayland?
Cinnamon, X11
It was, and would have been in wx3.0.4.
The original patch was replaced, 3.0.4 already has the later version, that's why I thought it was not in there.

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();
But this does work:

Code: Select all

CallAfter([&] { panel->Layout(); Layout(); });
jpo234
Experienced Solver
Experienced Solver
Posts: 70
Joined: Tue Feb 25, 2020 11:34 am

Re: GTK3 / wxStaticText size

Post by jpo234 »

This is still completely broken for me on Ubuntu 20.04 with wxGTK 3.1.4 from

Code: Select all

deb https://repos.codelite.org/wx3.1.4/ubuntu/ focal universe
Edit: I tried this unofficial version because the one shipped with Ubuntu didn't work, either...

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]
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?
jpo234
Experienced Solver
Experienced Solver
Posts: 70
Joined: Tue Feb 25, 2020 11:34 am

Re: GTK3 / wxStaticText size

Post by jpo234 »

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();
}
User avatar
doublemax
Moderator
Moderator
Posts: 19103
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: GTK3 / wxStaticText size

Post by doublemax »

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!
jpo234
Experienced Solver
Experienced Solver
Posts: 70
Joined: Tue Feb 25, 2020 11:34 am

Re: GTK3 / wxStaticText size

Post by jpo234 »

doublemax wrote: Thu Apr 15, 2021 2:50 pm 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.
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...
User avatar
doublemax
Moderator
Moderator
Posts: 19103
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: GTK3 / wxStaticText size

Post by doublemax »

The code is a little bit verbose because it comes from wxFormBuilder...
It's horrible indeed. Please remove *all* Fit() and Layout() calls. What happens on the "broken" page when you resize the frame manually?
Use the source, Luke!
jpo234
Experienced Solver
Experienced Solver
Posts: 70
Joined: Tue Feb 25, 2020 11:34 am

Re: GTK3 / wxStaticText size

Post by jpo234 »

doublemax wrote: Thu Apr 15, 2021 2:57 pm
The code is a little bit verbose because it comes from wxFormBuilder...
It's horrible indeed. Please remove *all* Fit() and Layout() calls. What happens on the "broken" page when you resize the frame manually?
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();
}
Resizing the window doesn't change anything. The "good" page is broken the first time its shown, but recovers after a switch or after manually resizing the window. The "bad", second page never recovers.

Everything is fine under Win10, btw.
User avatar
doublemax
Moderator
Moderator
Posts: 19103
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: GTK3 / wxStaticText size

Post by doublemax »

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.

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!
DavidHart
Site Admin
Site Admin
Posts: 4252
Joined: Thu Jan 12, 2006 6:23 pm
Location: IoW, UK

Re: GTK3 / wxStaticText size

Post by DavidHart »

Hi,
I have a faint memory that window creation under GTK is somehow delayed compared to window creation under Windows.
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.

Regards,

David
jpo234
Experienced Solver
Experienced Solver
Posts: 70
Joined: Tue Feb 25, 2020 11:34 am

Re: GTK3 / wxStaticText size

Post by jpo234 »

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.
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... #-o
jpo234
Experienced Solver
Experienced Solver
Posts: 70
Joined: Tue Feb 25, 2020 11:34 am

Re: GTK3 / wxStaticText size

Post by jpo234 »

DavidHart wrote: Thu Apr 15, 2021 5:08 pm Hi,
I have a faint memory that window creation under GTK is somehow delayed compared to window creation under Windows.
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.

Regards,

David
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?
DavidHart
Site Admin
Site Admin
Posts: 4252
Joined: Thu Jan 12, 2006 6:23 pm
Location: IoW, UK

Re: GTK3 / wxStaticText size

Post by DavidHart »

Well spotted!
Are you planning to provide 3.1.5 packages in your repository?
I've been busy with other things, so I've not started yet; but yes, it will happen.
Post Reply