Capítulo 4: Soy un artista... ¡No me coartes!

De doc.ubuntu-es
(Diferencias entre revisiones)
Saltar a: navegación, buscar
(categorizo)
Línea 163: Línea 163:
 
   (...)
 
   (...)
  
(...)
+
(...)
 
   ProgressBar = new wxGauge(ControlPanel, wxID_ANY, 100, wxPoint(3,3), wxSize(250,32));
 
   ProgressBar = new wxGauge(ControlPanel, wxID_ANY, 100, wxPoint(3,3), wxSize(250,32));
 
 
   MyCanvas * drawPanel = new MyCanvas(App,this, wxID_ANY, wxPoint(0,35), wxSize(640 , 480), wxTAB_TRAVERSAL | wxSUNKEN_BORDER);
 
   MyCanvas * drawPanel = new MyCanvas(App,this, wxID_ANY, wxPoint(0,35), wxSize(640 , 480), wxTAB_TRAVERSAL | wxSUNKEN_BORDER);
 
       m_drawPanel = drawPanel;
 
       m_drawPanel = drawPanel;
 
    
 
    
 
       //toolbar
 
       //toolbar
(...)
+
(...)
  
 
Con lo que creamos nuestra ventana en el punto wxPoint(0,35) con un tamaño de wxSize(640 , 480).
 
Con lo que creamos nuestra ventana en el punto wxPoint(0,35) con un tamaño de wxSize(640 , 480).
Línea 180: Línea 179:
 
== Organización de los elementos en la ventana (sizers): ==
 
== Organización de los elementos en la ventana (sizers): ==
  
Los sizers son una herramienta indispensable en la programación con wxWidgets, y se deben tener siempre presentes a la hora de programar. Nosotros concretamente vamos a usar wxBoxSizer, aunque existen algunas otras variantes que pueden ser muy interesantes. Pero para poder dar un poco más de juego, vamos primero a crear un montón de elementos basura.
+
Los sizers son una herramienta indispensable en la programación con wxWidgets, y se deben tener siempre presentes a la hora de programar. Nosotros concretamente vamos a usar wxBoxSizer, aunque existen algunas otras variantes que pueden ser muy interesantes. Pero para poder dar un poco más de juego, vamos primero a crear algunos elementos basura.
  
 
=== Creación de algunos elementos basura: ===
 
=== Creación de algunos elementos basura: ===
  
  (Construyendo...)
+
Propongamos poner, en la parte superior la scrollbar con un título (una etiqueta), y debajo, en la izquierda una columna de dos cuadros de texto, precedidos de una label, y en la derecha nuestro recien creado Canvas...
 +
 
 +
Asi que nos faltan dos etiquetas, y dos cuadros de texto, que por supuesto, para encontrar información sobre ellos, recurrimos a nuestra resabiada API, en la que si buscamos ''label'', podemos encontrar, entre otras cosas, la clase ''wxStaticText'', que es exactamente lo que buscabamos.
 +
 
 +
Así que vayamos a '''topframe.cpp''', y creemos nuestras dos nuevas etiquetas al final del constructor:
 +
 
 +
(...)
 +
    toolBar->AddTool(ID_START, wxBITMAP(start), wxNullBitmap, false, wxDefaultCoord, wxDefaultCoord, (wxObject *)NULL, _T("Start"), _T("Run the progress bar"));
 +
    toolBar->AddTool(ID_STOP, wxBITMAP(stop), wxNullBitmap, false, wxDefaultCoord, wxDefaultCoord, (wxObject *)NULL, _T("Start"), _T("Run the progress bar"));
 +
<b>wxStaticText * aLabel = new wxStaticText(<<DatePanel>>, wxID_ANY, _T("This is a wxGauge"),
 +
                              wxPoint(250, 60), wxDefaultSize,
 +
                              wxALIGN_CENTRE /*| wxST_NO_AUTORESIZE*/);
 +
    aLabel->SetForegroundColour( *wxBLACK );
 +
   
 +
