Reputation: 6372
I am having trouble with getting a wxStaticText
label to wrap dynamically in a dialog, using wxWidgets 3.0.2. I followed ideas for other questions like this one, bit I still have strange effects.
I am using the Wrap(int)
function on the text, in a callback on the wxEVT_SIZE
event, but it seems to have an unexpected effect on the text, and also seems to only "ratchet" down the size, and won't wrap again as the window expands.
The main part of the binding is:
CTOR(...) {
....
m_text->Bind(wxEVT_SIZE, &DIALOG_WRAPTEXT::onResize, this);
}
void CLASS::onResize( wxSizeEvent& event )
{
m_text->Wrap( event.GetSize().GetWidth() );
event.Skip();
}
The result looks OK when the dialog is first shown, but when you resize narrower and back up, you get this result:
A minimum reproducible example is:
#include <wx/wxprec.h>
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
class DIALOG_WRAPTEXT: public wxDialog
{
public:
DIALOG_WRAPTEXT( wxWindow* parent,
const wxString& aTitle, const wxSize aSize );
private:
void onResize( wxSizeEvent& evt );
wxBoxSizer* m_itemBoxSizer;
wxStaticText* m_text;
};
DIALOG_WRAPTEXT::DIALOG_WRAPTEXT(
wxWindow* parent, const wxString& aTitle, const wxSize aSize ):
wxDialog( parent, wxID_ANY, aTitle,
wxPoint( -1, -1 ), aSize,
wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
{
m_itemBoxSizer = new wxBoxSizer( wxVERTICAL );
SetSizer( m_itemBoxSizer );
wxString msg("Lots and lots of text to wrap hopefully. "
"Lots and lots of text to wrap hopefully. "
"Lots and lots of text to wrap hopefully. "
"Lots and lots of text to wrap hopefully. "
"Lots and lots of text to wrap hopefully. "
"Lots and lots of text to wrap hopefully. "
);
m_text = new wxStaticText( this, wxID_ANY, msg );
// wxEXPAND makes no difference
m_itemBoxSizer->Add( m_text, 1, wxALIGN_TOP | wxALL | wxEXPAND, 5 );
// Bind to m_text or this, same effect
m_text->Bind(wxEVT_SIZE, &DIALOG_WRAPTEXT::onResize, this);
}
void DIALOG_WRAPTEXT::onResize( wxSizeEvent& event )
{
//m_text->Freeze(); // makes no difference
const auto w = event.GetSize().GetWidth();
wxLogDebug( "Wrap to width: %d",w ); // produces sensible values
m_text->Wrap( w );
//m_text->Thaw();
event.Skip();
}
class MyApp: public wxApp
{
public:
bool OnInit() override
{
auto d = new DIALOG_WRAPTEXT(NULL, "Dialog title", wxSize(200, 200));
d->ShowModal();
d->Destroy();
}
};
wxIMPLEMENT_APP(MyApp);
What is the right way to dynamically wrap static text in a dialog?
Upvotes: 1
Views: 3569
Reputation: 27
Encountered similar problem. I have to store the unwrapped message somewhere, when wxStaticText is resized, set the message and call wrap. otherwise the line may not be wrapped nicely.
void MyFrame::onResize(wxSizeEvent& evt)
{
const auto w = evt.GetSize().GetWidth();
m_text->SetLabel(m_msg); // unwrapped message
m_text->Wrap(w);
evt.Skip();
}
Upvotes: 1
Reputation: 1652
Without any wrap(), the wxStaticText displays the text correctly (wrapping at word boundaries) using the follwing minimal code on windows with wx 3.0.2. I can resize the dialog (shrink, grow) and the wxStaticText will update itself correctly. This is not enough for your use case? Are you sure you need to use the wrap function?
#include <wx/wxprec.h>
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
class DIALOG_WRAPTEXT : public wxDialog
{
public:
DIALOG_WRAPTEXT(wxWindow* parent,
const wxString& aTitle, const wxSize aSize);
private:
void onResize(wxSizeEvent& evt);
wxBoxSizer* m_itemBoxSizer;
wxStaticText* m_text;
};
DIALOG_WRAPTEXT::DIALOG_WRAPTEXT(
wxWindow* parent, const wxString& aTitle, const wxSize aSize) :
wxDialog(parent, wxID_ANY, aTitle,
wxPoint(-1, -1), aSize,
wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
{
m_itemBoxSizer = new wxBoxSizer(wxVERTICAL);
SetSizer(m_itemBoxSizer);
wxString msg("Lots and lots of text to wrap hopefully. "
"Lots and lots of text to wrap hopefully. "
"Lots and lots of text to wrap hopefully. "
"Lots and lots of text to wrap hopefully. "
"Lots and lots of text to wrap hopefully. "
"Lots and lots of text to wrap hopefully. "
);
m_text = new wxStaticText(this, wxID_ANY, msg);
// wxEXPAND makes no difference
m_itemBoxSizer->Add(m_text, 1, wxALIGN_TOP | wxALL | wxEXPAND, 5);
// Act on dialog resize
Bind(wxEVT_SIZE, &DIALOG_WRAPTEXT::onResize, this);
}
void DIALOG_WRAPTEXT::onResize(wxSizeEvent& event)
{
// layout everything in the dialog
Layout();
event.Skip();
}
class MyApp : public wxApp
{
public:
bool OnInit() override
{
auto d = new DIALOG_WRAPTEXT(NULL, "Dialog title", wxSize(200, 200));
d->ShowModal();
d->Destroy();
return true;
}
};
wxIMPLEMENT_APP(MyApp);
Upvotes: 2