wxStaticText * bLabel = new wxStaticText(<<DatePanel>>, wxID_ANY, _T("This is 2 wxTextCtrl"),
 +
                              wxPoint(250, 60), wxDefaultSize,
 +
                              wxALIGN_CENTRE /*| wxST_NO_AUTORESIZE*/);
 +
    bLabel->SetForegroundColour( *wxBLACK );</b>
 +
    m_running = false;
 +
(...)
 +
 
 +
Conviene destacar que les he dado un punto de creación a ambas (250, 60), pero ya vereis como eso no importa... Y es importante reseñar que en el ''window parent'', pongo '''<<DatePanel>>''', esto es porque como aun no hemos creado paneles para introducir estos elementos, para que si se nos olvida, nos devuelva un error.
 +
 
 +
Ahora volvemos a nuestro API, y buscamos ''text'', encontrando la clase ''wxTextCtrl'', si nos fijamos en su constructor, aparece algo muy interesante, el validador ''wxValidator'' (pinchamos sobre el link para conseguir información), que nos va a permitir restringir nuestro segundo cuadro de texto a solo números...
 +
 
 +
Asi que añadimos sendos cuadros de texto a nuestra interfaz, nuevamente al final de '''topframe.cpp''':
 +
 
 +
(...)
 +
    bLabel->SetForegroundColour( *wxBLACK );   
 +
<b>// validator that only accept number keys
 +
wxTextValidator OnlyNum = wxTextValidator(wxFILTER_NUMERIC);
 +
    // text box that accepts all
 +
wxTextCtrl * aText = new wxTextCtrl(<<DatePanel>>, wxID_ANY, _T("Any text"), wxDefaultPosition, wxSize(100, 20), wxTE_RIGHT);
 +
    // text box that only take numbers
 +
wxTextCtrl * bText = new wxTextCtrl(<<DatePanel>>, wxID_ANY, _T("1"), wxDefaultPosition, wxSize(100, 20), wxTE_RIGHT, OnlyNum);</b>
 +
    m_running = false;
 +
(...)
 +
 
 +
Y ya tenemos nuestros elementos, solo debemos colocarlos... Como ya hemos dicho, nuestros cuadros de texto irán en una columna diferente de nuestra barra de progreso, luego necesitan un panel distinto, así que creemos un panel para ellos:
 +
 
 +
(...)
 +
    // Panel
 +
wxPanel * ControlPanel = new wxPanel(this, wxID_ANY, wxPoint(0,0), wxSize(256, 32));
 +
<b>wxPanel * ControlPanel2 = new wxPanel(this, wxID_ANY, wxPoint(0,0), wxSize(256, 32));</b>
 +
ProgressBar = new wxGauge(ControlPanel, wxID_ANY, 100, wxPoint(3,3), wxSize(250,32));
 +
(...)
 +
 
 +
Y ahora ya si, ¡comenzemos con los wxSizers!, como siempre, lo primero la documentación, en la que buscamos ''sizer'', y que rapidamente nos muestra, entre otras cosas, ''wxBoxSizer''. Bien, si leeemos atentamente la documentación, veremos que estos sizers nos permiten colocar los elementos como si fueran cajas Cuyo alto y ancho debe coincidir entre ellas (con sus proporciones), y que nos permite apilarlas horizontal o verticalmente.
 +
 
 +
Bien, empezemos con nuestro panel para la scrollbar, en el que recordemos, primero va ''aLabel'', y debajo ''ProgressBar'', así que editamos ''aLabel'' para que este en el mismo panel que ''ProgressBar'':
 +
 
 +
(...)
 +
wxStaticText * aLabel = new wxStaticText(<b>ControlPanel</b>, wxID_ANY, _T("This is a wxGauge"),
 +
                              wxPoint(250, 60), wxDefaultSize,
 +
                              wxALIGN_CENTRE /*| wxST_NO_AUTORESIZE*/);
 +
    aLabel->SetForegroundColour( *wxBLACK );
 +
(...)
 +
 
 +
Y al final del constructor de ''topframe'' creamos un sizer para ellos:
 +
 
 +
(...)
 +
wxBoxSizer *cpSizer = new wxBoxSizer(wxVERTICAL);
 +
cpSizer->Add(aLabel, wxSizerFlags().Proportion(1).Expand().Border(wxALL,4));
 +
cpSizer->Add(ProgressBar, wxSizerFlags().Proportion(1).Expand().Border(wxALL,4));
 +
ControlPanel->SetSizer/*AndFit*/(cpSizer);
 +
(...)
 +
 
 +
Y repetimos para nuestra columna de cuadros de texto, los cuales editamos para que se incluyan en el ''ControlPanel2'':
 +
 
 +
(...)
 +
wxStaticText * bLabel = new wxStaticText(ControlPanel2, wxID_ANY, _T("This is 2 wxTextCtrl"),
 +
                              wxPoint(250, 60), wxDefaultSize,
 +
                              wxALIGN_CENTRE /*| wxST_NO_AUTORESIZE*/);
 +
    bLabel->SetForegroundColour( *wxBLACK );   
 +
// validator that only accept number keys
 +
wxTextValidator OnlyNum = wxTextValidator(wxFILTER_NUMERIC);
 +
    // text box that accepts all
 +
wxTextCtrl * aText = new wxTextCtrl(ControlPanel2, wxID_ANY, _T("Any text"), wxDefaultPosition, wxSize(100, 20), wxTE_RIGHT);
 +
    // text box that only take numbers
 +
wxTextCtrl * bText = new wxTextCtrl(ControlPanel2, wxID_ANY, _T("1"), wxDefaultPosition, wxSize(100, 20), wxTE_RIGHT, OnlyNum);
 +
(...)
 +
 
 +
Y creamos el sizer para este panel:
 +
 
 +
(...)
 +
wxBoxSizer *cpSizer2 = new wxBoxSizer(wxVERTICAL);
 +
cpSizer2->Add(aLabel, wxSizerFlags().Proportion(1).Expand().Border(wxALL,4));
 +
cpSizer2->Add(aText, wxSizerFlags().Proportion(1).Expand().Border(wxALL,4));
 +
cpSizer2->Add(bText, wxSizerFlags().Proportion(1).Expand().Border(wxALL,4));
 +
ControlPanel2->SetSizer/*AndFit*/(cpSizer2);
 +
(...)
  
 
{| border=1 class="wikitable" align=center
 
{| border=1 class="wikitable" align=center

Revisión de 12:55 21 sep 2008

Contenido

Introducción

En este capítulo no vamos a introducir nada nuevo, tan sólo vamos a trabajar con dos elementos un tanto singulares, ambos dedicados a desarrollarnos como artistas, pues el primero son los sizers, que nos ayudarán enormemente a organizar nuestras ventanas, y el segundo es wxWindow, que serán las ventanas donde pintaremos.

Parecerá chocante la forma de moverse de wxWidgets en cuanto a nomenclatura, pues las wxWindow serán para nosotros lo que para el resto de la humanidad son las Canvas, wxFrame, como ya vimos en capítulos anteriores, no serán pantallas (para pintar por ejemplo), sino ventanas de cabecera. El único que mantiene una cierta línea clásica es wxDialog, que aunque no llegaremos a usarlo, os podeis imaginar que su uso será del todo análogo.

Por tanto presentemos el plan de trabajo para este capítulo:

  • Plan de trabajo del capítulo 4:
    • Creación de una wxWindow:
      Crearemos nuestra primera ventana para pintar, dentro del propio TopFrame.
    • Organización de los elementos en la ventana (sizers):
      Usando los sizers colocaremos a nuestro gusto todos los elementos que tenemos.
      • Creación de algunos elementos basura:
        Crearemos unos cuantos cuadros de texto y labels para tener mas objetos que poder colocar.
      • Colocación de los elementos.
    • Pintado de la wxWindow:
      • Pintado directo (wxPaintDC).
      • Pintado sobre un bitmap (wxMemoryDC).
      • Pintado con contexto gráfico.

El último punto es realmente interesante, y una de las más modernas implementaciones de estas magníficas librerías. No obstante esta herramienta nos costará algunos disgustos cuando compilemos en Windows, lo primero porque en Windows tienes que añadir estas librerías manualmente, y lo segundo porque sufren de una alta inestabilidad.

Hecha esta breve introducción, procedamos a trabajar un poco...

Creación de una wxWindow:

Como siempre, con nuestra API bien cerquita, acudimos a ella y buscamos wxWindow, y nos informamos de todas las posibilidades que tiene (que son muchas). Para proceder con una wxWindow, al igual que con una wxFrame, y con un wxDialog, nos crearemos una clase heredada de wxWindow.

Ya introducimos esta idea cuando creamos nuestra wxFrame, y ya adelantabamos que cuando nos encontráramos con elementos complicados (una ventana, un dialogo, un canvas, una malla...) debíamos actuar de esta forma.

Bueno, ya que hemos alineado un poco nuestras ideas, recuperamos nuestro proyecto donde lo dejamos, y creamos dos archivos, llamados "mycanvas.cpp" y "mycanvas.h", y como siempre los limpiamos.

Y declaramos nuestra nueva clase, en "mycanvas.h":

 class MyCanvas : public wxWindow
 {
 public:
 	MyCanvas(SampleApp * AApp, wxWindow *parent, wxWindowID id, const wxPoint& 
       pos=wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = 0);
 
 	void drawSomething();
     wxMemoryDC dc;
     wxGraphicsContext *gc;
 
 protected: // event handlers (NO virtual)
 	void OnPaint(wxPaintEvent& event);
 	void OnMaximize(wxSizeEvent& event);
 private:
 	wxBitmap m_pixels;
 	SampleApp * App;
 
 	// any class wishing to process wxWidgets events must use this macro
 	DECLARE_EVENT_TABLE()
 };

En un acto de previsión, hemos ido añadiendo todo aquello que creemos que vamos a necesitar, tal vez sería buena idea que buscarais en el API todos los elementos que hemos añadido.

El siguiente punto es crear nuestra clase, en "mycanvas.cpp":

 #include <wx/wx.h>
 #include <wx/icon.h>
 #include <wx/font.h>
 #include <wx/numdlg.h>
 #include <wx/string.h>
 #include <wx/event.h>
 #include <wx/textctrl.h>
 #include <wx/wfstream.h>
 #include <wx/datstrm.h>
 #include <wx/txtstrm.h>
 #include <wx/access.h>
 #include <wx/window.h>
 #include <wx/treectrl.h>
 #include <wx/spinctrl.h>
 #include <wx/collpane.h>
 #include <wx/stdpaths.h>
 #include <wx/datetime.h>
 #include <wx/graphics.h>
 #include "main.h"
 #include "mycanvas.h"
 
 BEGIN_EVENT_TABLE(MyCanvas, wxWindow)
 	EVT_PAINT(MyCanvas::OnPaint)			//to can paint in window
 	EVT_SIZE(MyCanvas::OnMaximize)			//answer to size changes (p.ej. maximize events)	
 END_EVENT_TABLE()
 
 const int BMPW = 3000;	//auxvars
 const int BMPH = 2000;	//auxvars
 
 MyCanvas::MyCanvas(SampleApp * AApp, wxWindow *parent, wxWindowID id, const wxPoint& 
  pos /*= wxDefaultPosition*/, const wxSize& size /*= wxDefaultSize*/, long style /*= 0*/)
 :wxWindow(parent,id,pos,size,style),
 m_pixels(BMPW,BMPH,-1)
 {
     App = AApp;
 }
 
 /***************************************************************/
 /**************	OnMaximize	************************************/
 /************** answer to Size changes	************************/
 /************** Used to resize all elements	********************/
 /***************************************************************/
 void MyCanvas::OnMaximize(wxSizeEvent& WXUNUSED(event))
 {
 }
 
 /***************************************************************/
 /**************	OnPaint	****************************************/
 /************** answer to paint events *************************/
 /************** Prepares the window to paint it ****************/
 /***************************************************************/
 void MyCanvas::OnPaint(wxPaintEvent& WXUNUSED(event))
 {
 }
 
 /***************************************************************/
 /**************	drawSomething	********************************/
 /************** Paint the canvas	****************************/
 /***************************************************************/
 void MyCanvas::drawSomething()
 {
 }

Paremos un segundo a explicar a que viene cada cosa.

  1. De repente añado un montón de librerías, que ni siquiera nos son necesarias... Esas librerías son las típicas que casi seguro tarde o temprano terminareis por usar, es por eso que las añado.
  2. ¿Un sizeevent?... Como maximizamos nuestra TopFrame, es previsible que el tamaño de esta ventana cambie junto a el, On Maximize será el encargado de arreglar los posibles desperfectos.
  3. ¿Dos constantes?... Efectivamente, si miramos esas líneas de código:
 (...)
 const int BMPW = 3000;	//auxvars
 const int BMPH = 2000;	//auxvars
 
 MyCanvas::MyCanvas(SampleApp * AApp, wxWindow *parent, wxWindowID id, const wxPoint& 
  pos /*= wxDefaultPosition*/, const wxSize& size /*= wxDefaultSize*/, long style /*= 0*/)
 :wxWindow(parent,id,pos,size,style),
 m_pixels(BMPW,BMPH,-1)
 (...)

Lo que hacemos es crear un ancho y un alto, y montar con ellos nuestro bitmap (m_pixels). Ya veremos su utilidad, de momento nos bastará con saber que estos valores deben ser superiores a la resolución de pantalla, o por lo menos al tamaño de la ventana.

Respecto a las funciones, pues lo mas interesante es que tenemos un drawSomething(), que será al que llamaremos para pintar, y que será el que cree el evento para que OnPaint haga el trabajo. Esto es un primer esbozo, porque pronto veremos como no trabajaremos exactamente así.

Bueno, y ahora solo resta añadirla a topframe, así que empezamos por "topframe.h":

 (...)
 private:
 	SampleApp * App;
 	MyCanvas * m_drawPanel;
     DECLARE_EVENT_TABLE()
 };

Haber incluido esta clase en la cabecera de topframe, nos obliga a que siempre que se incluya "topframe.h", haya que incluir antes "mycnavas.h", y por otro lado, "mycanvas.h" requiere de "main.h" antes de ella. Así, en "main.cpp" debemos añadir lo siguiente:

 (...)
 #include "main.h"
 #include "mycanvas.h"
 #include "topframe.h"
 (...)

Y añadimos y construimos MyCanvas en "topframe.cpp":

 (...)
 #include "main.h"
 #include "mycanvas.h"
 #include "topframe.h"
 #include "header.h"
 (...)
(...)
 	ProgressBar = new wxGauge(ControlPanel, wxID_ANY, 100, wxPoint(3,3), wxSize(250,32));
 	MyCanvas * drawPanel = new MyCanvas(App,this, wxID_ANY, wxPoint(0,35), wxSize(640 , 480), wxTAB_TRAVERSAL | wxSUNKEN_BORDER);
     m_drawPanel = drawPanel;
 
     //toolbar
(...)

Con lo que creamos nuestra ventana en el punto wxPoint(0,35) con un tamaño de wxSize(640 , 480).

Compilamos y ejecutamos... ¡Y allí está! ¡nuestra ventana!

Pero el aspecto no es precisamente el deseado ¿verdad?, para arreglar esto vamos a recurrir a los sizers.

Organización de los elementos en la ventana (sizers):

Los sizers son una herramienta indispensable en la programación con wxWidgets, y se deben tener siempre presentes a la hora de programar. Nosotros concretamente vamos a usar wxBoxSizer, aunque existen algunas otras variantes que pueden ser muy interesantes. Pero para poder dar un poco más de juego, vamos primero a crear algunos elementos basura.

Creación de algunos elementos basura:

Propongamos poner, en la parte superior la scrollbar con un título (una etiqueta), y debajo, en la izquierda una columna de dos cuadros de texto, precedidos de una label, y en la derecha nuestro recien creado Canvas...

Asi que nos faltan dos etiquetas, y dos cuadros de texto, que por supuesto, para encontrar información sobre ellos, recurrimos a nuestra resabiada API, en la que si buscamos label, podemos encontrar, entre otras cosas, la clase wxStaticText, que es exactamente lo que buscabamos.

Así que vayamos a topframe.cpp, y creemos nuestras dos nuevas etiquetas al final del constructor:

(...)
   toolBar->AddTool(ID_START, wxBITMAP(start), wxNullBitmap, false, wxDefaultCoord, wxDefaultCoord, (wxObject *)NULL, _T("Start"), _T("Run the progress bar"));
   toolBar->AddTool(ID_STOP, wxBITMAP(stop), wxNullBitmap, false, wxDefaultCoord, wxDefaultCoord, (wxObject *)NULL, _T("Start"), _T("Run the progress bar"));
	wxStaticText * aLabel = new wxStaticText(<<DatePanel>>, wxID_ANY, _T("This is a wxGauge"),
                              wxPoint(250, 60), wxDefaultSize,
                              wxALIGN_CENTRE /*| wxST_NO_AUTORESIZE*/);
   aLabel->SetForegroundColour( *wxBLACK );
   
	wxStaticText * bLabel = new wxStaticText(<<DatePanel>>, wxID_ANY, _T("This is 2 wxTextCtrl"),
                              wxPoint(250, 60), wxDefaultSize,
                              wxALIGN_CENTRE /*| wxST_NO_AUTORESIZE*/);
   bLabel->SetForegroundColour( *wxBLACK );
   m_running = false;
(...)

Conviene destacar que les he dado un punto de creación a ambas (250, 60), pero ya vereis como eso no importa... Y es importante reseñar que en el window parent, pongo <<DatePanel>>, esto es porque como aun no hemos creado paneles para introducir estos elementos, para que si se nos olvida, nos devuelva un error.

Ahora volvemos a nuestro API, y buscamos text, encontrando la clase wxTextCtrl, si nos fijamos en su constructor, aparece algo muy interesante, el validador wxValidator (pinchamos sobre el link para conseguir información), que nos va a permitir restringir nuestro segundo cuadro de texto a solo números...

Asi que añadimos sendos cuadros de texto a nuestra interfaz, nuevamente al final de topframe.cpp:

(...)
   bLabel->SetForegroundColour( *wxBLACK );    
	// validator that only accept number keys
	wxTextValidator OnlyNum = wxTextValidator(wxFILTER_NUMERIC);
   // text box that accepts all
	wxTextCtrl * aText = new wxTextCtrl(<<DatePanel>>, wxID_ANY, _T("Any text"), wxDefaultPosition, wxSize(100, 20), wxTE_RIGHT);
   // text box that only take numbers
	wxTextCtrl * bText = new wxTextCtrl(<<DatePanel>>, wxID_ANY, _T("1"), wxDefaultPosition, wxSize(100, 20), wxTE_RIGHT, OnlyNum);
   m_running = false;
(...)

Y ya tenemos nuestros elementos, solo debemos colocarlos... Como ya hemos dicho, nuestros cuadros de texto irán en una columna diferente de nuestra barra de progreso, luego necesitan un panel distinto, así que creemos un panel para ellos:

(...)
   // Panel

wxPanel * ControlPanel = new wxPanel(this, wxID_ANY, wxPoint(0,0), wxSize(256, 32)); wxPanel * ControlPanel2 = new wxPanel(this, wxID_ANY, wxPoint(0,0), wxSize(256, 32)); ProgressBar = new wxGauge(ControlPanel, wxID_ANY, 100, wxPoint(3,3), wxSize(250,32));

(...)

Y ahora ya si, ¡comenzemos con los wxSizers!, como siempre, lo primero la documentación, en la que buscamos sizer, y que rapidamente nos muestra, entre otras cosas, wxBoxSizer. Bien, si leeemos atentamente la documentación, veremos que estos sizers nos permiten colocar los elementos como si fueran cajas Cuyo alto y ancho debe coincidir entre ellas (con sus proporciones), y que nos permite apilarlas horizontal o verticalmente.

Bien, empezemos con nuestro panel para la scrollbar, en el que recordemos, primero va aLabel, y debajo ProgressBar, así que editamos aLabel para que este en el mismo panel que ProgressBar:

(...)
	wxStaticText * aLabel = new wxStaticText(ControlPanel, wxID_ANY, _T("This is a wxGauge"),
                              wxPoint(250, 60), wxDefaultSize,
                              wxALIGN_CENTRE /*| wxST_NO_AUTORESIZE*/);
   aLabel->SetForegroundColour( *wxBLACK );
(...)

Y al final del constructor de topframe creamos un sizer para ellos:

(...)
	wxBoxSizer *cpSizer = new wxBoxSizer(wxVERTICAL);
	cpSizer->Add(aLabel, wxSizerFlags().Proportion(1).Expand().Border(wxALL,4));
	cpSizer->Add(ProgressBar, wxSizerFlags().Proportion(1).Expand().Border(wxALL,4));
	ControlPanel->SetSizer/*AndFit*/(cpSizer);
(...)

Y repetimos para nuestra columna de cuadros de texto, los cuales editamos para que se incluyan en el ControlPanel2:

(...)
	wxStaticText * bLabel = new wxStaticText(ControlPanel2, wxID_ANY, _T("This is 2 wxTextCtrl"),
                              wxPoint(250, 60), wxDefaultSize,
                              wxALIGN_CENTRE /*| wxST_NO_AUTORESIZE*/);
    bLabel->SetForegroundColour( *wxBLACK );    
	// validator that only accept number keys
	wxTextValidator OnlyNum = wxTextValidator(wxFILTER_NUMERIC); 
    // text box that accepts all
	wxTextCtrl * aText = new wxTextCtrl(ControlPanel2, wxID_ANY, _T("Any text"), wxDefaultPosition, wxSize(100, 20), wxTE_RIGHT);
    // text box that only take numbers
	wxTextCtrl * bText = new wxTextCtrl(ControlPanel2, wxID_ANY, _T("1"), wxDefaultPosition, wxSize(100, 20), wxTE_RIGHT, OnlyNum);
(...)

Y creamos el sizer para este panel:

(...)
	wxBoxSizer *cpSizer2 = new wxBoxSizer(wxVERTICAL);
	cpSizer2->Add(aLabel, wxSizerFlags().Proportion(1).Expand().Border(wxALL,4));
	cpSizer2->Add(aText, wxSizerFlags().Proportion(1).Expand().Border(wxALL,4));
	cpSizer2->Add(bText, wxSizerFlags().Proportion(1).Expand().Border(wxALL,4));
	ControlPanel2->SetSizer/*AndFit*/(cpSizer2);
(...)
Capítulo 3: ¡Qué aburrido! yo quiero interactuar Nuestra primera interfaz gráfica con CodeBlocks y wxWidgets Capítulo 5: El lado oscuro (compilando para Windows)
Herramientas personales