Está en la página 1de 120

Annlmo

CcLubre de 2010 (versln de dlsLrlbucln llbre)


A8LnuA CL4 uLSuL PC? MlSMC


!


"



"#$%&'" ()* '%+'% ,-. /0+/-

Este pietenue sei el piimei libio en espaol uel mejoi Fiamewoik ue uesaiiollo
multiplatafoima ue touos los tiempos, y que caua uia nos biinua nuevas posibiliuaues. Es una
lstima peio a uia ue hoy no hay ninguna tiauuccion, ni libio ueuicauo seiiamente a Qt 4 en
nuestio iuioma, poi lo que me uispuse a cambiai esta situacion.
El enfoque que vamos a usai es poi supuesto uesue C++, y poi lo tanto es impoitante
poseei ue antemano unos conocimientos pievios ue este lenguaje. El nivel necesaiio paia
compienuei este libio lo completa peifectamente el libio ue !"#$%& ()$*+,)$+- , "El lenguaje ue
piogiamacion C++" publicauo en espaol poi Auuison-Wesley en 2uu1 (ISBN: 84-7829-u46-X).
C++ es un lenguaje que ha evolucionauo mucho uesue que fue cieauo en 198S poi !"#$%&
()$*+,)$+- en los laboiatoiios AT&T, uonue tambin nacio su pieuecesoi C, unos uiez aos antes
(1972), ue la mano ue Bennis Ritchie. El lenguaje C, que habia naciuo paia sustituii al
ensamblauoi en el uesaiiollo ue sistemas opeiativos, y asi pouei poitailos ms fcilmente a
otias platafoimas fisicas, y asi se ieesciibio completamente 0NIX ue los Laboiatoiios Bell cieauo
en 1969. C++ suigio como una necesiuau ue aauii nuevos paiauigmas a los ya incoipoiauos poi
C, peio sin peiuei la potencia uel mismo, al pouei acceuei al haiuwaie ue maneia sencilla. Asi
C++ aauio el lenguaje oiientauo a objetos, poi ello se le conoce como C con clases. Sin embaigo
cuanuo alguien que viene ue C, comienza a estuuiai C++, uebe ue evitai pensai que es una
extension uel lenguaje C lo que est estuuianuo, ya que C++ es mucho ms que eso. C++, se ha
uesvinculauo ue muchas picticas habituales en C que eian motivo ue mltiples fallos en la
piogiamacion, como el casting incontiolauo, el uso ue la memoiia, ue los punteios, el paso ue
paimetios poi iefeiencia, incoipoiacion ue elementos muy tiles como las Colecciones o
Conteneuoies y la cieacion ue una libieiia ue incalculable valoi paia el piogiamauoi en C++, las
STL (Stanuaiu Template Libiaiies). Aunque 0NIX y Linux fue cieauo uesue C, otios opeiativos
como Winuows, nacieion ue C++. Los sistemas con entoino gifico, eian mucho ms sencillos ue
uesaiiollai usanuo el paiauigma uel lenguaje oiientauo a objetos, que la meia piogiamacion
estiuctuiaua ue C.
En 1991, uos piogiamauoies noiuegos (Eiiik Eng y Baavaiu Noiu ue Quasai
Technologies, ms taiue Tiolltech) cieaion un Fiamewoik en C++ que peimitieia usai el mismo
couigo en el uesaiiollo ue una u0I (inteifaz gifica) tanto paia Winuows como paia 0NIXX11.
Inicialmente eia couigo abieito, peio la licencia no eia libie. Entie 199S y 1998 se uesaiiollo con
este Fiamewoik un esciitoiio paia uN0Linux que tuvo mucho xito, llamauo KBE que hoy sigue
sienuo uno ue los esciitoiios ms usauos ue Linux. uN0 miiaba con iecelo que el esciitoiio ms
usauo en Linux no fueia libie, asi que hubo una ieunion entie los uesaiiollauoies ue KBE y
Tiolltech, paia aseguiai el futuio ue Qt en una libeiacion bajo licencia BSB. Entie los aos 2uuu y
2uuS se piouujo la libeiacion bajo licencia uPL ue las veisiones ue Qt paia Winuows, Linux y
Nacintosh. En }unio ue 2uu8, Nokia se aseguio el uesaiiollo paia sus moviles tanto Symbian
como Naemo (pioyecto que al final se ha fusionauo con Noblin ue Intel, paia cieai Neeuo, y
competii con Anuioiu ue uoogle) con la auquisicion ue Qt.
Actualmente a finales ue 2u1u, Qt acaba ue salii en la veision 4.7 uonue se aauen
nuevas caiacteiisticas extiaoiuinaiias paia la cieacion ue uiseos ue fiont-enus paia
uispositivos moviles y electiouomsticos, con la entiaua ue QNL (Qt Beclaiative) un lenguaje
ueclaiativo paia cieai inteifaces gificos muy vistosos. Qt ya ha siuo poitauo y sopoitauo poi
Nokia paia las siguientes platafoimas: LinuxX11 (y otios 0NIX, como Solaiis, AIX, BP-0X, IRIX),
Winuows, Nacintosh, Embeuueu Linux, Winuows CENobile, Symbian y Neeuo. Y con uesaiiollo
exteino se ha poitauo o se est poitanuo a platafoimas como: 0pen Solaiis, Baiku(Be0S libie),
0S2(Platafoima eCS ue IBN), iPhone y Anuioiu. Como pouemos apieciai, Qt es un Fiamewoik
que no paia ue ciecei, y el secieto ue este xito, es no solo su potencia y velociuau fiente a otias
alteinativas como }ava (uonue es entie S y 6 veces ms ipiuo), si no poique es atiactivo paia el
piogiamauoi y ipiuo paia uesaiiollai, uesue la saliua ue QtCieatoi 2.u, el entoino IBE paia Qt.
#


Qt incoipoia un estilo ue piogiamacion a C++, que le hace menos vulneiable a los fallos
ue piogiamacion, sobie touo en el manejo ue memoiia (memoiy leaks), y que lo hacen muy
agiauable ue caia al uesaiiollauoi.
Qu vamos a apienuei en este libio.. Este libio pietenue sei el piimei escalon a subii
paia alguien ue habla hispana que quieia apienuei a uesaiiollai aplicaciones multiplatafoima
con Qt4. Su conteniuo ha siuo escogiuo, paia pouei cubiii el uesaiiollo ue cualquiei aplicacion ue
pioposito geneial. Cualquieia que complete el conteniuo ue este libio con sus ejeicicios y
ejemplos, poui uesaiiollai este tipo ue aplicaciones sin gianues pioblemas. Sin embaigo, Qt
ciece touos los uias, aauienuo nuevas posibiliuaues, nuevos mouulos y nuevas clases, y a uia ue
hoy es tan extenso que ningn libio en ningn iuioma contiene una uesciipcion completa uel
mismo. Poi lo que la nica fuente uonue pouemos iecogei esa infoimacion, es la misma ayuua
que el SBK uel Fiamewoik nos piopoiciona con su asistente (Qt Assistant), peio esta
uocumentacion est esciita en ingls nicamente. Es poi tanto necesaiio pouei leei y sei capaz
ue uesenvolveise en este iuioma, paia usai toua la capaciuau que Qt nos pueua ofiecei.
Poi lo tanto, este libio consigue sentai unas bases claias en el conocimiento ue Qt4, peio
paia ii ms all es necesaiio sabei usai la uocumentacion en ingls que acompaa a toua veision
uel Fiamewoik. Los temas estn oiuenauos ue maneia piogiesiva, paia que nauie se pieiua. El
lenguaje usauo es sencillo y uiiecto, poi lo que el conteniuo ue ningn tema exceue las 8 pginas
ue extension, y poi tanto pueue cubiiise en un solo uia. Acompaanuo a estos temas, est el
couigo ue los ejemplos, y los ejeicicios iesueltos, que nos complementan lo apienuiuo. No pase
ue un tema al siguiente, sin leei touo este couigo, compienueilo, e intentai hacei los ejeicicios
que se pioponen. Este libio piopone una base funuamental paia el conocimiento ue Qt oiientauo
al uesaiiollo ue aplicaciones ue pioposito geneial, y sin uominai esta base soliua, no poui
seguii avanzanuo confoime a sus necesiuaues futuias en nuevos aspectos uel Fiamewoik.
Tiataiemos poi tanto touos los aspectos funuamentales uel uesaiiollo ue aplicaciones u0I con
touos sus componentes posibles, capaciuaues como el uibujo, impiesion ue uocumentos, acceso a
bases ue uatos, acceso a la ieu, la piogiamacion concuiiente, acceso al sistema ue ficheios y el
uso ue los piincipales tipos ue iecuisos.
Y lo mejoi ue touo, es que este libio es libie, y se poui uistiibuii libiemente y sin coste
alguno. Tiatamos ue beneficiainos con la cieacion ue una comuniuau ue piogiamauoies en
espaol, nutiiua y piolifica. Poi touo ello, bienveniuo a esta maiavillosa aventuia que es
apienuei C++Qt4.













$


123456 36 782962438:

1.- Instalacion uel Qt SBK 7
2.- Compilacion 9
S.- Estiuctuia ue una aplicacion 11
4.- La piimeia aplicacion Qt 1S
S.- Q0bject, metaobjetos y piopieuaues 17
6.- El manejo ue la memoiia 2S
7.- Seales y Slots 27
8.- QSignalNappei SS
9.- Nanejo ue cauenas en Qt SS
1u.- Colecciones en Qt S9
11.- Tipos Qt 4S
12.- Sistema ue ficheios 4S
1S.- Esciituia y Lectuia ue ficheios 47
14.- Wiugets y Layouts 49
1S.- ventanas ue Bilogo SS
16.- Nouelo, vista y Contiolauoi. Intiouuccion. 61
17.- QListWiuget y QTableWiuget 6S
18.- Qt Cieatoi 67
19.- Nain Winuows 69
2u.- Besaiiollo ue una aplicacion completa 7S
21.- Layout a fonuo 8S
22.- Bases ue uatos 89
2S.- Reues TCPIP 9S
24.- Piogiamacion concuiiente 99
2S.- uificos e Impiesion 1uS
26.- Recuisos Exteinos 1u7
27.- Bscate la viua 1u9
28.- Instalauoies 111
Bibliogiafia 119

%































&


)%/" ;
0&+)"<"70-& '%< () +'=

A piogiamai, se apienue piogiamanuo, poi lo que antes ue comenzai a iecibii una
ingente cantiuau ue infoimacion teoiica, hay que estai en la uisposicion ue pouei piobai touo lo
que se iecibe ue una maneia pictica, paia que asi el ciclo uiuctico se culmine poi completo. Poi
ello, antes ue naua, vamos a piepaiainos un entoino ue uesaiiollo lo suficientemente comouo
paia pouei acuuii a l caua vez que lo necesitemos, mientias vamos apienuienuo nuevos
conceptos.
Qt es un Fiamewoik completo multiplatafoima, poi lo que vamos a vei como se instala
en los S tipos ue sistemas ms extenuiuos hoy uia, a sabei: Winuows, Linux y Nac0SX.

>?@?A:6 6B +'= 36 0296A269
Qt se pueue empezai a conocei e incluso a usai nicamente en su veision 0pen Souice
(uPL o LuPL), la cual pouemos bajai en su ltima veision ue la web
http:qt.nokia.comuownloaus .
Be touos los aichivos que alli se nos ofiece, iecomenuamos pulsai en la seccion LuPL y
bajaise las veisiones "Complete Bevelopment Enviionment", que auems son las ms extensas,
ya que no solo incluyen el SBK, si no tambin el Qt Cieatoi, que es el IBE ue uesaiiollo, auems
ue muchas otias heiiamientas ue uesaiiollo, ejemplos y uocumentacion, eso si, en peifecto
ingls. Poi lo que es ue gian ayuua al menos sei capaz ue leei y compienuei un poco el ingls
infoimtico.


02:9?B?54C2 62 D4238E: FG H49:

0na vez nos hemos bajauo el ficheio qt-suk-win-opensouice-2uxx.xx.exe (uonue las
xx.xx son nmeios iefeientes a ao y veision uel empaquetauo). Esta instalacion lleva incluiuo el
paquete NinuW que compienue el compilauo y heiiamientas gcc , g++ y make.
Solamente hay que ejecutailo, y seguii las instiucciones poi uefecto. Al final obtenemos
un icono en el Esciitoiio uel Qt Cieatoi. En el pioximo tema, veiemos la estiuctuia ue lo que nos
ofiece uicho IBE. No obstante pueues vei que en el men ue Aplicaciones, apaiece el giupo "Qt
SBK by Nokia .", y uentio ue l, pouemos vei heiiamientas como Qt Bemo, uonue se nos
piesenta una seiie ue aplicaciones ue ejemplo, uonue pouiemos ejecutailas pues ya vienen
compilauas paia nuestia platafoima, y en la subcaipeta Tools, tenemos el Qt Assistant que sei
nuestio asistente y ayuua uocumental paia buscai la infoimacion que necesitemos uel SBK. El Qt
Besignei que nos seivii paia uiseai u0Is, y el Qt Linguistic que nos ayuuai a implementai
tiauucciones a otios iuiomas ue nuestia aplicacion.
El sistema ya est listo y piepaiauo paia sei usauo en nuestio cuiso. Ya pueues ii uiiecto
al siguiente tema.

02:9?B?54C2 62 <42IJ FG K L* H49:
Aunque algunas uistiibuciones Linux pueuen bajaise ue sus iepositoiios oficiales una
veision ue Qt e incluso uel Qt Besignei, nosotios vamos a optai poi instalai, la ltima veision
completa en nuestia uistio.
'


Paia ello nos bajamos el ficheio qt-suk-linux-x86-opensouice-2uxx.xx.bin (uonue las
xx.xx son nmeios iefeientes a ao y veision uel empaquetauo), paia Linux S2 bits o el ficheio
qt-suk-linux-x86_64-opensouice-2uxx.xx.bin paia Linux 64 bits. Antes ue instalailo, es necesaiio
tenei instalauos uCC, u++ y Nake, que en las veisiones ueiivauas ue Bebian se hace con un meio
"apt-get install builu-essential" y en las basauas en Reu Bat se hace con una "yum install gcc gcc-
c++ make".
0n vez bajauos los ficheios, uesue ioot le uamos peimiso ue ejecucion (chmou +x), y lo
ejecutamos uesue la consola. Se abiii una ventana ue uilogo y pouemos instalailo en el
uiiectoiio que queiamos (poi ejemplo optqtsuk-2uxx.xx). 0na vez se acaba la instalacion,
vamos a piepaiai el PATB paia nuestia sesion ue usuaiio que poui acceuei al IBE. Asi poi
ejemplo en el uiiectoiio ue usuaiio, en .bash_piofile, aauiiemos al PATB actual lo siguiente:
PATB=$PATB:optqtsuk-2u1u.uSqtbin: optqtsuk-2u1u.uSbin
volvemos a ieiniciai la sesion, y ya pouiemos acceuei uesue la consola a las uifeientes
heiiamientas, como al Qt Cieatoi, tecleanuo qtcieatoi, al Qt Bemo, tecleanuo qtuemo, al Qt
Assistant, tecleanuo assistant, al Qt Linguistic, tecleanuo linguistic.
En el Qt Bemo, uonue se nos piesenta una seiie ue aplicaciones ue ejemplo, uonue
pouiemos ejecutailas pues ya vienen compilauas paia nuestia platafoima. El Qt Assistant que
sei nuestio asistente y ayuua uocumental paia buscai la infoimacion que necesitemos uel SBK.
El Qt Besignei que nos seivii paia uiseai u0Is, y el Qt Linguistic que nos ayuuai a
implementai tiauucciones a otios iuiomas ue nuestia aplicacion.
Pueues haceite unos uispaiauoies (accesos uiiectos) en tu esciitoiio, buscanuo el
ficheio en optqtsuk-2uxx.xxqtbin, y el icono en optqtsuk-2uxx.xxbin (Nokia-QtCieatoi-
128.png).
El sistema ya est listo y piepaiauo paia sei usauo en nuestio cuiso. Ya pueues ii uiiecto
al siguiente tema.

02:9?B?54C2 62 /?5-+M
Bajauo el ficheio qt-suk-mac-opensouice-2uxx.xx.umg y pieviamente instalauo XCoue
uel uisco ue Nac0SX coiiesponuiente, solo tenemos que instalailo siguienuo las opciones poi
uefecto uel instalauoi.
0na vez teiminaua la instalacion, pouemos aauii accesos uiiectos a nuestia baiia a las
heiiamientas que pouiemos encontiailas en BevelopeiApplicationsQt. Los ejemplos se han
instalauo en BevelopeiExamplesQt.
El sistema ya est listo y piepaiauo paia sei usauo en nuestio cuiso. Ya pueues ii uiiecto
al siguiente tema.

-9A?: NB?9?O8AP?:
La instalacion en otias platafoimas, no est explicaua en este libio, ya que no se tiata ue
un tema ue caictei intiouuctoiio ni ue pioposito geneial. No obstante pueues obtenei ms
infoimacion al iespecto en http:uoc.tiolltech.com4.6suppoiteu-platfoims.html y en otias
secciones ue la web ue Qt Nokia.



(


)%/" G
7-/#0<"70Q&

0na vez ya tenemos nuestios SBK y heiiamientas ue uesaiiollo peifectamente
instalauas, vamos a configuiai el Qt Cieatoi, y a explicai someiamente su uso, compilanuo un
ejemplo.
Antes ue comenzai a piogiamai, seiia inteiesante uestinai un uiiectoiio o caipeta uel
sistema local paia guaiuai los ejemplos y ejeicicios que vamos a hacei. Pueue sei en cualquiei
caipeta o uiiectoiio, y uentio ue esta se iin guaiuanuo en caipetas caua uno ue los pioyectos
que vayamos usanuo. En esa misma caipeta pueues tambin uescompiimii touos los ejemplos
que van acompaanuo a este libio, ue maneia que si uestinamos la caipeta qtsic paia este
menestei, los ejemplos estain en caipetas como qtsictemaXX (uonue XX es el nmeio uel
tema).
vamos poi tanto ya a abiii el Qt Cieatoi, ejecutnuolo. Se nos abiii el IBE con una
ventana sobie l como sta:

Pouemos pulsai sobie Cieate Pioject. paia cieai un nuevo pioyecto, u 0pen Pioject. paia abiii
uno pieexistente. Si activamos el tab Bevelop, pouiemos vei las sesiones iecientes que hemos
abieito y asi acceuei a ellas uiiectamente.
Bien vamos a pulsai en 0pen Pioject. y vamos ii a la caipeta temau2 y uentio ue ella,
vamos a entiai en la caipeta application, vamos a seleccionai el ficheio application.pio, y vamos
a abiiilo.
Al abiiise, pouemos vei la uisposicion uel Qt Cieatoi. A la izquieiua, hay una baiia ue
heiiamientas, uonue en la paite supeiioi ue la misma, se pueue elegii la heiiamienta ue
uesaiiollo a usai. Be aiiiba a abajo: Welcome (Bienveniua), Euit (euitoi, que es su foima habitual
paia intiouucii couigo), Besign (acceso al Qt Besignei, paia cieai la u0I euitanuo ficheios tipo
*.ui), Bebug (paia uebugeai un ejecutable), Piojects (que nos peimite configuiai opciones uel
pioyecto) y Belp (paia acceuei al asistente). En la zona infeiioi ue esta misma baiia,
encontiamos un icono ue una pantalla ue oiuenauoi, uonue en la paite supeiioi, inuica el
nombie uel pioyecto actual poi uefecto, y si el mouo Builu es Bebug o Release (poi uefecto lo
tenuiemos en Bebug, hasta que vayamos a geneiai una aplicacion paia sei uistiibuiua). Bebajo
estn las heiiamientas ue Run (ejecutai), Stait Bebug (comenzai uebug) y Builu All (constiuiilo
touo).
)*


A la ueiecha ue esta baiia ue heiiamientas, peio an en el lauo izquieiuo, nos queua en
la zona supeiioi, el ibol logico ue los ficheios que componen el pioyecto. Pouemos seleccionai
uentio ue l, cualquiei ficheio, y hacienuo uoble clic sobie l, abiiilo paia euicion. En la paite
infeiioi apaiecein el listauo ue touos los ficheios que tengamos abieitos, ue maneia que
pouemos acceuei uiiectamente a ellos, pulsanuo sobie sus nombies, o ceiiailos, pulsanuo sobie
la X que apaiece si uejamos un tiempo el cuisoi sobie un nombie ue ficheio.
La paite ueiecha supeiioi, es uonue pouiemos vei el couigo ue los ficheios, y en la
infeiioi, los mensajes uel compilauoi, uebuggei, etc.
vamos ahoia a configuiai el entoino paia tiabajai con los ejemplos ue nuestio libio.
Paia ellos entiamos a las piefeiencias, que en Winuows y Linux, est en Tools->0ptions, y en
Nac0SX, est en Qt Cieatoi->Piefeiences. Nos apaiecei una ventana con opciones, las cuales
vamos a uejai touas poi uefecto excepto en Piojects, uonue vamos a fijai el uiiectoiio paia
nuestios pioyectos, y en Besignei, nos vamos a ceicioiai ue tenei la opcion "Aggiegation as a
pointei membei" y naua ms (como pueues vei en el gifico infeiioi).

Pulsamos en 0K y nos vamos a Piojects en la heiiamientas ue la izquieiua. Alli seleccionamos
Euitoi Settings, y ponemos como Befault File Encouing "0TF-8".
Pulsamos ahoia en Euit, y nos vamos abajo paia pulsai en Run. Be esta maneia se
compilai el pioyecto actual, y se ejecutai una vez compilauo. Nos apaiecei una ventana ue un
sencillo euitoi ue texto con su baiia ue heiiamientas, que coiiesponue a la aplicacion que
acabamos ue compilai y ejecutai. Si en la baiia ue la izquieiua sobie la zona infeiioi, hubieia
apaieciuo una baiia en iojo con un nmeio (el ue eiioies), esto nos inuicaiia que hay eiioies en
la compilacion o en el linkauo, poi lo que habiia que ievisai que la instalacion sea coiiecta, y la
aplicacion que se ha caigauo.
En los siguientes temas, iiemos piofunuizanuo en el uso uel Qt Cieatoi como IBE ue
uesaiiollo uel SBK ue Qt.
)62R? 62 5I629? SI6 T6P8: NA6N?A?38 6B 6298A28 N?A? 36:?AA8BB?A 2I6:9A?:
?NB45?54826:U N6A8 ?I2SI6 T?K? 582:6RI438 58PN4B?AB?: 62 :I V6A:4C2 $6B6?:6 W28 '6HIRXU
28 N83AY N8A9?AB?: 9?B 5I?B ? 89A? PYSI42? N?A? SI6 OI2548262 9?B 5I?BU K T?HAY SI6 98P?A
546A9?: 5I6:94826: 62 582:436A?54C2 N?A? SI6 :6 NI63?2 4PNB6P629?A 6 42:9?B?A :42
NA8HB6P?: 62 I2 :4:96P? O42?B 36 NA83I554C2Z )838 6BB8 B8 V6A6P8: 582 369624P46298 62 6B
96P? G[Z '6 P8P6298U V?P8: ? ?NA6236A ? 36:?AA8BB?AU N6A8 :4 :6 BB6V? B8: 6@65I9?HB6: ?
89A? PYSI42? :42 6B +'= 42:9?B?38U :6N? SI6 28 V?2 ? OI25482?A 36 ?296P?28Z


))


)%/" F
%+)$\7)\$" '% \&" "#<07"70Q& ()*

Antes ue comenzai a vei la piimeia aplicacion en Qt4, vamos a vei cual es la estiuctuia
ue una aplicacion en Qt, ue esta maneia comenzaiemos a vei el cuauio uesue lejos, antes ue
empezai a auentiainos en los uetalles. Esta es la foima ms ueseable ue comenzai un estuuio
que pietenue sei los ms apiovechable posible. Qt, posee una foima ue oiuenai el couigo, que
uesue el piincipio es funuamental conoceilo, paia cieai couigo sencillo y legible uesue el piimei
momento. No impoita lo sencillo o complejo que pueua sei un pioyecto, si el couigo se estiuctuia
bien, siempie poui sei manteniuo ue una maneia ms sencilla y eficaz.
%:9AI59IA? 36 I2 NA8K6598
Touo pioyecto con inteifaz visual (u0I) en Qt, tiene los mismos elementos que son:
1.- ./01&$*, 2& 3*$4+5#$/*, 63*$4,7.- Con la extension *.ui, caua ficheio uesciibe en lenguaje XNL
el inteifaz gifico ue foimulaiios o ventana ue la aplicacion. Poi lo tanto caua ficheio *.ui es una
ventana, peio no touas las ventanas ue la aplicacion tienen que estai en un ficheio *.ui, ya que se
pueuen implementai con couigo C++. Estos ficheios son uiseauos gificamente en el Qt
Besignei, el cual geneia automticamente el couigo XNL ue uichos ficheios.
2.- ./01&$*, 8#9&0&$# 61&#2&$,7.- Con la extension *.h . Lo ms iecomenuable es que la ueclaiacion
ue caua clase vaya en un ficheio cabeceia poi sepaiauo, y el nombie uel ficheio coinciua con el
nombie ue la clase que se ueclaia. Asi poi ejemplo, si vamos a uesaiiollai una clase llamaua
calculatoi, el ficheio cabeceia que la ueclaia poi completo la llamaiiamos "calculatoi.h".
S.- ./01&$*, .+&%)& 6,*+$0&,7.- Con la extension *.cpp . Lo ms iecomenuable es que la
implementacion o uesaiiollo ue caua miembio ue una clase, est conteniuo poi completo en un
ficheio con el mismo nombie que la clase que implementa. Asi poi ejemplo, la implementacion ue
la clase calculatoi, estaiia en el ficheio ue nombie "calculatoi.cpp". Bentio ue los ficheio fuente,
siempie hay uno que contiene la funcion piincipal (main) y cuyo nombie sei "main.cpp".
4.- ./01&$* 2& -$*:&0)* 6-$*"&0)7.- Con la extension *.pio . Es un ficheio que pueue geneiaise y
iellenaise automticamente si hemos cieauo el couigo con el Qt Cieatoi, o que pueue no existii, y
ueba antes sei cieauoi con el comanuo "qmake -pioject" antes ue la compilacion uefinitiva. El
nombie uel mismo coinciuii con el ue la caipeta ue pioyecto cieaua. Si nuestio pioyecto se
llama calculatoi, el ficheio pioyecto tomai el nombie "calculatoi.pio".
Touos los ficheios ue un pioyecto Qt, es iecomenuable que se encuentien en un mismo
uiiectoiio iaiz, cuyo nombie coinciua con el nombie completo uel pioyecto. veamos ahoia la
estiuctuia inteina ue caua uno ue los tipos ue ficheios mencionauos.

]45T6A8 O8APIB?A48
Se tiata ue un ficheio esciito en couigo XNL con la uesciipcion ue touos los elementos
uel inteifaz visual ue uno ue los foimulaiios uel pioyecto. No es necesaiio conocei la estiuctuia
exacta uel mismo, y ue hecho, si en el Qt Cieatoi, haces uoble click sobie un ficheio *.ui, se te
abiii uiiectamente el Qt Besignei, ue maneia que se mostiai la inteifaz gifica. En la baiia ue
heiiamientas ue la izquieiua, tenuis que pasai uel mouo "Besign" al mouo "Euit" paia pouei vei
el couigo XNL que siempie tenui la siguiente estiuctuia.




<?xml version="1.0" encoding="UTF-8"?>
)!


<ui version="4.0">
.........................
.........................
<ui>

]45T6A8 5?H656A? W5B?::2?P6ZTX
vamos a paitii ue la iuea ue solamente ueclaiai una clase en un solo ficheio.

#ifndef CLASSNAME_H
#define CLASSNAME_H

#include <QClasePadre>
// podemos declarar aqu otras clases del proyecto que
// sean usadas en la implementacin de esta clase
class Claseincluida;

class Classname : public QClasePadre
{
// el contructor con un solo parmetro lo declararemos
// siempre como explicit, y al menos con el puntero a la
// clase padre inicializado a NULL
explicit Classname (QClasePadre *parent = 0);

// Cuerpo con la declaracin de todos los miembros de la clase

..
};
#endif


Como pueues obseivai, es muy iecomenuable el ponei en la piimeia, segunua y
ltima lineas uel mismo, las conuicionales al piepiocesauoi paia evitai la ieinclusion ue este
couigo ms ue una vez. Bespus, incluimos con #incluue las clases Qt usauas en la
implementacion ue esta clase, y la ueclaiacion ue clases nuestias incluiuas en este pioyecto que
son usauas en la implementacion ue esta clase. Finalmente tenemos la ueclaiacion ue la clase
misma con touos los elementos miembio.


]45T6A8 OI6296 W5B?::2?P6Z5NNX

#include "classname.h"

Classname:: Classname (QClasePadre *parent) :
QClasePadre (parent)
{
// implementacin del contructor de la clase
}

// implementacin del resto de miembros de la clase classname
..



)"


Piimeio incluimos la cabeceia ue nuestia clase. Luego implementamos el constiuctoi,
e inicializamos el constiuctoi ue la clase pauie siempie lo piimeio. Bespus implementamos el
iesto ue los miembios ue la clase.


Fichero fuente principal (main.cpp)

#include <QModulo>
#include "claseinterfaz.h"

int main(int argc, char **argv)
{
QApplication a(argc, argv);

claseinterfaz w;
w.show();
// Mucho ms cdigo que sea necesario

return a.exec();
}


Piimeiamente incluimos el mouulo necesaiio paia el couigo que vamos a incluii en la
funcion main(). Lo ms logico es que vaya incluiua la clase inteifaz, que ciea la ventana piincipal.
Bicha ventana poui sei un wiuget (QWiuget), una ventana ue uilogo (QBialog) o una ventana
piincipal (QNainWinuow). Piimeiamente cieamos una instancia ue QApplication que pueue
iecibii aigumentos ue la linea ue comanuos. Luego instanciamos la clase inteifaz, mostiamos
uicho inteifaz, y finalmente con QApplication::exec() entiamos en el bucle ue eventos paia
inteiactuai con el inteifaz mostiauo.

La piimeia y ltima lineas ue couigo ue la funcion main(), solo son necesaiias si se
tiata ue una aplicacion con inteifaz gifico (u0I). Si se tiata ue una aplicacion ue consola, no se
usain, y en puesto ue instanciai un clase inteifaz, se haiia uso ue couigo no gifico paia consola.
Baiemos uso ue piogiamas paia consola, paia estuuiai y iefoizai clases ue Qt que no son
gificas, paia simplificai el couigo y facilitai el apienuizaje ue los conceptos.














)#































)$


)%/" *
<" #$0/%$" "#<07"70Q& (9

La mayoiia ue libios que ensean un lenguaje ue piogiamacion, siempie empiezan poi
uemostiai la sencillez uel lenguaje con la tipica aplicacion Bola Nunuo. Y es una tiauicion que se
ha peipetuauo poi los tiempos ue los tiempos. Sinceiamente me paiece que es una tiivialiuau, ya
que no ensea absolutamente naua sobie el lenguaje ms all ue impiimii un mensaje en
pantalla, peio en un munuo uonue touos vamos coiiienuo y necesitamos vei los iesultauos antes
ue iecoiiei el camino, ha teiminauo imponinuose. Bien es cieito que Qt no es un lenguaje, si no
un Fiamewoik que en este libio en paiticulai lo hemos ueuicauo al uesaiiollo ue Qt en C++. Asi
que el lenguaje C++, es un conocimiento pievio que se piesupone antes ue leei la piimeia linea
ue este libio, poi lo que un Bola Nunuo queua an ms uescolocauo, peio en fin, sucumbiiemos a
la tenuencia geneializaua.

Paia uesaiiollai uicha aplicacion, vamos a usai el Qt Cieatoi, y puesto que Qt se pueue
usai no solo paia cieai inteifaces gificas, si no tambin aplicaciones ue consola, vamos a vei las
uos posibles aplicaciones Bola Nunuo.

,8B? PI238 582 ^\0
Abiimos Qt Cieatoi, o si ya lo tenemos abieito, abiimos un nuevo pioyecto pulsanuo en
File->New File oi Pioject. Apaiecei una ventana como la ue abajo.

Elegimos 0thei Pioject -> Empy Qt Pioject (un pioyecto vacio). Be esta foima no se nos cieai
ningn couigo automticamente, touo lo haiemos nosotios manualmente. Pulsamos el boton
Choose. y apaiece una nueva ventana, uonue ponuiemos el nombie uel pioyecto que sei
"holamunuo" y abajo en Cieate in, escogeiemos un uiiectoiio uonue tenuiemos touos nuestios
pioyectos. Pulsamos Continue y luego Bone. A la izquieiua en la columna ue pioyectos (Piojects)
nos apaiece, la caipeta ue nuestio nuevo pioyecto, y solo el ficheio holamunuo.pio que Qt
Cieatoi se encaigai ue ii iellenanuo poi nosotios. Bacemos clic con el boton ueiecho sobie el
pioyecto y uel menu emeigente escogemos la penltima opcion (Auu New.). Escogemos C++ en
Files anu Classes, y C++ Souice File en la columna ue la ueiecha. Pulsamos Choose. y le ponemos
el nombie al ficheio "main.cpp" en Name. Pulsamos Continue y Bone. Ahoia apaiece una nueva
caipeta llamaua Souices con un ficheio main.cpp uentio ue ella.
)%



Bacienuo uoble clic sobie main.cpp, pouiemos vei a la ueiecha el lienzo en blanco piepaiauo
paia empezai a esciibii el couigo en l. vamos a esciibii el siguiente couigo:
#include <QApplication>
#include <QLabel>

int main(int argc, char **argv){
QApplication a(argc,argv);

QLabel l("Hola mundo");
l.show();

return a.exec();
}

Como se pueue vei hemos usauo una clase QLabel paia cieai el letieio uonue ponui el mensaje
"Bola munuo". Puesto que usamos uos clases en este ficheio ue Qt (QApplication y QLabel),
hemos teniuo que incluii sus cabeceias.

,8B? PI238 :42 ^\0
#include <QDebug>

int main(int argc, char **argv)
{
qDebug() << "Hola mundo\n";

return 0;
}

La clase QBebug es peifecta paia sacai mensajes poi consola, y tiene sobiecaigauo el opeiauoi
<< paia que actue ue maneia similai a como lo hacia stu::cout en la STL ue C++.
Sigue los ejeicicios ue este tema uonue se compila y se ejecutan estos 2 simples ejemplos.








)&


)%/" _
(-H@659U P69?8H@698: K NA8N463?36:

Llego el momento ue meteinos en haiina, y paia ello mejoi es empezai a conocei las
paiticulaiiuaues ue Qt que la hacen uifeiente a las STL. Paia ello lo mejoi es comenzai poi la
clase piincipal, pauie ue la mayoiia ue las clases que componen Qt4, esa clase es Q0bject. Luego
veiemos la estiuctuia global ue clases que componen el Fiamewoik y tiabajaiemos con una ue
las cualiuaues ms inteiesantes ue Qt, la /%)$*,-&00/;%.

<? 5B?:6 (-H@659
uian paite ue la magia uesplegaua en el Fiamewoik Qt, ueiiva ue la clase Q0bject, que es
la clase piincipal. Touos los wiugets usauos paia cieai la u0I ueiivan ue esta clase. Be hecho Qt
uespliega gian paite ue lo que Qt es: seales y slots, piopieuaues y manejo ue memoiia sencillo.
Qt extienue a C++ con nuevas caiacteiisticas, ue las cuales uos son intiouuciuas poi esta misma
clase como son: el mouelo ue intiospeccion, y las conexiones entie objetos meuiante seales y
slots. Si ievisas la uocumentacion ue Q0bject en el asistente (Qt Assistant), veis entie sus
miembios touas estas caiacteiisticas.
Q0bject, poi tanto, es la clase base ue la mayoiia ue las clases uel fiamewoik Qt, sin
embaigo, no ue touas. Las clases que no uepenuen ue Q0bject son:
- Clases ue piimitivas gificas que iequieien tenei poco peso, sienuo ms sencillas como:
Quiauient, QPaintei, QScieen, QPalette.
- Clases conteneuoias ue uatos como: QChai, QStiing, QList, QNap, QBash..
- Clases que necesiten sei copiables, ya que las clases ueiivauas ue Q0bject no son
copiables.
La piimeia caiacteiisticas impoitante que tiene Q0bject, es que no es copiable, toua
instancia ue la misma es nica. Touo objecto Q0bject es nico e inuiviuual. Poique los objetos
tienen nombie (piopieuau *9"&0)<#4&), y este es nico paia caua objeto, y esto es funuamental
paia implementai la intiospeccion. Caua objeto, esta situauo en algn lugai especifico ue la
jeiaiquia ue clases Q0bject, y eso no iequieie sei copiable. Finalmente caua objeto, tiene
conexiones con otios objetos meuiante conexiones seal-slot que veiemos ms auelante, y eso no
pueue sei copiauo. Poi touas estas iazones, los objetos ue Q0bject, son nicos e incopiables en
tiempo ue ejecucion como poi ejemplo si lo es un QStiing (una cauena).
C++ es extenuiuo en Qt paia uotailo ue caiacteiisticas funuamentales paia el fiamewoik.
0na ue ellas, son los !"#$%$#&' .
Los metauatos, llevan infoimacion sobie el objeto instanciauo, tales como el nombie uel
objeto, el nombie ue su clase, sus objetos hijos, sus piopieuaues, sus seales y slots, toua una
seiie ue infoimaciones sobie la clase uel mismo. Esto nos peimite una ue las ms impoitantes
caiacteiisticas ue Qt, que es la intiospeccion, que facilita mucho integiai Qt con otios lenguajes
ue sciipting y entoinos uinmicos (Ruby, Python, PBP, etc). Instanciauo un Q0bject, pouiiamos
obtenei ue l infoimacion sobie el mismo a tiavs ue los metauatos.
0na foima, seiia meuiante el mtouo miembio Q0bject::inheiits(const chai* className),
que nos peimitiiia hacei un casting uinmico sin usai el RTTI (lo cual pueue evitai muchos
eiioies uel piogiamauoi):
if(object->inherits("QAbstractItemView")){
QAbstractItemView *view = static_cast<QAbstractItemView *>(widget);
............
}

)'


0no ue los miembios ms impoitantes paia acceuei a los metauatos ue una clase, y poi
tanto paia implementai la intiospeccion es !"#$()*"+#,- . Bevuelve un objeto ue la clase
QNeta0bject, que si miiamos en el asistente touos sus miembios, pouiemos obseivai toua la
infoimacion que pouemos conseguii en $+%=)/4& ue un objeto cualquieia.
object->metaObject()->className(); // devuelve un char* con el nombre de la clase
object->metaObject()->indexOfProperty("width");


Los metauatos, son iecabauos poi el moc (meta-object compilei) uel piopio couigo
ueclaiativo ue las clases en los aichivos cabeceia. Lo piimeio que busca el moc es que la clase se
ueiive ue Q0bject ue maneia uiiecta o inuiiecta, paia buscai en ella touos los metauatos y
geneiai el couigo necesaiio paia ellos. Luego busca NACR0S uel tipo Q_ , como: Q_0B}ECT,
Q_CLASSINF0, etc; que aauen infoimacion ue la clase. Finalmente busca palabias clave aauiuas
poi Qt como slots y signals, que ueclaian los mtouos miembios ue la clase que se encaigain ue
la conectiviuau ue la misma con objetos ue otias clases. El moc con touo esto geneia
automticamente couigo que guaiua en ficheios que comienzan poi moc_*.cpp .
0tia funcion miembio intiospectiva muy impoitante que incoipoia Q0bject es
/01%+203%4"1. La fiima ue la misma es:
(<4:9`)a (-H@659bbO4237T4B3A62 W 582:9c(+9A42Rcdc1$!"ce (+9A42RWX X 582:9
que nos uevuelve una coleccion ue objetos hijos ue la clase cuyo nombie se pase como
aigumento. QList es una clase template que veiemos ms auelante, peio similai a una lista o
vectoi ue STL.
Poi ejemplo, si queiemos obtenei los wiugets que son hijos ue un wiuget en paiticulai a
tiavs ue su nombie (wiugetname), pouemos usai un couigo como este:
QList<QWidget *> widgets = parentWidget.findChildren<QWidget *>("widgetname");

Poi ejemplo, paia obtenei una lista con touos los botones uel tipo QPushButton,
conteniuos como hijos ue paientWiuget, pouemos usai un couigo como el que sigue:
QList<QPushButton *> allPushButtons = parentWidget.findChildren<QPushButton *>();


#A8N463?36: 36 I2 8H@698
Touo objeto, necesita guaiuai su estauo en algn sitio, uonue se uefina poi completo el
estauo uel mismo y touas sus paiticulaiiuaues, esto es lo que llamamos 54&50"%$%"' ue un
objeto. En el Qt Besignei, a abiii un ficheio foim (*.ui), pouemos pulsai sobie cualquieia ue los
elementos que hay en el foim, y a la ueiecha en la paite infeiioi, vei touas las piopieuaues que
uicho objeto tiene, y los valoies que esas piopieuaues toma paia ese objeto en paiticulai. Qt
guaiua esas piopieuaues como metauatos, y hace uso ue una macio piopia paia ello:
Q_PROPERTY(type name
READ getFunction
[WRITE setFunction]
[RESET resetFunction]
[NOTIFY notifySignal]
[DESIGNABLE bool]
[SCRIPTABLE bool]
[STORED bool]
[USER bool]
[CONSTANT]
)

)(


Esta macio se pone en la ueclaiacion ue la clase, en el ficheio cabeceia ue la misma,
uespus ue la macio Q_0B}ECT. Las paites entie coichetes (|j) no son obligatoiias. vamos a
uetallai caua paite ue esta ueclaiacion:
):-&.- es el tipo ue la vaiiable que guaiuai el estauo ue uicha piopieuau uel objeto (QStiing,
int.).
%#4&.- es el nombie piopio ue la piopieuau en cuestion (wiuth, height..)
>&).+%0)/*%.- nombie ue la funcion gettei o que lee el valoi ue la piopieuau (lo veiemos ms
auelante)
,&).+%0)/*%.- nombie ue la funcion settei o que establece o cambia el valoi ue la piopieuau (lo
veiemos ms auelante)
$&,&).+%0)/*%.- nombie ue la funcion que pone el valoi poi uefecto a la piopieuau.
%*)/3:(/>%#5.- nombie ue la seal (signal) que se piouucii inmeuiatamente uespus ue que el
valoi ue la piopieuau sea cambiauo.
?&,/>%#95&.- nos uice si uicha piopieuau es accesible uesue el entoino ue uiseo, Qt Besignei.
(0$/-)#95&.- nos uice si uicha piopieuau es accesible uesue el entoino ue sciipt ue Qt.
()*$&2.- la mayoiia ue piopieuaues son guaiuauas, y establecen el estauo ue un objeto en un
momento concieto, otias toman valoies ue otias piopieuaues (poi ej. wiuth es paite ue size) y no
son guaiuauas.
@,&$.- es una piopieuau mouificable poi el usuaiio ue la aplicacion (poi ej. isCheckeu() en una
QCheckBox).
8*%,)#%).- las piopieuaues ueclaiauas constant, no pueuen sei cambiauas en la instanciacion ue
la clase, si no entie instanciaciones ue clases.

La gian mayoiia uel tiempo usaiemos meiamente las secciones $%"' y D$0)% paia
nuestias piopieuaues, y si nuestia clase es paite ue un nuevo wiuget visual uiseauo poi
nosotios, aauiiemos '%+0^&"><% tiue, y pueue que \+%$ tiue, si esta pueue sei cambiaua poi
el usuaiio que use la aplicacion (no el piogiamauoi).
La ueclaiacion ue una nueva piopieuau, implica una seiie ue aauiuos en los miembios
ue la clase a la que peitenece, y estos son:
- El constiuctoi uebe ue poneile un valoi inicial, la cual tambin pouiia sei un paimetio
uel mismo, y asi pouei inicializai su valoi poi paite uel piogiamauoi en su instanciacion.
- Bebe ue habei una funcion miembio que se encaigai ue la iecogiua uel valoi actual ue
esa piopieuau. Es lo que llamamos un gettei. Y esta funcion uebe estai en la paite
pblica paia pouei sei usaua uesue fueia ue la clase misma, a la que llamamos settei ue
la piopieuau. Seiia bueno que se llamaia getPiopieuau() o Piopieuau(), e
isEstauo_Piopieuau() si uevuelve un bool.
- Pueue habei una funcion miembio que se encaigue ue establecei o cambiai el valoi ue
piopieuau. Seiia bueno que se llamaia setPiopieuau(valoi_ue_la_piopieuau).
- Bebe ue habei una vaiiable piivaua, que contenga el estauo ue la piopieuau en caua
momento, ue maneia que esta no pueua sei uiiectamente accesible fueia ue la clase.
En una palabia, los gettei y settei ue una piopieuau, son el inteifaz ue la piopieuau ue
uicha clase con el iesto ue objetos, y solo a tiavs ue ellos, el iesto ue la aplicacion poui acceuei
a uicha piopieuau.
Pongamos un ejemplo sencillo ue piopieuau en una clase. Piimeio comenzaiemos con la
ueclaiacion ue los miembios ue la clase en su ficheio cabeceia.
!*


// Fichero angleobject.h
class AngleObject : public QObject
{
Q_OBJECT
QPROPERTY(qreal angle READ angle WRITE setAngle)

public:
AngleObject(qreal angle, QObject *parent=0);

qreal angle() const;
void setAngle(qreal);

private:
qreal m_angle;
}

Si obseivas, veis que angle es una piopieuau que se va a guaiuai en una vaiiable uel
tipo qieal (que es un typeuef ue uouble en Qt, un nmeio ieal ue uoble piecision). La vaiiable la
ponemos como piivaua bajo el nombie ue m_angle (notacion especial paia uistinguii vaiiables
miembio). La funcion gettei es angle() que como vemos al no cambiai el estauo uel objeto
pouemos ueclaiaila como const. La funcion settei va a sei setAngle() y en la instanciacion al
cieai un objeto nuevo ue esta clase, tenuiemos que ponei al menos como paimetio el valoi
inicial ue uicha piopieuau. 0tia foima hubieia siuo que uentio ue la implementacion uel
constiuctoi, uicha piopieuau hubieia tomauo un valoi fijo, que luego el piogiamauoi hubieia
pouiuo cambiai usanuo la funcion settei coiiesponuiente a uicha piopieuau.
Paia entiai un poco ms en mateiia vamos a vei la implementacion ue esta clase:
AngleObject::AngleObject(qreal angle, QObject *parent) :
QObject(parent), m_angle(angle)
{
}

qreal AngleObject::angle() const
{
return m_angle;
}

void AngleObject::setAngle(qreal angle)
{
m_angle = angle;
hazAlgo();
}

vemos como en la implementacion uel constiuctoi, se inicializa llamanuo al constiuctoi
ue Q0bject, la clase pauie y la vaiible piivaua m_angle con el valoi pasauo como paimetio en la
instanciacion. Quizs no ests acostumbiauo a este tipo ue notacion y lo veas mejoi asi:
AngleObject::AngleObject(qreal angle, QObject *parent)
{
QObject(parent);
m_angle = angle;
}
Peio es exactamente lo mismo. La implementacion ue la funcion gettei es tan simple
como uevolvei el valoi ue la piopieuau que se almacena en la vaiiable inteina piopia, y la
implementacion ue la funcion settei, suele hacei uos cosas, piimeio cambiai el valoi ue la
vaiiable inteina asociauo a la piopieuau en cuestion, y luego ponei un couigo que se encaigue ue
la notificacion ue uicho cambio, y la toma ue uecisiones al iespecto (lo hemos iepiesentauo touo
eso como un meio hazAlgo()).
!)


El usai un settei paia cambiai el valoi ue una piopieuau, y no acceuei uiiectamente a la
vaiiable piivaua uel mismo, peimite que un couigo pueua evaluai uicho valoi pieviamente antes
ue asignailo a uicha vaiiable, y asi contiolai uicho valoi uentio ue un iango aumisible uentio ue
la aplicacion, y ue esta maneia hacei honoi a la piopieuau ue encapsulacion C++ como lenguaje
oiientauo a objetos.
El tipo ue una funcion pouiia sei un enum, algo asi como:
public:
enum AngleMode {Radianes, Grados};

En ese caso, tenuiemos que notificai pieviamente al moc ue que, uicho tipo es un enum,
usanuo la macio Q_EN0N ue la siguiente foima:
Q_OBJECT
Q_ENUM(AngleMode)
Q_PROPERTY(AngleMode angleMode READ angleMode WRITE setAngleMode)

Tambin es posible que ese enum, uefina Flags numiicos que pueuan combinaise entie
si con 0R (|). Algo asi como:
Q_OBJECT
Q_FLAGS(LoadHint LoadHints)
Q_PROPERTY(LoadHint hint READ hint WRITE setHint)


public:
enum LoadHint {
ResolveAllSymbolsHint = 0x01, // 00000001
ExportExternalSymbolsHint = 0x02, // 00000010
LoadArchiveMemberHint = 0x04 // 00000100
};
Q_DECLARE_FLAGS(LoadHints, LoadHint)


&89?54C2 6:N654?B 36B 5C34R8
Aunque C++ y Qt poi tanto aumita libiemente la eleccion ue los nombies ue las clases,
sus miembios y la oiganizacion ue las mismas. Es auecuauo paia cieai couigo fcil ue leei, y poi
tanto fcil ue mantenei, si se siguen unas ieglas que se han iuo aauienuo al estilo ue
piogiamacion ue Qt.
Touas las clases ueben ue estai uefiniuas en ficheios apaite con el nombie ue la clase en
minsculas, la ueclaiacion ue la clase y sus miembios en un ficheio *.h y la implementacion ue la
misma en un ficheio *.cpp .
Los nombies ue las clases ueben comenzai en mayscula, y su nombie uebe sei
uesciiptivo ue lo que iepiesentan, o uel tiabajo que van a iealizai. Si es un nombie compuesto, es
impoitante que caua paite uel mismo se uestaque con una mayscula, poi ejemplo
venueuoiesBeRopa. A veces si ueiivamos nuestia clase ue otia pieexistente ue Qt, puesto que
estas siempie comienzan poi Q, pueue sei ue ayuua el llamailas ue la misma foima peio sin la Q
inicial, claio esta, como:
class MainWindow : public QMainWindow

Touas las funciones comienzan en minscula, y si su nombie es compuesto, el iesto ue
paites las comenzamos con maysculas. Su nombie uebe uejai claio, cual es su cometiuo uentio
ue la clase a la que peitenecen. Poi ejemplo, setWiuth(), isBigit(), uockWiugetAiea().
Touas las vaiiables miembio que estn asociauas a piopieuaues que uefinen el estauo
uel objeto, empiezan poi m_. Poi ejemplo m_height (paia sealai la altuia uel objeto).
!!


Como ya hemos sealauo anteiioimente, no es obligatoiia este tipo ue notacion uel
couigo Qt, peio es muy aconsejable si quieies que touo el munuo entienua tu couigo ue maneia
sencilla, incluiuo t mismo unos meses o aos uespus ue habeilo esciito. Bacei anotaciones en
el couigo es inteiesante siempie que se expliquen cosas que no salten a la vista en el mismo
couigo. Be hecho, comentai en exceso el couigo es la mejoi foima ue peiuei la vision global uel
mismo, poi lo que una foima ue evitai tenei que comentai, es que las vaiiables, clases y
funciones tengan sigan una notacion claia y tomen un nombie altamente uesciiptivo, aunque no
muy laigo.
Finalizauos estos iuuimentos, vamos a vei en el pioximo capitulo, la paite ms
impoitante ue una buena piogiamacion en C++, y es el manejo ue la memoiia. 0na buena
piogiamacion en este sentiuo nos evitai ue muchos ue los pioblemas piopios ue la memoiia,
como el tan temiuo "memoiy leak" o "fuga ue memoiia". Es muy impoitante que tomes en
consiueiacion, y ueuiques el mximo esfueizo al conteniuo uel pioximo tema.























!"


)%/" L
%< /"&%f- '% <" /%/-$0"

El mal manejo ue la memoiia, junto con el mal uso ue punteios, es la fuente ue la
mayoiia ue los eiioies y pioblemas ue aquellos que piogiaman en C o en C++. 0n piogiamauoi
ue }ava, nos uii que esa es la gian uesventaja ue piogiamai en C, y que ellos con su magnifico
iecolectoi ue basuia se evitan esos pioblemas. Sin uuua es una buena solucion paia ellos, peio
paia aquel que ama C++, no es iazon suficiente como paia abanuonai el uesaiiollo en este
lenguaje tan potente y veistil a la vez. Be hecho touo piogiamauoi ue sistemas que se piecie,
siempie antes o tempiano tenui que hacei uso ue C, y la alteinativa que quieio planteaite es
usai el estilo Qt junto con su Fiamewoik paia evitai ste y otios pioblemas tipicos.

%B P?26@8 36 B? P6P8A4? 62 (9
Antes ue naua vamos a iecoiuai a unos y a explicai a otios, algo que quizs en su
momento no compienuieion. Caua vez que el sistema opeiativo caiga en memoiia un piogiama
paia ejecutailo, el sistema ieseiva unas ueteiminauas zonas ue memoiia paia el mismo:
- La zona uel couigo o segmento ue couigo.- En ella se caiga el couigo binaiio uel
piogiama que se va a ejecutai con touas sus instiucciones mquina tal cual el
compilauoi las cieo.
- La pila o stack. Esta zona es uonue se van apilanuo vaiiables como en una pila ue platos,
usanuo el mtouo LIF0 (last in, fiist out), el ltimo que entia es el piimeio que sale. La
pila es usaua caua vez que el couigo llama a una funcion, y entia en ella. En la pila se
guaiuan: los paimetios que se pasan a la funcion, las vaiiables locales ueclaiauas
uentio uel mbito ue la misma, y el valoi ue ietoino ue la funcion. Touas estas vaiiables
son uestiuiuas una vez se vuelve ue la llamaua a la funcion. Lo que es lo mismo, fueia ue
las llaves que cieiian el mbito ue la funcion, uichas vaiiables ya no existen, son
uestiuiuas inexoiablemente.
- El monton o heap. Esta zona se ieseiva con peticiones malloc() en C, y new en C++, y
peimanecen touo el tiempo que se quieia. El piogiamauoi tiene la obligacion ue libeiai
esos espacios ue memoiia usanuo fiee() en C, o uelete en C++. Si uicho espacio no es
libeiauo, entonces el piogiama tiene una fuga ue memoiia (memoiy leak) y le pueue
conuucii a un violento ciash.
En la memoiia, y piincipalmente en el heap, es uonue va a estai el oiigen ue gian paite
ue los uesaguisauos ue nuestia piogiamacion en C++.
veamos antes cuales son los pioblemas tipicos en la gestion ue la memoiia:
a) Pioblemas en el stack:
- Leei o esciibii fueia ue los limites ue una aiiay esttico. Esto se pueue solucionai
usanuo los conteneuoies que suministia Qt paia manejai colecciones y usai iteiauoies
paia iecoiieilos o bucles contiolauos con foieach, una nueva palabia clave ue Qt.
- Coiiupcion ue un punteio a funcion. Esto nos pueue llevai a no pouei alcanzai
coiiectamente la funcion. La solucion es no usai punteios a funciones, ue hecho con el
mecanismo ue conexiones entie objetos meuiante funciones seal y funciones slots, nos
evitamos el uso ue callbacks.
b) Pioblemas en el heap:
- Intento ue libeiacion ue memoiia ya libeiaua.
- Libeiacion ue memoiia no asignaua.
- Intento ue esciituia en memoiia ya libeiaua.
- Intento ue esciituia en memoiia no asignaua
- Eiioi en la asignacion ue memoiia
!#


- Lectuia-esciituia ue la memoiia fueia ue los limites ue un aiiay uinmico. Este se pueue
iesolvei ue igual maneia al aiiay esttico en el stack.
Paia iesolvei los cinco pioblemas sealauos en el heap, apaiece un estilo ue
piogiamacion que incoipoiaiemos a Qt, y ese sei el pioposito uel pioximo paigiafo.

,6A6254? 625?362?3?
La mejoi foima ue no tenei que ponei couigo paia libeiai memoiia con uelete, es que
touos los objetos que componen la aplicacion tengan un pauie que o bien est en el stack, o sean
a su vez pauie ue otio objeto. Be esta foima, ningn objeto que est en el heap sei huifano.
vamos a ponei un ejemplo con los objetos que componen una ventana ue uilogo.
QDialog *parent = new QDialog();
QGroupBox *box = new QGroupBox(parent);
QPushButton *button = new QPushButton(parent);
QRadioButton *option1 = new QRadioButton(box);
QRadioButton *option2 = new QRadioButton(box);

Como se pueue vei, es un ibol jeiiquico uel que penuen box y button ue paient, y ue
box penuen option1 y option2. El nico objeto que no tiene pauie, es paient, que seiia la ventana
ue uilogo. Luego el tiuco paia que no haya que aauii ningn couigo que libeie su espacio, es
colocai su cieacion en el stack.
Paia ello vamos a tenei que cieai una clase ueiivaua ue QBialog, a la que llamaiemos
Bialog, y vamos a cieai una instancia ue la misma en el stack ue esta maneia:
#include <QApplication>
#include dialog.h

int main(int argc, char **argv){
QApplication a(argc,argv);

Dialog dialog;
dialog.show();

return a.exec();
}

Al ueiivai Bialog ue QBialog, tenemos que ueclaiailo en un ficheio que llamaiemos
uialog.h, con el siguiente conteniuo:
#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>

class Dialog : public QDialog
{
public:
explicit Dialog(QWidget *parent = 0);
};

#endif // DIALOG_H

Es el minimo couigo, ya que no vamos a ieuefinii ningn mtouo, ni a aauii naua. Luego
en la implementacion, uebeiemos cieai los objetos que uepenuen uel objeto uialog en su
constiuctoi con new, ue esa maneia sein cieauos inmeuiatamente al sei cieauo uialog en el
stack, y peimanecein en la memoiia una vez acabauo el mbito uel constiuctoi, hasta que la
aplicacion se acabe, y al boiiaise uialog uel stack, poi uepenuencia heieuaua sein libeiauos los
espacios ue touos sus hijos. Be esta maneia, hemos evitauo el uso ue couigo libeiauoi, que nos
!$


pouiia habei llevauo a pioblemas con un couigo ms gianue y complejo. veamos pues el couigo
ue implementacion que ponuiiamos en el ficheio uialog.cpp:
#include "dialog.h"

Dialog::Dialog(QWidget *parent) :
QDialog(parent)
{
QGroupBox *box = new QGroupBox(this);
QPushButton *button = new QPushButton(this);
QRadioButton *option1 = new QRadioButton(box);
QRadioButton *option2 = new QRadioButton(box);
}

Es impoitante poi lo tanto que te queues con esta filosofia ue piogiamacion, uonue
siempie, touo objeto que sea huifano ha ue cieaise en el stack que iequieia ue acueiuo al
tiempo que ueba ue vivii (en main, viviiia touo el tiempo ue la aplicacion). Paia ello seiia
necesaiio ueiivai uicho objeto ue una clase ueiivaua ue una ue Qt, geneianuo asi uos ficheios
paia implementai uicha nueva clase, y en el constiuctoi ue uicha clase, es uonue cieaiemos en el
heap los objetos que uepenuan jeiiquicamente ue ste. En una u0I es poi tanto muy habitual el
jeiaiquizai confoime al conteniuo. Asi, si un objeto ue una clase est conteniuo gificamente
uentio ue los limites ue un objeto ue otia clase, sta sei la clase base ue aqul.
Paia ello, las clases ue Qt, implementan vaiios constiuctoies, uonue al menos uno lleva
solo el paimetio uel pauie inicializauo a N0LL pointei poi uefecto, ue maneia que touas las
veisiones uel constiuctoi tiene como ltimo paimetio el N0LL pointei poi uefecto ue la clase
pauie ue la que ueiiva.
En el siguiente tema vamos a vei como en Qt se han evitauo el uso ue callbacks paia
conectai funciones ue uos o ms objetos. Es otia ue las caiacteiisticas funuamentales ue Q0bject.















!%































!&


)%/" g
+%h"<%+ . +<-)+

El mecanismo ue seales y slots ue Qt, ciea una foima uinmica ue comunicai eventos
con los cambios ue estauo que estos piovocan y las ieacciones ue los mismos. Lo excepcional ue
este mecanismo, es que los objetos que se comunican ue esta foima, no iequieien conoceise
mutuamente. Paia ello Q0bject la clase base ue gian paite ue las clases que confoiman Qt,
incoipoia un mtouo llamauo +&11"+#, que se encaiga ue establecei esa comunicacion entie los
uos objetos.
Touo objeto ueiivauo ue Q0bject pueue poseei uos tipos ue funciones piopias
especiales:
:4R2?B:.- funciones que peimiten emitii una seal cuanuo hay algn cambio ue estauo en el
objeto al que peitenecen.
:B89:.- funciones que son el final ue la conexion, y que ejecutan una seiie ue acciones una vez
ieciben el mensaje ue la seal.

Como se pueue vei en el gifico supeiioi, una seal pueue conectaise a ms ue un slot,
paia llevai a cabo uifeientes activiuaues. Tambin vaiios seales uifeientes pueuen conectaise
con un mismo slot, y tenuiiamos una activiuau que pueue sei uesataua ue vaiias foimas
uifeientes.
veamos como es la fiima uel mtouo connect:
bool QObject::connect ( const QObject *sender, SIGNAL(*signal), const QObject *receiver, SLOT(*slot) )

0samos las macios SIuNAL y SL0T paia envolvei a las funciones signal y slot con los
tipos ue sus paimetios.
!'


Pongamos un ejemplo, claio. La clase QApplication, tiene un slot llamauo quit() que
simplemente hace que la aplicacion se cieiie y teimine. Poi otio lauo la clase QPushButton, que
siive paia implementai botones en el inteifaz gifico, posee una signal llamaua clickeu(), que es
emitiua cuanuo el estauo uel boton cambia al sei pulsauo poi el usuaiio. Asi que pouiiamos cieai
una conexion entie el boton y la aplicacion que conecten la seal clickeu() uel boton, con el slot
quit() ue la aplicacion, y en consecuencia una vez estableciua tal conexion, al pulsai el boton, eso
haiia que la aplicacion se ceiiai y teiminai.
#include <QApplication>
#include <QObject>
#include <QPushButton>

int main(int argc, char **argv){
QApplication a(argc,argv);

QPushButton button("Salir");
button.show();
QObject::connect(&button,SIGNAL(clicked()),&a,SLOT(quit()));

return a.exec();
}

Bien, las piopieuaues ue una funcion slot son las siguientes:
- Es implementaua como una funcion oiuinaiia.
- Pueue sei llamaua como una funcion oiuinaiia.
- 0n slot pueue sei ueclaiauo en la zona piivate, piotecteu o public ue una clase, peio eso
solo le afectai si es llamaua como funcion, no como slot. Como slot siempie poui sei
conectaua con objetos ue otia clase inuepenuientemente ue la zona uonue se haya
uefiniuo en su clase. Y se ueclaia en la seccion con la palabia slots.
- Como funcion pueue uevolvei un valoi ue ietoino, peio nunca en conexiones, solo
cuanuo es llamaua como funcion.
- Cualquiei nmeio ue seales pueue sei conectauas a un mismo slot.


Las piopieuaues ue una seal son las siguientes:
- 0na seal es ueclaiaua en la seccion con la palabia signals.
- 0na seal es una funcion que siempie ietoina voiu.
- 0na seal nunca pueue sei implementaua, el moc se encaiga ue haceilo
automticamente.
- 0na seal pueue sei conectaua a cualquiei nmeio ue slots a la vez.
- Es como una llamaua uiiecta, y poi tanto es seguia tanto en llamauas entie thieaus
(hilos) como entie sockets (ieu).
- Los slots son activauos poi las seales en oiuen aibitiaiio.
- 0na seal es emitiua uesue cualquiei paite uel couigo ue la clase poi la palabia emit
(emit nombie_signal(paiams); ).

Es impoitante tenei en cuenta las fiimas ue las seales y los slots que son conectauos, ya
que como iegla Qt no peimite cieai, ni conveitii valoies entie los paimetios, poi lo que no se
pueue conectai cualquiei seal con cualquiei slot, si no entie compatibles entie si, confoime a la
citaua iegla.
Ponuiemos ejemplos ue compatibiliuau:
rangeChanged(int, int) ---------------------------> setRange(int, int)
rangeChanged(int, int) ---------------------------> setValue(int)
rangeChanged(int, int) ---------------------------> updateDialog()

!(


Y ahoia ue incompatibiliuau:
clicked()---------------------------> setValue(int)
textChanged(QString) --------> setValue(int)

vamos a vei un ejemplo ue implementacion ue una clase con signals y slots:
// Fichero angleobject.h
class AngleObject : public QObject
{
Q_OBJECT
Q_PROPERTY(real angle READ angle WRITE setAngle NOTIFY angleChanged)

public:
AngleObject(qreal angle, QObject *parent=0);
qreal angle() const;

public slots:
void setAngle(qreal); // los setters son perfectos slots

signals:
void angleChanged(qreal); // declarado en NOTIFY Q_PROPERTY arriba

private:
qreal m_angle;
}

// Parte del fichero angleobject.cpp
void AngleObject::setAngle(qreal angle)
{
if(m_angle == angle) return; // nunca olvides esta parte

m_angle = angle;
emit angleChanged(m_angle);
}

Como pueues vei en la implementacion uel settei, tambin slot, es uonue tenemos que,
piimeiamente paia evitai que se cieen bucles infinitos al conectai signal y slot, ievisanuo si el
valoi que entia ue angle, es nuevo o no, y si no es asi, salii uiiectamente. Si, el valoi es nuevo,
entonces piimeiamente actualizaiemos el estauo uel mismo y finalmente emitiiemos la seal ue
que ha habiuo un cambio en uicho estauo. Esta es la foima en como se implementan seales y
slots en las clases ueiivauas ue Q0bject.
Es muy tipico que uos wiugets estn conectauos entie si, ue maneia que la seal ue uno
este conectauo con el slot uel otio. vamos a vei un ejemplo completo ue un conveitiuoi ue
tempeiatuias ue giauos Celsius a Fahienheit y viceveisa.
vamos a apiovechai este uesaiiollo paia usai touo lo apienuiuo hasta el momento, y ue
esta maneia ii avanzanuo en el uesaiiollo ue aplicaciones Qt con inteifaz gifico.

782V6A:8A 36 96PN6A?9IA?:
vamos a abiii un nuevo pioyecto en el Qt Cieatoi, ue nuevo un Empty Pioject (un
pioyecto vacio), y le vamos a llamai "tempconveitei". Con ello ya tenemos la caipeta
tempconveitei cieaua, contenienuo el ficheio uel pioyecto que el Cieatoi ha geneiauo l solo.
Ahoia vamos a aauii un ficheio fuente main.cpp, hacienuo clic ueiecho sobie la caipeta,
eligienuo Auu New. , luego C++ -> C++ Souice File en la ventana emeigente. Ponemos main.cpp
en Name.
"*


Ahoia cieamos Nuevo, y esta vez elegimos C++ -> C++ Class. Como class name le
ponemos "TempConveitei", y como Base class ponemos Q0bject. Le uamos a continue, y uone y
se nos han cieauo los ficheios tempconveitei.h y tempconveitei.cpp con paite ue couigo
geneiauo automticamente.
vamos a vei en piimei lugai el couigo que uesciibe la clase y sus miembios en el ficheio
cabeceia coiiesponuiente.
#ifndef TEMPCONVERTER_H
#define TEMPCONVERTER_H

#include <QObject>

class TempConverter : public QObject
{
Q_OBJECT
public:
TempConverter(int tempCelsius, QObject *parent = 0);

// funciones getter
int tempCelsius() const;
int tempFahrenheit() const;

signals:
void tempCelsiusChanged(int);
void tempFahrenheitChanged(int);

public slots: // funciones setter y slots
void setTempCelsius(int);
void setTempFahrenheit(int);

private:
int m_tempCelsius;
};
#endif // TEMPCONVERTER_H

Es suficiente con usai una sola vaiiable como uesciiptoia uel estauo ue la tempeiatuia,
ya que la tempeiatuia es una, se esciiba en un sistema o en otio, solo cambiai el valoi ue nmeio
que la iepiesenta. Tomamos poi tanto la escala Celsius como la piincipal. Sin embaigo vamos a
usai ue uos funciones settei, paia que sea una ue ellas la que haga el cambio. Poi ejemplo
setTempFahienheit, sei la que haga el cambio a Celsius, paia guaiuai.
Puesto que ambos uiales estn inteiconectauos entie si, es uecii, si cambia uno,
inmeuiatamente uebe cambiai el otio y viceveisa, paia evitai caei en un bucle infinito, tenemos
que cuiuai en el settei ponei antes ue naua el couigo que ievise el cambio ue estauo. Como el
estauo lo hemos uefiniuo en Celsius, vamos a hacei esto en el slot setTempCelsius.
El couigo fuente ue la implementacion ue esta clase queuai ue esta foima.
#include "tempconverter.h"

TempConverter::TempConverter(QObject *parent) :
QObject(parent)
{
m_tempCelsius = 0;
}

int TempConverter::tempCelsius()
{
return m_tempCelsius;
}

int TempConverter::tempFahrenheit()
{
int tempFahrenheit = (9.0/5.0)*m_tempCelsius+32;
return tempFahrenheit;
}

void TempConverter::setTempCelsius(int tempCelsius)
{
if(m_tempCelsius == tempCelsius) return; // cortamos el bucle
")



m_tempCelsius = tempCelsius; // actualizamos el nuevo estado
// emitimos las dos se_ales del cambio ocurrido

emit tempCelsiusChanged(m_tempCelsius);
emit tempFahrenheitChanged(tempFahrenheit());
}
void TempConverter::setTempFahrenheit(int tempFahrenheit)
{
int tempCelsius = (5.0/9.0)*(tempFahrenheit-32);
setTempCelsius(tempCelsius);
}

La clase TempConveitei que acabamos ue uefinii va a sei la encaigaua ue conveitii los
valoies ue Celsius a Fahienheit y viceveisa. Peio vamos a uefinii ahoia el inteifaz con los wiugets
que van a peimitii cambiai la tempeiatuia meuiante unos uiales, y mostiaila meuiante unos LCB
numbeis. Como an no hemos estuuiauo las ventanas ue uilogo con wiugets y layouts, vamos
simplemente a uefinii el couigo ue las conexiones implicauas, y cuanuo lleguemos al tema 14,
entonces apiovechaiemos paia hacei el inteifaz gifico ue este ejemplo.
Bien, queiemos que cuanuo giiemos los uiales, automticamente se cambie la
tempeiatuia ue ambos LCB caua uno con sus valoies ue acueiuo a su escala ue tempeiatuias, y
que ambos uiales giien el uno poi accion uel otio.
Bueno pues vamos a vei, cuales son las seales y slots que vamos a usai en caua
elemento gifico:
El uial Celsius (celsiusBial) => Seal -> valueChangeu(int) ; Slot -> setvalue(int)
El uial Fahienheit (fahienheitBial) => Seal -> valueChangeu(int) ; Slot -> setvalue(int)
El LCB Celsius (celsiusLcu) => Slot -> uisplay(int)
El LCB Fahienheit (fahienheitLcu) => Slot -> uisplay(int)
La foima en como se conectaiian estos 4 wiugets gifico con la clase conveisoia
TempConveitei, seiia como vemos en el gifico.

"!


La accion comenzaiia al giiai uno ue los uiales, supongamos poi ejemplo, el ue los
giauos Celsius. Esto uispaiaiia la seal ue celsiusBial, valueChangeu(int), que iiia a 2 sitios. Al
celsiusLCB uiiectamente meuiante su slot uisplay(int), y a TempConveitei, a su slot
setTempCelsius(int). Como pouemos vei en el couigo, ste ultimo slot emite las 2 seales
tempCelsiusChangeu(int) y tempFahienheitChangeu(int), caua una conectaua con los slots
coiiesponuientes ue celsiusBial y fahienheitBial, setvalue(int) en ambos casos. Be esa maneia,
tenemos touo peifectamente inteiconectauo. vamos poi tanto a vei el couigo que implementaiia
esas conexiones.
connect(celsiusDial,SIGNAL(valueChanged(int)),tempConverter,SLOT(setTempCelsius(int));
connect(celsiusDial, SIGNAL(valueChanged(int)), celsiusLcd, SLOT(display(int));
connect(tempConverter,SIGNAL(tempCelsiusChanged(int)),celsiusDial,SLOT(setValue(int));

connect(fahrenheitDial,SIGNAL(valueChanged(int)),tempConverter,SLOT(setTempFahrenheit(
int));
connect(fahrenheitDial, SIGNAL(valueChanged(int)), fahrenheitLcd, SLOT(display(int));
connect(tempConverter,SIGNAL(tempFahrenheitChanged(int)),fahrenheitDial,SLOT(setValue(
int));





















""


)%/" [
(+4R2?B/?NN6A

0na vez hemos visto como funciona el sistema ue conexiones entie objetos en Qt
meuiante seales y slots, vamos ahoia a planteainos un pioblema ms complejo ue afiontai
meuiante este esquema ue tiabajo.
Es muy noimal, que en algunos casos, nos lleguemos a planteai el enviai un valoi junto
con la seal, sin embaigo esto no es posible. Poi ejemplo, supongamos que tenemos un conjunto
ue teclas iepiesentanuo los nmeios uel u al 9, como un maicauoi telefonico, o los numeiales ue
una calculauoia. Nos gustaiia sin uuua el pouei enviai junto con la seal uel clickeu() el valoi ue
la tecla pulsaua.
Claio una foima ue implementai este caso, seiia cieai 1u slots paia caua tecla, peio eso
supone iepetii casi el mismo couigo uiez veces, y si alguna vez nos planteamos hacei algn
cambio, tenuiemos que estai atentos en haceilo en 1u sitios uifeientes.
Bien, paia estos casos existe una clase muy til llamaua QSignalNappei. Si buscas
infoimacion ue la misma en el asistente, veis que es bastante sencilla en cuanto a miembios,
slots y signals, sin embaigo, como inteimeuiaiia ue un sistema ue tiansmision ue seales uonue
necesitamos enviai ue alguna maneia tambin un valoi junto con la seal, es muy inteiesante.
QSignalMapper *m = QSignalMapper(this);
QPushButton *b;

b=new QPushButton("1");
connect(b, SIGNAL(clicked()), m, SLOT(map());
m->setMapping(b,1);

b=new QPushButton("2");
connect(b, SIGNAL(clicked()), m, SLOT(map());
m->setMapping(b,2);
................

connect(m, SIGNAL(mapped(int)), this, SLOT(keyPressed(int)));

vamos conectanuo caua boton meuiante la seal clickeu() al slot map() uel
QSignalNappei. Neuiante el mtouo setNapping lo que hacemos es vinculai al objeto uel que
iecibe la seal el QSignalNappei, y que una vez, ieciba la seal en el slot map(), ste geneiai
una seal mappeu(int) que lleva el valoi enteio asignauo con setNapping a uicho objeto. Como
vemos en el ltimo connect, conectamos uicha seal mappeu(int) con el slot keyPiesseu(int) que
pouemos ya ieuefiniilo paia llevai a cabo las acciones que queiamos, ue acueiuo al boton
pulsauo. El gifico infeiioi, iepiesentaiia las ielaciones implicauas en este mtouo ue conectai
elementos.



"#































"$


)%/" i
/"&%f- '% 7"'%&"+ %& (9

Antes ue seguii con la piogiamacion gifica (u0I), veo muy impoitante el conocei toua
una seiie ue elementos funuamentales que usaiemos en los piogiamas con entoino gifico, y que
nos peimitiin hacei aplicaciones tiles. Nuchos libios ue Qt, enfocan siempie solo el aspecto
gifico, e incoipoian estos elementos junto con aquellos, ue maneia que a veces pueuen agobiai
al que empieza, con multituu ue conceptos, poi ello aqui he piefeiiuo sepaiai ambos aspectos
completamente, y poi tanto incluso los ejemplos que vamos a usai, van a ii uespiovistos ue u0I,
y su saliua sei en la consola.
Ya hemos visto en el tema 4, el ejemplo ue Bola Nunuo con saliua a consola, poi lo que
usaiemos qBebug(), paia nuestios ejemplos.
Qt es un Fiamewoik, cuya piincipal motivacion es la ue que usanuo el mismo couigo,
pouamos compilailo en uifeientes platafoimas sin tenei que hacei cambios. Poi ello, ha teniuo
que abstiaei muchos ue los tipos que ya existian en C++STL paia haceilo completamente
multiplatafoima. Asi ocuiie con el tiatamiento ue cauenas, en el que stu::stiing ha siuo mejoiauo,
aauinuole capaciuau ue iepiesentai caiacteies unicote (chino, hebieo, iabe, etc), y ue esta
maneia inteinacionalizai el mbito aplicable uel tiatamiento ue cauenas. Esto se ha hecho,
cieanuo una clase llamaua (+9A42R. Si la buscas en el Qt Assistant pouis vei touas las
posibiliuaues que esta clase nos biinua paia el manejo ue cauenas que en C, siempie fue
complicauo, fiente a otios lenguajes ue piogiamacion. Asi, QStiing sopoita las conveisiones a
otios sistemas (QStiing::toAscii, QStiing::toLatin1 . ), peimite la iepiesentacion en unicoue ue
picticamente la totaliuau ue sistemas ue esciituia actuales y tambin peimite mtouos ue
inspeccion y manipulacion ue cauenas ue texto.

782:9AI554C2 36 5?362?:
Bay ties mtouos paia constiuii cauenas poi concatenacion:
1.- Neuiante el opeiauoi +
QString res = "Hola " + "amigos ";

2.- Neuiante el opeiauoi ue QStiingBuiluei
#include <QStringBuilder>
..............
QString str = "Hola " % "amigos";

S.- Neuiante el mtouo aig ue QStiing
QString str = QString("Hola %1, tengo %2 aos").arg("amigos").arg(42);

El mtouo 1, es mejoi que el 2 si se va a componei la cauena en muchas veces, con
muchas asignaciones. El mtouo S peimite foimateai la cauena, y uejai los huecos que luego
sein iellenauos poi oiuen, poi el mtouo aig que peimite intiouucii tanto cauenas como
nmeios.


"%


+IH5?362?:
vamos a vei una seiie ue mtouos paia tiatai subcauenas uentio ue cauenas ms
gianues.
Funciones left, iight, miu, ieplace:
QString str = "Hola mundo";
str.left(4); // "Hola"
str.right(5); // "mundo"
str.mid(3,5); // "a mun"
str.replace("mundo","tronco"); // Hola tronco


S'6HIRWX K (+9A42R W:?B43?: N8A 582:8B?X
qBebug se usa paia sacai mensajes poi consola. Incluiuo en la clase QBebug, tiene
uifeientes foimas ue tiabajai.
Como piintf() en C peio aauienuo un ietoino ue caiio "n". Paia impiimii un QStiing antes
uebe sei pasauo poi la funcion qPiintable incluiua en Qtulobal (no iequieie poi tanto incluii
ninguna cabeceia paia su uso):
QString str = "Antonio";
qDebug("Hola me llamo %s, y tengo %d aos",qPrintable(str),42);

Tambin pouemos usailo como un stieam, como stu::cout ue C++STL:
qDebug() << "Hola me llamo " << str << ", y tengo " << 42 << " aos";


&jP6A8: K 5?362?:
Conveitii un nmeio en una cauena:
QString years = QString::number(42); // "42"

Conveitii ue cauena a nmeio:
bool ok;
years.toInt(&ok); // ok = true si lo convirti bien

Tambin existe toBouble(), toFloat(), etc.


+)< K (+9A42R

Si usamos una libieiia cieaua con las STL, y queiemos hacei un inteifaz con ella, paia
iecibii cauenas ue ella, o enviaile cauenas hacia ella, entonces tenuiemos que auaptai la cauena
paia que touo funcione bien. Paia ello existen unas funciones que vamos a vei.
std::string str = "Hola mundo";
QString qstr = QString::fromStdString(str);

QString qstr = "Hola mundo";
std::string str = QString::fromStdString(qstr);

Se supone que sti est en ASCII.
"&


7?362?: V?5k?: K 5?362?: 2IB?:
Becimos que una cauena es nula, si no est apuntanuo a ninguna cauena, y uecimos que
est vacia si no contiene ningn caictei.
Queuai aclaiauo con este ejemplo:
QString str = QString; // str no esta apuntando a nada
str.isNull(); // true
str.isEmpty(); // true

QString str = ""; // str esta apuntando a un espacio vaco
str.isNull(); // false
str.isEmpty(); // true


$8PN6A K I24A 5?362?:
Ntouos split y join.
QString str = "Madrid - Barcelona - Bilbao - Sevilla";
QStringList ciudades = str.split(" - "); /* ciudades = {Madrid, Barcelona, Bilbao,
Sevilla} */
QString new_str = ciudades.join(", "); // "Madrid, Barcelona, Bilbao, Sevilla"

QStiingList es un conteneuoi, similai a una aiiay ue cauenas, que vamos a vei ahoia.

(+9A42R<4:9
Es una clase especializaua en contenei QStiings en un contenei tipo lista (QList). En
iealiuau es una QList<QStiing>.
Esta lista pueue sei iellenaua usanuo el opeiauoi << como en un stieam.
QStringList verbos;
verbos = "correr" << "comer" << "coser"; // {correr, comer, coser}

QStiingList posee mtouos paia tiatai, touas las cauenas que lleva consigo, que son muy
inteiesantes:
verbos.replaceInStrings("er","iendo"); // {corriendo, comiendo, cosiendo}
verbos.sort(); // {comer, correr, coser}
verbos.filter("m"); // {comer}
verbos << "comer"; // {comer, comer}
verbos.removeDuplicates(); // {comer}


096A?238 :8HA6 (+9A42R<4:9
Pouemos moveinos poi una QStiingList usanuo el opeiauoi |j con ayuua ue lenght()
paia no sobiepasai sus uimensiones, o con la piopieuau ue solo lectuia at().
QStringList verbos;
verbos = "correr" << "comer" << "coser"; // {correr, comer, coser}
for(int i; i < verbos.length(); i++){
qDebug() << verbos[i]; // verbos.at(i);
}

"'


Peio la foima ms comoua y seguia ue iecoiiei una QStiingList es con foieach, incluiuo
en Qtulobal poi uefecto.
foreach(const QString &verbo, verbos){
qDebug() << verbo;
}

0samos una iefeiencia const paia optimizai el ienuimiento uel bucle, pasanuo solo una
iefeiencia.
Foieach siempie tiene la misma foima, a la ueiecha como segunuo paimetio esta una
coleccion ue elementos ue un ueteiminauo tipo, y a la izquieiua como piimei paimetio,
ponemos una vaiiable uel tipo ue los elementos, que es la vaiiable que va a ii iecogienuo los
valoies iecoiiiuos ue la coleccion, uesue el piimeio hasta el ltimo.
Bien, en el pioximo tema vamos a vei las colecciones en Qt. Es conveniente que piuebes
el couigo que hemos iuo vienuo en este tema, incluynuolo en el esqueleto ue una aplicacion ue
consola usanuo qBebug().




















"(


)%/" ;l
7-<%770-&%+ %& (9

Las colecciones en Qt estn funuamentauas sobie las mismas ue STL, peio
llevauas a una implementacion multiplatafoima. vamos a ii vinuolas una a una.

(<4:9`)a
Es una lista, como las ue STL, y la foima ue iellenaila es igual. vamos a vei
unos ejemplos sencillos.
QList<int> pares;
pares << 2 << 4 << 6;
pares.prepend(0); // 0,2,4,6
pares.append(10); // 0,2,4,6,10
pares.insert(4,8); // 0,2,4,6,8,10
pares.removeFirst(); // 2,4,6,8,10
pares.removeLast(); // 2,4,6,8
pares.removeAt(2); // 2,4,8
pares.removeAll(); // nada

Con takeAt(), takeFiist(), takeLast(), nos uevuelve el elemento en si y auems lo boiia ue
la lista, ue maneia que si tenemos una lista ue objetos, pues nos uevolveiia la iefeiencia a uicho
objeto.
Pouemos acceuei a sus elementos meuiante el opeiauoi |j, y la funcion value().
Paia iteiai una lista usamos (<4:9096A?98A`)a. Que tiene funciones como hasNext()
paia aseguiaise que no hemos llegauo al final.

QListIterator<int> i(pares);
while (i.hasNext()){
qDebug("Numero par: %d",i.next());
}

Tambin pouemos usai /&4"$+2 paia iteiai toua la lista completa:
foreach(const int &valor, pares){
qDebug("Numero par: %d",valor);
}

0tias alteinativas similaies a QList, son QLinkeuList que implementa una lista vinculaua,
y Qvectoi que es una coleccion vectoi como las ue STL. Los mtouos usauos son los mismos que
QList. Bepenuienuo uel uso que les vayamos a hacei, usaiemos una lista, una lista vinculaua o un
vectoi.


#*


#4B?: 582 (+9?5m
QStack<int> pila;
pila.push(1);
pila.push(2);
pila.push(3);
qDebug("Top: %d",pila.top()); // 3
qDebug("Top: %d",pila.pop()); // 3
qDebug("Top: %d",pila.pop()); // 2
qDebug("Top: %d",pila.pop()); // 1
pila.isEmpty(); // true

78B?: 582 ((I6I6
QQueue<int> cola;
cola.enqueue(1);
cola.enqueue (2);
cola.enqueue (3);
qDebug("Top: %d",cola.head()); // 1
qDebug("Top: %d",cola.dequeue()); // 1
qDebug("Top: %d",cola.dequeue()); // 2
qDebug("Top: %d",cola.dequeue()); // 3
pila.isEmpty(); // true

782@I298: 582 (+69
Los conjuntos o sets, tambin pouemos asimilailos a los Set ue STL. vamos a vei un poco
ue couigo paia asimilailos.
QSet<int> conjunto;
conjunto << 1 << 3 << 7 << 9;
conjunto.contains(8); // false
conjunto.contains(3); // true
conjunto.remove(8); // false y no borra nada
conjunto.remove(3); // true y borra el 3

Pouemos tambin conveitii una lista en un conjunto y viceveisa:
QList<int> pares;
pares << 2 << 2 << 4 << 4 << 8; // 2,2,4,4,8
QSet<int> conjunto = pares.toSet(); // 2,4,8
QList<int> pares_no_repes = conjunto.toList();

Si hubiiamos queiiuo conseivai los elementos iepetiuos en el conjunto, hubiiamos
teniuo que usai un QNultiSet.

(/?N`m6K)U)a K (,?:T`m6K)U)a
Se tiata ue paies key => value, como en las STL (o las matiices ue PBP), uonue una key
se coiiesponue con un nico value. Paia intiouucii elementos se hace ue la siguiente maneia:
QMap<QString,int> edades;
edades["Antonio"] = 42;
edades["Maria"] = 42;
edades["Pablo"] = 8;

La funcion key() iecoge el valoi uel piimei elemento, keys() uevuelve una QList<keyT>
con touas las keys, y value(key) uevuelve el valoi asociauo con un key en paiticulai. veamos
ejemplos:
foreach(const QString &key, edades.keys()){
qDebug("Nombre: %s",qPrintable(key));
}

#)


Con la funcion contains(key), pouemos vei si una ueteiminaua key esta en la coleccion.
if(edades.contains("Pablo")){
qDebug("Pablo tiene %d", edades.value("Pablo"));
}

QBash es lo mismo que QNap, solo que la key se pasa poi una funcion hash, paia
conveitiila en un valoi uint (unsigneu int), la cual peimite mayoi ienuimiento a la coleccion.
Bicha funcion hash, ha ue escogeise ue maneia que no se iepita ningn valoi uint que uificulte su
ienuimiento. Paia ello el tipo ue key, uebe ue pioveei ue 2 mtouos: uint qBash (tipoKey), y bool
opeiatoi== (key1, key2). Si asi se hace ue maneia optima, QBash<keyT,T> uai mejoi
ienuimiento en touas las opeiaciones que QNap<keyT,T>. veamos un ejemplo ue
implementacion ue estas funciones, como miembios ue una clase hipottica Peisona, que tiene
uos miembios bsicos llamauos euau() y nombie().
uint Persona::qHash (const Persona &p)
{
return p.edad() + qHash(p.nombre());
}
bool Persona::operator== (const Persona &p1, const Persona &p2)
{
return (p1.edad() == p2.nombre()) && (p1.nombre() == p2.nombre());
}

Con esto ya pouiiamos cieai un QBash<Peison,int>, que tiabaje ue foima optima.
Paia finalizai, existen las veisiones 6783#07$5 y 6783#09$'2, paia cuanuo una misma
key, pueue tenei asociauos vaiios valoies a la vez. En estos casos, no se pueue usai el opeiauoi |j
paia intiouucii nuevos uatos, y se utiliza inseit(). Si se quieie iecogei el valoi key una sola vez,
se usa la funcion uniqueKeys(). veamos un ejemplo paia ilustiailo.
QMultiMap<QString,QString> lang;
lang.insert("Antonio", "C/C++");
lang.insert("Antonio", "Java");
lang.insert("Antonio", "PHP");
lang.insert("Antonio", "Erlang");

foreach(const QString &nombre, lang.uniqueKeys()){
QStringList program_lang = lang.values(nombre);
// {C/C++, Java, PHP, Erlang} solo pasa una vez el bucle
}











#!































#"


)%/" ;;
)0#-+ (9

Como en el tema anteiioi hemos visto, uebiuo a que el pioposito ue Qt es pouei sei
multiplatafoima sin tenei que mouificai el couigo, otia cosa que hubo que mouificai son los tipos
como los enteios, que uepenuen uel sistema opeiativo, y ue la CP0.
Asi los tipos queuan fijauos ue esta maneia en Qtulobal:
qint8 ------> 8 bits enteio
qint16 ------> 16 bits enteio
qintS2 ------> S2 bits enteio
qint64 ------> 64 bits enteio
quint8 ------> 8 bits enteio sin signo
quint16 ------> 16 bits enteio sin signo
quintS2 ------> S2 bits enteio sin signo
quint64 ------> 64 bits enteio sin signo
qieal ------> uouble

(n?A4?29
Es un tipo que pueue guaiuai un tipo cualquieia. Si necesitamos sei capaces ue uevolvei
cualquiei tipo, a tiavs ue un inteiface Qvaiiant nos pueue ayuuai, y finamente pouemos
conveitiilo a su tipo final meuiante las funciones uel tipo toTipo() (ej. toInt(), toFloat()). veamos
un ejemplo.
QVariant var(5);
int i;
i=var.toInt(); // 5


7?:942R 342YP458
Paia hacei casting uinmico entie clases, peio sin iequeiii el uso uel RTTI uel
compilauoi, en Qt existe el opeiauoi en Qtulobal llamauo :&)*"+#;+$'#01<.
Si no tenemos claio, si el casting se va a iesolvei bien, entonces usaiemos este tipo ue
casting, ya que ue no iesolveise bien, uevolvei un punteio nulo.
QObject *obj = new QTimer; // QTimer hereda de QObject

QTimer *timer = qobject_cast<QTimer *>(obj);
// timer == (QObject *)obj

QAbstractButton *button = qobject_cast<QAbstractButton *>(obj);
// button == 0


##































#$


)%/" ;G
+0+)%/"+ '% ]07,%$-+

0tio ue los sitios uonue est muy justificauo el uso ue un sistema inuepenuiente ue la
platafoima es en los accesos a sistemas ue ficheios, ya que en caua opeiativo, esto es uifeiente.
Be esta maneia suige una seiie ue clases en Qt que nos ayuuan a abstiaeinos ue uichas
paiticulaiiuaues.

('4A
Esta clase nos piovee uel manejo uel sistema ue ficheios ue maneia tianspaiente. Los
uiiectoiios ms tipicos estn uefiniuos como mtouos estticos.
QDir dir = QDir::current(); // directorio actual
QDir dir = QDir::home(); // /home
QDir dir = QDir::temp(); // directorio temporal
QDir dir = QDir::root(); // directorio raiz
QDir dir = QDir(QApplication::applicationDirPath());
// directorio de la aplicacion

QFileInfo es una clase que pueue contenei toua la infoimacion iefeiente a un ficheio
(nombie, path, peimisos, etc). QFileInfoList es una QList<QFileInfo>. 0na funcion muy impoiante
ue QBii es entiyInfoList() que uevuelve toua lista ue un uiiectoiio (es como un uii o un ls).
veamos un ejemplo ue como listai un uiiectoiio.
QFileInfoList infos = QDir::root().entryInfoList();
foreach(const QFileInfo &info, infos){
qDebug("%s",qPrintable(info.fileName()));
}

Se pouiia hacei un filtiauo ue uicho listauo usanuo los siguientes filtios, puestos y
combinauos con 0R (|) como piimei paimetio ue entiyInfoList(filtei,soit):
QBii::Biis uiiectoiios
QBii:: Files ficheios
QBii::NoSymLinks no vinculos
QBii::Reauable con piemiso ue lectuia
QBii::Wiiteable con peimiso ue esciituia
QBii::Executable con peimiso ue ejecucion
QBii::Biuuen ficheios ocultos
QBii::System ficheios ue sistema
El oiuen ue listauo se pueue enviai como segunuo paimetio y estos son los filtios ue
oiuenacion:
QBii::Name poi nombie
QBii::Type poi tipo (extension)
QBii::Size poi tamao
#%


QBii::Time poi fecha ue cieacion
QBii::BiisFiist uiiectoiios piimeio
QBii::BiisLast uiiectoiios lo ltimo
QBii::Reveiseu en oiuen inveiso
EntiyInfoList tambin tiene un constiuctoi uonue uelante ue estos paimetios vistos
antes, se le pueue aauii un paimetio que iiia antes ue que estos con una QStiingList con filtios
wilucaiu (uel tipo *.h, *.cpp, etc). veamos un ejemplo:
QFileInfoList infos = QDir::root().entryInfoList(QStringList << "*.h" <<
"*.cpp",QDir::Files,QDir::Name);
foreach(const QFileInfo &info, infos){
qDebug("%s",qPrintable(info.fileName()));
}

Las uistintas paites uel path ue un ficheio estn gificamente ielatauas en el siguiente
gifico.















#&


)%/" ;F
%+7$0)\$" . <%7)\$" '% ]07,%$-+

Paia la lectuia y esciituia en ficheios, tenemos que al menos implicai S clases uifeientes,
tanto en el caso ue que sea un ficheio binaiio, como si es ue texto. Bien vamos a vei caua una ue
esas clases, y la maneia en que se ielacionan en el pioceso ue lectuia y esciituia.
La clase 6=03" que ueiiva ue 6>(?"@0+", es la que se usa paia la opeiacion ue apeituia,
esciituia, lectuia y cieiie uel aichivo. Los flags que iepiesentan los uifeientes mouos ue acceso al
ficheio estn uefiniuos como un enum en QI0Bevice, y son los siguientes:
QIODevice::ReadOnly abierto para lectura
QIODevice::WriteOnly abierto para escritura
QIODevice::ReadWrite abierto para lectura y escritura
QIODevice::Append abierto para aadir al final del fichero
QIODevice::Text cuando lee los enter los pasa a \n y cuando escribe,
los enter los pasa al sistema local


Be la clase QI0Bevice vamos a usai meiamente los mouos ue acceso a los ficheios, y ue
la clase QFile, vamos a usai los mtouos open() paia la apeituia uel ficheio, close() paia el cieiie,
wiite() paia la esciituia en el mismo, y ieau() y similaies paia la lectuia. Tambin vamos a usai
mtouos como atEnu() paia ieconocei el E0F (final uel ficheio), o seek() paia situainos en una
posicion concieta uel ficheio. veamos un ejemplo ue lectuia:



QFile f("fichero.txt");

if(!f.open(QIODevice::ReadOnly))
qFatal("No puedo abrir el fichero para lectura.");

while(!f.atEnd()){
QByteArray data = f.read(1024);
// Aqui puedes usar los datos leidos
}

f.close();


Esto mismo pueue sei hecho ue una maneia ms intuitiva usanuo stieams. Las clases
inteiface, que se encaigan ue cieai un stieam con los uatos que pioceuen o van al ficheio en
nuestio caso, aunque tambin se pueue usai con cualquiei otio uispositivo. Estas clases son
6A"B#C#4"$! paia flujos ue texto, y 6?$#$C#4"$! paia flujos ue uatos binaiios. Be estas clases
vamos a usai solamente el constiuctoi, inuicanuo como paimetio el uispositivo ue
entiauasaliua.
veamos un ejemplo ue lectuia ue ficheio ue texto usanuo un stieam:
QFile f("fichero.txt");
QTextStream in(&f);

if(!f.open(QIODevice::ReadOnly)
qFatal("No puedo abrir el fichero para lectura.");
while(!in.atEnd()){
qDebug("%s",qPrintable(in.readLine()));
}
f.close();



#'


veamos ahoia un ejemplo ue esciituia ue ficheio ue texto:
QFile f("fichero.txt");
QTextStream out(&f);

if(!f.open(QIODevice::WriteOnly | QIODevice::Append)
qFatal("No puedo abrir el fichero para escritura.");
out << "Esto es un fichero de texto" << str << endl;
f.close();

En el caso ue leei o esciibii uatos, uebemos uecii al compilauoi ue Qt la veision que
estamos usanuo uel mismo, ya que es posible que en uifeientes veisiones, la implementacion uel
uatastieam sea uifeiente. veamos un ejemplo ue esciituia.
QFile f("fichero.bin");
QDataStream out(&f);

out.setVersion(QDataStream::Qt_4_6);
if(!f.open(QIODevice::WriteOnly)
qFatal("No puedo abrir el fichero para escritura");
out << 0xFFFC;
f.close();


+9A6?P: K )4N8:
Se pueue seiializai a un ficheio una clase cualquiei cieaua poi nosotios, simplemente si
en la misma implementamos los opeiauoies << y >>. vamos a vei un ejemplo ue nuevo con la
clase Peisona y sus miembios euau() y nombie().
QDataStream Persona::&operator<< (QDataStream &out, const Persona &p)
{
out << p.nombre();
out << p.edad();
return out;
}

QDataStream Persona::&operator>> (QDataStream &in, const Persona &p)
{
QString nombre;
int edad;
in >> nombre;
in >> edad;
p = Persona(nombre, edad);
return in;
}









#(


)%/" ;*
D0'^%)+ . <".-\)+

Los piimeios temas, uel 1 al 1S, contenian los piincipios bsicos que uifeiencian a la
piogiamacion C++STL ue la piogiamacion C++Qt. Es funuamental que tenga touos esos
conceptos claios, y que haya hecho touos los ejemplos, y ejeicicios posibles paia afianzailos bien.
Si esto no es asi, es el momento ue que se paie, y vuelva sobie los 1S temas que acabamos ue
pasai.
Besue el tema actual, hasta el tema 2u incluiuo, vamos a vei los conceptos bsicos y
touas las heiiamientas necesaiias paia uesaiiollai un inteifaz gifico completo. Es funuamental
poi tanto que tiate este bloque ue temas como un touo, y que se ejeicite en ellos antes ue seguii
auelante. Besue el tema 21 en auelante, ya se tiatan paiticulaiiuaues y ampliaciones, que con una
base soliua en los 2 bloques anteiioies (1 al 1S y 14 al 2u), poui avanzai poi ellos ue maneia
seguia y fiable.
0n inteifaz gifico muestia al usuaiio ventanas con elementos gificos con los que
pueue inteiactuai, seleccionanuo opciones, intiouucienuo texto, pulsanuo en botones, etc. Toua
aplicacion tiene una ventana piincipal, que es la que se abie al piincipio y se mantiene hasta el
final, cuanuo el usuaiio ueciue ceiiai la aplicacion. A paite, pueuen habei ventanas ue Bilogo,
que se supeipongan a la piincipal en el momento en que piuen alguna accion poi paite uel
usuaiio. Cualquieia ue estas ventanas, esta compuesta a su vez poi unos elementos gificos
bsicos que uiviuiiemos en 2 tipos: los wiugets y los layouts.
Los wiugets son elementos gificos inteiactivos o no, que se uibujan uentio ue una
ventana ocupanuo un iea iectangulai, como un boton, una etiqueta, un cuauio ue seleccion, etc.
0n Layout es un componente que se usa paia uisponei espacialmente los wiugets uentio ue la
ventana, es uecii, paia oiganizai su posicion en ella. Layouts y wiugets negocian el espacio a
ocupai. En Qt se usan unos wiugets llamauos spaceis (veitical y hoiizontal) que actan como
muelles, empujanuo los wiugets hacia una zona ue la ventana, con touo esto se consigue un
inteifaz elstico, que se auapta a las uimensiones que se quieia uai a la ventana que los contiene,
y es muy eficaz en el caso ue queiei inteinacionalizai un inteifaz, tiauucinuolo a uifeientes
iuiomas, uonue los textos, miuen uifeiente en caua iuioma, y uonue no queiemos que se
tiunquen ni textos, ni gificos.

<8: E43R69:
En el Qt Besignei nos pouemos encontiai ms ue 4S wiugets paia usai, y ceica ue 6u son
ueiivauos ue la clase piincipal 6D0%<"#. Los wiugets estn oiganizauos en categoiias, y una
categoiia impoitante son los wiugets conteneuoies, que pueuen contenei en su inteiioi otios
wiugets, ue maneia que siiven paia oiganizailos, y auems pueuen actuai en su inteiactiviuau,
como poi ejemplo, cuanuo metemos vaiios iauio-buttons (QRauioButton) uentio ue gioup-box
(QuioupBox), conseguimos que al seleccionai uno ue ellos, los uems se ueseleccionen
automticamente, poi lo que se pueue uecii que los wiugets conteneuoies pueuen afectai y
mouificai la inteiactiviuau ue un wiuget conteniuo en l.
0tia piopieuau impoitante ue los wiugets, es que son capaces ue iecibii eventos uesue
los uispositivos ue entiaua (poi ejemplo el iaton). Cuanuo poi causa ue un evento, o poi otia
causa, el estauo uel wiuget es cambiauo, emite una seal notificanuo tal cambio. Los wiugets poi
tanto pueuen conectaise con otios wiugets y objetos, meuiante el mecanismo ue signal-slot que
vimos en los Q0bjects, ya que QWiuget ueiiva ue aqul.


$*


<8: <?K8I9:
Los objetos layout ueiivan ue la clase QLayout. Bay S tipos uifeientes ue layouts:
QBBoxLayout (que oiganiza el espacio que ocupan los wiugets hoiizontalmente), QvBoxLayout (
que oiganiza el espacio que ocupan los wiugets veiticamente) y QuiiuLayout (que oiganiza el
espacio que ocupan los wiugets, sobie un giiu, uiviuienuo el espacio en filas y columnas, y
situanuo a caua wiuget en la celua que le coiiesponua). Los spaceis, iellenan los espacios vacios,
y ue esta maneia, layouts y wiugets, negocian su tamao y el espacio paia cieai un inteifaz
elstico auaptable a touas las situaciones.
0n Layout, pueue contenei en su inteiioi otios Layouts y otios Wiugets. Asi QLayout
posee unas funciones miembio especiales paia aauii estos conteniuos a su inteiioi, y cuanuo
estas funciones son usauas, inmeuiatamente uicho conteniuo pasa a sei hijo ue la clase
conteneuoia. Este mecanismo facilita entonces la tiansmision ue eventos y piopieuaues a lo laigo
ue la jeiaiquia familiai, unuole ms consistencia al inteifaz gifico cieauo poi objetos
continentes y objetos conteniuos. Tambin facilita el mecanismo ue libeiacion ue memoiia que
vimos en el tema 6, evitanuo fugas ue memoiia. veamos las S funciones bsicas paia aauii
elementos a un Layout:
void QBoxLayout::addStretch ( int stretch= 0 )
Aaue un spacei que ocupai poi uefecto como minimo u pixeles, hasta el limite ue su
conteneuoi, empujanuo al wiuget en esa uiieccion (la uel conteneuoi). Solo BoxLayouts
veiticales y hoiizontales (no vale paia uiiuLayouts).
void QLayout::addWidget (QWidget *w)
Aaue un wiuget uentio uel Layout uel tipo que sea ste. Besue ese momento uicho wiuget pasa a
sei hijo uel Layout que lo contiene.
void QLayout::addLayout (QLayout *layout, int stretch = 0 )
Aaue un Layout uentio ue otio (cajas pequeas uentio ue cajas ms gianues). Besue ese
momento uicho layout pasai a sei hijo ue su conteneuoi, y poi heiencia a su vez ue las cosas
que aqul contenga.
Be hecho, en toua ventana gifica, se pueue uibujai un ibol jeiiquico que ieciee las
ielaciones paientales ue touos sus objetos. Poi lo tanto, touo el conteniuo ue una ventana uebe
estai sometiuo jeiiquicamente al objeto que iepiesenta la ventana completa. Asi cuanuo uicha
ventana sea boiiaua ue la memoiia, con ella se boiiain touos sus elementos, evitanuo asi
pioblemas ue memoiy leaks. Es muy habitual poi tanto que los elementos gificos ue una
ventana sean cieauos meuiante new uentio uel constiuctoi uel objeto que hai ue ventana.
Puesto que hay muchos wiugets, y sus piopieuaues son muchas, y sus mtouos son
muchos, no es pioposito ue este libio el veilos touos. Poi tanto, es conveniente que confoime los
vayas necesitanuo, los vayas ievisanuo en el Qt Assistant, y apienuienuo a usai esta
uocumentacion como guia a la piogiamacion. El autoiiellenauo uel Qt Cieatoi, facilita tambin la
laboi ue encontiai fcilmente los elementos ue la piogiamacion que iequeiimos.
vamos poi tanto a continuacion a planteainos la constiuccion ue un cuauio ue uilogo,
piimeio en couigo puio, y luego en el Qt Besignei. Be esta maneia uejaiemos concietaua la
enseanza que pietenuiamos paia este tema, que es el uiseo ue ventanas usanuo Layouts y
Wiugets.




$)


782:9AI554C2 36 I2? V629?2? 36 '4YB8R8 582 5C34R8
vamos a constiuii una ventana ue uilogo que tenga el aspecto ue la foto que mostiamos
a continuacion.

Pouemos obseivai que piimeiamente hay S cajas hoiizontales (iectngulos iojos), que
son conteneuoies Layout que en su inteiioi tienen wiugets o spaceis (stietch). vamos a suponei
que la constiuccion ue touo ello es hecho en el constiuctoi ue la ventana ue uilogo, poi lo que
los contenuoies supeiioies, que son S, tomain como pauie a la ventana y poi tanto usaiemos el
punteio this como aigumento ue los constiuctoies ue los mismos.
QHBoxLayout *topLayout = new QHBoxLayout(this);
QHBoxLayout *groupLayout = new QHBoxLayout(this);
QHBoxLayout *buttonsLayout = new QHBoxLayout(this);

Empecemos poi el topLayout uonue hay un QLabel con el texto Piintei y un QComboBox,
al que luego queiemos aauiile items ue uonue seleccionai opciones. Poi lo que aauimos uebajo
ue la piimeia linea uel couigo ue antes:
QComboBox *c;
QHBoxLayout *topLayout = new QHBoxLayout(this);
topLayout->addWidget(new QLabel("Printer:"));
topLayout->addWidget(c=new QComboBox());

Bate cuenta ue que la Label solo la hemos instanciauo, peio no la hemos asignauo a
ninguna vaiiable, ya que no iequeiimos haceile naua en el couigo ms auelante, no iequeiimos
acceuei a ninguna vaiiable que la maneje, mientias que la ComboBox si la hemos asignauo a la
vaiiable c, paia ms auelante pouei aauiile items ue seleccion meuiante uicha vaiiable.
Ahoia vamos a poi el buttonsLayout, uonue tenemos que colocai un spacei piimeio, y
luego los 2 botones.
QHBoxLayout *buttonsLayout = new QHBoxLayout(this);
buttonsLayout->addStretch();
buttonsLayout->addWidget(new QPushButton("Print"));
buttonsLayout->addWidget(new QPushButton("Cancel"));

vamos ahoia a poi la caja cential que es la ms compleja ue este ejemplo. Piimeiamente
vamos a aauiile a gioupLayout los 2 uioupBoxes.
QHBoxLayout *groupLayout = new QHBoxLayout(this);
QGroupBox *orientationGroup = new QGroupBox();
groupLayout->addWidget(orientationGroup);
QGroupBox *colorGroup = new QGroupBox();
groupLayout->addWidget(colorGroup);

$!


Fijate que aqui hemos instanciauo piimeio los uioupBoxes y luego los hemos aauiuo al
Layout. Bien, ahoia vamos a usai un Layout veitical uentio ue caua uiupoBox paia oiganizai el
espacio ue los wiugets que van a ii uentio.
QGroupBox *orientationGroup = new QGroupBox();
QVBoxLayout *orientationLayout = new QVBoxLayout(orientationGroup); // nueva
groupLayout->addWidget(orientationGroup);
QGroupBox *colorGroup = new QGroupBox();
QVBoxLayout *colorLayout = new QVBoxLayout(colorGroup); // nueva
groupLayout->addWidget(colorGroup);

Ahoia vamos a aauiile a caua veitialLayout los wiugets que le coiiesponuen. Poi lo que
el couigo completo iefeiente al Layout uel meuio se queua asi.
QHBoxLayout *groupLayout = new QHBoxLayout(this);
QGroupBox *orientationGroup = new QGroupBox();
QVBoxLayout *orientationLayout = new QVBoxLayout(orientationGroup);
orientationLayout->addWidget(new QRadioButton("Landscape"));
orientationLayout->addWidget(new QRadioButton("Portrait"));
groupLayout->addWidget(orientationGroup);
QGroupBox *colorGroup = new QGroupBox();
QVBoxLayout *colorLayout = new QVBoxLayout(colorGroup);
colorLayout->addWidget(new QRadioButton("Black and White"));
colorLayout->addWidget(new QRadioButton("Color"));
groupLayout->addWidget(colorGroup);

Si te has uauo cuenta, no hemos puesto an el spacei veitical que hay entie el Layout
cential y el infeiioi (el ue los botones). Paia hacei eso usanuo la funcion auuStietch, tenemos que
iefeiiinos a una veiticalLayout, poi lo que vamos a tenei que conteneilo touo uentio ue un
Layout ms gianue. Como este QvBoxLayout, conteneuoi ue touo, seiia el pauie ue touo,
entonces tenuiiamos que iefeiii los S Layouts iniciales a ste, y ste pasaiia a sei el ms ceicano
en jeiaiquia a la ventana ue Bilogo. Y asi queuaiia touo:
QStringList options;
options << "Office Printer" << "HP LaserJet" << "Canon OfficeJet";
QComboBox *c;

QVBoxLayout *outerLayout = new QVBoxLayout(this);
// Layout superior
QHBoxLayout *topLayout = new QHBoxLayout();
topLayout->addWidget(new QLabel("Printer:"));
topLayout->addWidget(c=new QComboBox());
// Fin Layout superior
outerLayout->addLayout(topLayout);
// Layout Central
QHBoxLayout *groupLayout = new QHBoxLayout();
QGroupBox *orientationGroup = new QGroupBox("Page Orientation");
QVBoxLayout *orientationLayout = new QVBoxLayout(orientationGroup);
orientationLayout->addWidget(new QRadioButton("Landscape"));
orientationLayout->addWidget(new QRadioButton("Portrait"));
groupLayout->addWidget(orientationGroup);
QGroupBox *colorGroup = new QGroupBox((Coloi options);
QVBoxLayout *colorLayout = new QVBoxLayout(colorGroup);
colorLayout->addWidget(new QRadioButton("Black and White"));
colorLayout->addWidget(new QRadioButton("Color"));
groupLayout->addWidget(colorGroup);
// Fin Layout Central
outerLayout->addLayout(groupLayout);
outerLayout->addStretch();
// Layout Inferior
QHBoxLayout *buttonsLayout = new QHBoxLayout();
buttonsLayout->addStretch();
buttonsLayout->addWidget(new QPushButton("Print"));
buttonsLayout->addWidget(new QPushButton("Cancel"));
// Fin Layout Inferior
outerLayout->addLayout(buttonsLayout);

c->addItems(options);

$"


Bemos sangiauo los bloques que ya teniamos constiuiuos paia uejai claio el couigo que
hemos aauiuo, y el sentiuo uel mismo con iespecto a los bloques que contiene, y el spacei
veitical. Tambin nos hemos peimitiuo el lujo ue aauii los items uel ComboBox que hain ue
opciones, meuiante una StiingList.

782:9AI554C2 36 I2? V629?2? 36 '4YB8R8 582 (9 '6:4R26A
Algunos pensain que soy un masoquista, uiseanuo la ventana a tecla, peio es
funuamental apienuei antes el couigo que hay uetis ue touo, antes que abanuonaise al placei
uel meio y puio uiseo, que nos sepaia ue la piogiamacion y poi tanto uel entenuimiento ue las
bases funuamentales.
vamos a cieai un nuevo pioyecto, uonue elegiiemos Qt C++ Pioject -> Qt u0I
Application. Le pouemos llamai al pioyecto "uialog". La clase base se llamai "Bialog" y la clase
base va a sei QWiuget.
0na vez se han cieauo touos los ficheios, abiimos "uialog.ui" que se nos abiii en el Qt
Besignei. vamos a ii uibujanuo en l, el inteiface uel uiseo que estamos siguienuo. Iiemos
colocanuo piimeio en la paite supeiioi, lo mejoi que pouamos, un Label y un ComboBox,
aiiastinuolo ue las heiiamientas al foimulaiio y soltnuolo. Bacemos uoble clic sobie el texto
uel Label y ponemos "Piintei:". Luego en el bloque cential vamos a situai piimeio los 2
uioupBox uno al lauo uel otio. Les cambiamos los textos, poi los que les coiiesponuen. Luego
aauimos en la paite infeiioi los 2 PushButtons, y les cambiamos su texto.
Ahoia vamos a ponei los RauioButtons en sus iespectivos uioupBoxes, y les ponemos el
texto que les coiiesponuen. Ahoia situamos el spacei hoiizontal y el veitical, confoime al uibujo
uel uiseo que estamos siguienuo.
Si te uas cuenta, poi mucho que lo intentes, no va a queuai touo lo alineauo que
queiemos, poi eso, es el momento ue comenzai a cieai los Layouts que oiganicen touo este
espacio. Esto se hace siempie ue uentio hacia fueia, empezaiemos poi agiupai los RauioButton,
seleccionanuo los uel giupo izquieiuo (ambos mantenienuo la tecla Ctil pulsaua, Cmu en los
Nac), y los agiupamos pulsanuo el boton Lay 0ut veitically. Apaiece una caja ioja alieueuoi ue
ellos que los alinea peifectamente entie si. vamos a hacei lo mismo con los ue la ueiecha. Luego
vamos a seleccionai el uioupBox izquieiuo, y pulsamos Lay 0ut veitically, que lo oiganiza con su
conteniuo, los iauiobuttons. Bacemos los mismo con el uioupBox ue la ueiecha.
Luego seleccionamos ioueanuo con el iaton touo el bloque cential y pulsamos en Lay
0ut Boiizontally. Luego hacemos lo mismo con el giupo supeiioi (label y combobox) y con el
giupo infeiioi (spacei hoiizontal y los 2 botones).
Ahoia nos queuan los S giupos y el spacei veitical. Pulsamos sobie una zona vacia uel
foimulaiio, paia seleccionailo a l poi completo, y teiminamos pulsanuo en Lay 0ut veitically.
Ya se nos ha oiganizauo touos los wiugets con los layouts. Be hecho pueues vei como el uiseo se
auapta flexiblemente al tamao libie ue la ventana si aiiastias uno ue los boiues uel foimulaiio,
cambianuo su tamao, veis como touo se oiganiza en tamao y posicion peifectamente.
Con esto uamos poi teiminauo el tema iefeiente a los elementos ue una ventana
(wiugets y layouts), en el pioximo tema vamos a pasai a vei las ventanas ue uilogo, elemento
inuispensable ue una aplicacion gifica.
Si poi cuiiosiuau quieies aauii los items uel ComboBox, abie el couigo ue "uialog.cpp" y
ujalo ue esta foima:
QStringList options;
options << "Office Printer" << "HP LaserJet" << "Canon OfficeJet";
ui->setupUi(this);
ui->comboBox->addItems(options);

$#


Fijate que hemos acceuiuo uesue el objeto ui que iepiesenta el inteifaz uiseauo en el
ficheio *.ui, a la combobox, poi su nombie (objectName), y entonces ya pouemos llamai a sus
mtouos libiemente. Ya veiemos esto con ms uetalle ms auelante.




























$$


)%/" ;_
n%&)"&"+ '% '0"<-^-

0n wiuget , que no tenga pauie se le llama top-level wiuget. 0n top-level pueue usai el
mtouo show() paia mostiaise en pantalla, y pueue poi tanto constituiise como ventana. Asi hay
S tipos ue top-level Winuows (ventanas):
(D43R69.- Cualquiei wiuget sin pauie es constituiuo automticamente como una ventana, una
ventana plana, como la que hemos cieauo en el tema anteiioi, o como la que se geneiaba
simplemente mostianuo un QLabel en el ejemplo ue BolaNunuo.
('4?B8R.- Es un wiuget especial, que confoima una ventana que auems uevuelve un valoi
siempie tias ceiiaise (0K, Cancel, etc.)
(/?42D4238E.- Es otio wiuget especial, que confoima la ventana ms completa y poi tanto la
piincipal ue una aplicacion gifica, con mens, heiiamientas, status bai, uock, etc.
Puesto que ya hemos visto a los wiugets funcionanuo como ventanas, y las
NainWinuows las tiataiemos a fonuo en el tema 19, en este tema vamos a tiatai ue ceica las
ventanas ue uilogo, uescenuientes ue QBialog.
Toua ventana ue Bilogo lleva una seiie ue wiugets que la componen, peio lo
funuamental es que lleva botones paia aceptai yo iechazai una ueteiminaua accion, y que esa
uecision es uevuelta al piogiama meuiante un valoi.
En este capitulo vamos a vei el couigo que confoima a una ventana Bilogo paia su uso
uentio ue una aplicacion mayoi, peio no vamos a uesaiiollai un ejemplo completo, ya que nos
faltan elementos que no uebemos an tocai aqui y que una vez conociuos pouiemos uniilos
touos en el tema 2u.
0na ventana uepenuienuo, ue la inteiactiviuau que bloquea, pueue sei:
&8 /83?B.- Si no bloquea ninguna ventana que le acompae, y peimite estanuo ella abieita,
inteiactuai con otias ventanas tambin abieitas.
D4238E/83?B.- Solo bloquea la ventana pauie ue la misma, no puuienuo inteiactuiai con ella,
hasta que sta es ceiiaua, aunque peimite inteiactuai con el iesto.
"NNB45?9482/83?B.- Bloquea a touas las ventanas ue la aplicacion, solo puuienuo inteiactuai con
ella mientias est abieita.
Toua ventana ue Bilogo, heieua ue QBialog, y uebe llevai botones paia seleccionai
opciones y pushbuttons paia aceptai o iechazai la accion. vamos a cieai una ventana ue uilogo
con el Qt Besignei, tal como hemos apienuiuo en el tema pasauo, con esta foima:



$%


Asi que esta vez el pioyecto lo basaiemos en la clase QBialog y le llamaiemos
SeaichBialog. 0na vez abieito el ficheio *.ui en el Qt Besignei, selecciona el foimulaiio, y a la
ueiecha, cambia la piopieuau WinuowTitle en QWiuget, poi "Seaich" paia que salga el titulo que
vemos en el uibujo. Constiuye algo similai a esto:

Y pulsanuo en el cuauio azul infeiioi ueiecho ue la seleccion uel foimulaiio, haz el tamao lo
minimo que se pueua ue alto, peio hazlo al menos el uoble ue ancho que ue alto, ue maneia que
se paiezca al uibujo oiiginal. Cambia el nombie uel QLineEuit poi "seaichText" y el ue los
iauiobuttons poi "uiiectionFoiwaiu" y "uiiectionBackwaiu" iespectivamente.
0na vez hecho el uiseo, vamos a vei el couigo que lo integiai en la funcionaliuau ue
una aplicacion ms compleja.
En el aichivo seaichuialog.h en el constiuctoi ponuiemos un couigo como ste:
class SearchDialog : public QDialog
{
Q_OBJECT
public:
explicit SearchDialog(const QString &initialText, bool isBackward, QWidget *parent
= 0);
~SearchDialog();

// los getters que recogern las opciones
bool isBackward() const;
const QString &searchText() const;

private:
Ui::SearchDialog *ui;
};

Bemos puesto aigumentos paia inicializai el texto ue bsqueua, poi ejemplo, y asi que
se conseive entie las bsqueuas. Tambin se inicializa ue igual maneia la opcion ue uiieccion ue
la bsqueua. 0saiemos 2 getteis paia iecogei el estauo ue las opciones. vamos a vei la
implementacion ue este couigo en seaichuialog.cpp .
SearchDialog::SearchDialog(const QString &initialText, bool isBackward, QWidget
*parent) : QDialog(parent), ui(new Ui::SearchDialog)
{
ui->setupUi(this);
ui->searchText->setText(initialText);
if(isBackward)
ui->directionBackward->setChecked(true);
else
ui->directionForward->setChecked(true);
}

bool SearchDialog::isBackward() const
{
return ui->directionBackward->isChecked();
}

const QString &SearchDialog::searchText() const
{
return ui->searchText->text();
}
$&


Ahoia vamos a vei como se integiaiia el couigo ue mostiai la ventana en el iesto ue la
aplicacion.

SearchDialog
dlg(settings.value("searchText").toString(),settings.value("searchBackward").toBool(),
this);

if(dlg.exec() == QDialog::Accepted){
QString text = dlg.searchText();
bool backwards = dlg.isBackward();
.......................
}

Poi uefecto la ventana es moual, peio pueue sei cambiauo meuiante el mtouo
setWinuowNouality(). Estbamos acostumbiauos a mostiai la ventana con show() (no moual
poi uefecto), peio ahoia al haceilo con exec() (moual poi uefecto), lo que se uevolvei una vez
ceiiaua, sei un valoi enteio, que es un BialogCoue.

Constant Value
QDialog::Accepted 1
QDialog::Rejected 0


n629?2?: 36 '4YB8R8 +9?23?A3

Auems ue pouei uiseai ventanas a nuestio gusto y necesiuaues, Qt incoipoia una
seiie ue ventanas que son muy tipicas ue las u0Is ue touas las platafoimas. En concieto son 6
tipos ms los subtipos ue caua una ue ellas. vamos a veilas uesue la ms sencilla a las ms
avanzaua.

EFG 6>158#?0$3&<A= Es una ventana ue uilogo que piovee automticamente ue un Label, un
LineEuit o un ComboBox, y los botones 0K y Cancel. Pueue iecogei: un Int, un Bouble, un texto o
un Item ue un combo box, y lo hace con las funciones coiiesponuientes getInt(), getBouble(),
getText() y getItem(). Touas estas funciones uevuelven como ltimo paimetio un bool que uice
si se eligio el boton 0K (tiue), o el Cancel (false). vamos a vei el couigo ejemplo ue las 4
posibiliuaues:

H*"!53& +&1 <"#>1#I
bool ok;
int i = QInputDialog::getInt(this,"Ejemplo con getInt","Porcentaje:", 25, 0, 100, 1,
&ok);

H*"!53& +&1 <"#?&8)3"I
double d = QInputDialog::getDouble(this," Ejemplo con getDouble",
"Cantidad:", 37.56, -10000, 10000, 2, &ok);

H*"!53& +&1 <"#>#"!I
QStringList items;
items << "Primavera" << "Verano" << "Otoo" << "Invierno";

QString item = QInputDialog::getItem(this, " Ejemplo con getItem",
"Estacin:", items, 0, false, &ok);
if (ok && !item.isEmpty()) itemLabel->setText(item);


H*"!53& +&1 <"#A"B#I
QString text = QInputDialog::getText(this, "Ejemplo con getText",
"Usuario:", QLineEdit::Normal, QDir::home().dirName(), &ok);
if (ok && !text.isEmpty()) textLabel->setText(text);



$'



JFG6H44&47"''$<".- Es una ventana ue eiioi que piovee ue un TextLabel y un CheckBox.

errorMessageDialog = new QErrorMessage(this);
errorMessageDialog->showMessage("Esta ventana muestra un error. "
"Si el checkbox se deja, volver a mostrarse, "
"si no se deja, ya no volver a mostrarse. ");

Con showNessage() ponemos el texto uel eiioi, automticamente apaiecei el checkbox
uicienuo si quieie que se muestie el eiioi ue nuevo, si ueciue que no, ya no volvei a salii,
aunque sea llamaua en el couigo la funcion showNessage() ue nuevo.

KFG67"''$<"L&B.- Es una ventana moual que piegunta al usuaiio una piegunta, y iecibe una
iespuesta. Las hay ue 4 tipos:

B#$%/%>.-

QMessageBox msgBox(QMessageBox::Warning,"warning",MESSAGE, 0, this);

msgBox.addButton("Save &Again", QMessageBox::AcceptRole);
msgBox.addButton("&Continue", QMessageBox::RejectRole);
if (msgBox.exec() == QMessageBox::AcceptRole)
// codigo de aceptacion
else
// codigo de rechazo

C+&,)/*%.-

QMessageBox::StandardButton reply;

reply = QMessageBox::question(this,"question",MESSAGE , QMessageBox::Yes |
QMessageBox::No | QMessageBox::Cancel);

if (reply == QMessageBox::Yes)
// codigo de Yes
else if (reply == QMessageBox::No)
// codigo de No
else
// codigo de Cancel

/%3*$4#)/*%.-

QMessageBox::StandardButton reply;
reply = QMessageBox::information(this," information", MESSAGE);
if (reply == QMessageBox::Ok)
// codigo de OK
else
// codigo de Escape (tecla escape) no todos los sistemas lo admiten


ciitical.-

QMessageBox::StandardButton reply;

reply = QMessageBox::critical(this,"critical",MESSAGE, QMessageBox::Abort |
QMessageBox::Retry | QMessageBox::Ignore);

if (reply == QMessageBox::Abort)
// codigo de Abort
else if (reply == QMessageBox::Retry)
// codigo de Retry
else
// codigo de Ignore

MFG6N&3&4?0$3&<.- Nuestia el cuauio ue seleccion ue coloi, y uevuelve el couigo uel mismo.

QColor color = QColorDialog::getColor(Qt::green, this); // color inicial verde

if (color.isValid()) {
// codigo de uso de color
}
$(



OFG 6=&1#?0$3&<.- Paia elegii la fuente.

bool ok;

QFont font = QFontDialog::getFont(&ok, this);

if (ok) {
// codigo de uso de la fuente
}

PFG6=03"?0$3&<.- Paia hacei opeiaciones ue ficheios o uiiectoiios. Bay ue 4 tipos:

get0penFileName.-

QString selectedFilter;
QString fileName = QFileDialog::getOpenFileName(this,
"getOpenFileName",
defaultFileName,
"All Files (*);;Text Files (*.txt)",
&selectedFilter,
options);
if (!fileName.isEmpty()) // codigo de apertura del fichero


getSaveFileName.-

QString selectedFilter;
QString fileName = QFileDialog::getSaveFileName(this,
"getSaveFileName",
defaultFileName,
"All Files (*);;Text Files (*.txt)",
&selectedFilter,
options);
if (!fileName.isEmpty())// codigo de guardado del fichero


get0penFileNames.-

QString selectedFilter;
QStringList files = QFileDialog::getOpenFileNames(this,
"getOpenFileNames",
openFilesPath,
"All Files (*);;Text Files (*.txt)",
&selectedFilter,
options);
if (files.count()) {
openFilesPath = files[0];
// codigo de apertura de ficheros
}

getExistingBiiectoiy.-

QFileDialog::Options options = QFileDialog::DontResolveSymlinks |
QFileDialog::ShowDirsOnly;

QString directory = QFileDialog::getExistingDirectory(this,
"getExistingDirectory",
defaultDirName,
options);
if (!directory.isEmpty())// codigo de apertura de directorio






%*































%)


)%/" ;L
/-'%<-U n0+)" . 7-&)$-<"'-$U 0&)$-'\770-&

El piimei lenguaje que poi piimeia vez intiouujo el paiauigma NvC (Nouelo, vista,
Contiolauoi) fue Smalltalk en 1979 en el laboiatoiio ue Xeiox. Actualmente muchos lenguajes y
fiamewoiks lo han incoipoiauo como una ventaja al uesaiiollo inestimable, y poi supuesto Qt no
iba a sei menos.
En la gian mayoiia ue aplicaciones, se acceue a fuentes ue uatos, que pueuen sei, un
ficheio, un sistema ue aichivos, una base ue uatos, un stieam ue uatos, etc. Luego esos uatos se
muestian al usuaiio ue uiveisas foimas, y el usuaiio inteiacta con ellos, mouificnuolos,
leynuolos o tiatnuolos ue alguna maneia y la fuente ue los mismos es actualizaua con uicha
mouificacion o tiatamiento. El paiauigma NvC sepaia en S aspectos uifeientes ue esta activiuau,
poi un lauo esta el Nouelo, que est en contacto uiiecto con la fuente ue uatos, ue maneia que es
quien iecoge los uatos ue la misma y los actualiza. Esos uatos son enviauos poi el mouelo a la
vista (view), que se encaiga ue visualizailos ue una maneia especifica. 0n mismo mouelo pueue
alimentai vaiias vistas uifeientes y ambas sincionizai su conteniuo a la vez. Sobie la vista el
usuaiio inteiacta, y la misma pueue pioveei ue mtouos paia enviai mouificaciones ue los
uatos al Nouelo (mouel), y este a la fuente ue uatos, o existen tambin objetos especiales,
especializauos en la inteiaccion uel usuaiio con la vista, que aqui no se llama Contiolauoi sino
Belegauo (uelegate).
La veiuau es que se tiata ue conceptos muy abstiactos, y cieo que lo mejoi es poneilos a
funcionai paia vei ue lo que estamos hablanuo. Suponga que quieie piesentai en una ventana en
foima ue ibol el conteniuo completo uel uiiectoiio ue su oiuenauoi, con ficheios y uiiectoiios.
Sin uuua seiia algo uificil ue hacei meiamente con QTieeWiuget y QBii (QFileInfo, etc), y si al
final lo logiaia, seguio que ocupaiia bastantes lineas ue couigo. Pues bien, el paiauigma NvC
viene a nuestio iescate, paia hacei ue esta taiea algo sencillo y con poco couigo, ue hecho se
pouiia hacei con solamente 4 lineas ue couigo, si no fueia poique nos gusta cambiai unas
ueteiminauas piopieuaues ue la vista, peio en cualquiei caso no va a pasai ue las 1u lineas.
Como es eso posible..
Qt piovee ue una seiie ue vistas suficientes paia lo que cualquieia suele piogiamai, y
tambin ue los mouelos paia lo mismo, peio si esto no fueia asi, seiia mucho ms sencillo
cieailos paia pouei poneilos a tiabajai juntos, a hacei un piogiama especifico con un couigo
complejo y poco ieutilizable. Cuanuo un piogiamauoi se pone a esciibii mucho couigo, es poique
sabe que lo va a ientabilizai en el tiempo, ue lo contiaiio, se est quieto.
Bien, pues paia llevai a cabo la aplicacion que hemos comentauo, vamos a usai como
vista, la clase QTieeview, que nos piovee ue un magnifico gifico en ibol muy avanzauo y
paiametiizable, y como Nouelo, vamos a usai la clase QBiiNouel, que se ielaciona uiiectamente
con el sistema ue aichivos como su fuente ue uatos. Aunque paiezca mentiia, simplemente hay
que combinai ambas clases, Nouelo y vista paia que suija la chispa mgica, y eso se hace con el
mtouo ,&)D*2&564*2&5%#4&7 , que pioveen touas las vistas. Be esta maneia la vista es caigaua
con uatos que consigue el mouelo paia ella. vamos a poi el couigo.
Esta vez vamos a cieai un pioyecto vacio (Empty Pioject), al que vamos a llamai "mvc".
Luego vamos a aauiile un ficheio fuente "main.cpp" y vamos a empezai a esciibii uiiectamente
en l.
#include <QtGui>
#include <QApplication>
int main(int argc, char **argv)
{
QApplication app(argc,argv);

QDirModel model;
QTreeView view;
view.setModel(&model);
%!


// Vamos a cambiar el aspecto de la vista
view.setAnimated(false);
view.setIndentation(20);
view.setSortingEnabled(true);
view.setWindowTitle("Dir View");
view.resize(640,480);
// vamos a mostrar la vista
view.show();

return app.exec();
}

Eso es touo el couigo, vamos a vei cual es el iesultauo final ue esas pocas lineas.

Efectivamente es impiesionante el iesultauo obteniuo con tan escueto couigo. Con esto queua
justificauo sobiauamente el uso uel paiauigma NvC siempie que sea posible.
Ahoia que he conseguiuo tu atencion, es hoia ue que te piesente las vistas y los mouelos
ue que vas a uisponei en Qt, que como ya apuntamos van a sei suficientes paia la gian mayoiia
ue aplicaciones que vas a acometei. Si esto no es asi, en un cuiso ms avanzauo pouis apienuei
a cieai tus piopios mouelos, o tus piopias vistas, peio eso ya se sale uel pioposito ue este piimei
libio.

<?: n4:9?:
Las vistas que piopoiciona Qt son touas ueiivauas ue la clase 6Q)'#4$+#>#"!R0"S . Las
vistas que ue ella se ueiivan son ties tipos piincipalmente: QListview, QTableview y QTieeview.
QListview, piopoiciona una vista uniuimensional, uonue hay solo una columna (column)
y muchas filas (iow). Bispone ue una seiie ue mtouos paia cambiai la piesentacion ue los items
ue la misma.
QTableview, es la ms usaua, sobie touo en la piesentacion ue tablas ue bases ue uatos.
Tiene foima biuimensional con vaiias columnas y vaiias filas, auems posee cabeceia tanto paia
las columnas como paia las filas, paia ponei sus titulos en ellas.
%"


QTieeview, es usaua sobie touo en acceso a uiiectoiios, como hemos visto en el ejemplo,
y uispone la infoimacion en foima ue ibol. Auems tambin uispone ue cabeceia hoiizontal
(heauei), paia ponei titulos a las piopieuaues ue los items.

<8: P836B8:
Los mouelos que piopoiciona Qt paia acceuei a los uifeientes tipos ue fuentes ue uatos,
ueiivan ue 6Q)'#4$!>#"!7&%"3, y entie los que piopoiciona estn: QStiingListNouel,
QStanuaiuItemNouel, QFileSystemNouel y QSqlRelationalTableNouel.
E()$/%>F/,)D*2&5, es usauo paia guaiuai una lista ue QStiings.
E()#%2#$2G)&4D*2&5, se usa paia el manejo ue estiuctuias ms complicauas en foima ue
ibol, que pueuen guaiuai cualquiei tipo ue uatos.
E./5&(:,)&4D*2&5, piovee ue la infoimacion que obtiene uel sistema ue ficheios, como
E?/$D*2&5, peio ms avanzauo.
E(C5H&5#)/*%#5I#95&D*2&5, se usa paia tiatai uatos piovenientes ue una base ue uatos
ielacional. Be ella ueiiva E(C5I#95&D*2&5 que se usa paia guaiuai los uatos ue una tabla concieta
ue una base ue uatos. Be ella ueiiva E(C5E+&$:D*2&5 que guaiua los uatos ue la iespuesta a una
queiy a una base ue uatos.

-H:6AV?54826: O42?B6:
Como pueues imaginai, combinanuo una vista o vaiias vistas con un mouelo, pueuo
obtenei el inteifaz gifico que necesito paia inteiactuai con los uatos que quieio. El caso ms
tipico es con una base ue uatos ielacional, como NySQL u 0iacle. Se tiataiia poi tanto ue
combinai una QTableview con una QSqlTableNouel o una QSqlQueiyNouel. veiemos casos
concietos en los temas que coiiesponuan a bases ue uatos.













%#































%$


)%/" ;g
(<0+)D0'^%) . ()"><%D0'^%)

Beiivauas ue QListview y QTableview, tenemos 2 clases que iepiesentan vistas en
foima ue lista y tablas, iespectivamente, con un mouelo pieuefiniuo. Ambos son QWiugets
piopoicionauos poi la baiia ue heiiamientas uel Qt Besignei, y suelen sei usauos paia
aplicaciones sencillas uonue no se usan mouelos combinauos con ellas. Estn foimauos poi items
ue las clases QListWiugetItem y QTableWiugetItem, iespectivamente.

(<4:9D43R69
Paia aauii elementos a esta Lista hay 2 foimas:
1.- Constiuyenuo los items con esta clase como pauie.
new QLIstWidgetItem ("Texto elemento 1",listWidget);

2.- Constiuyenuo el item sin pauie y aauinuolo a la lista ms taiue.
QListWidgetViewItem *newItem = new QListWidgetViewItem;
newItem->setText("Texto Elemento 1");
listWidget->insertItem(row,newItem);

En la segunua opcion tambin se pueue usai el mtouo /%,&)G%)&4,6E()$/%>F/,)7, y
tambin #22G)&46E()$/%>7, que aaue al final uel anteiioi, y no es una posicion exacta.
El mouo ue seleccion ue los elementos en la lista se pueue leei con la funcion
,&5&0)D*2&67, y se pueue establecei con la funcion ,&)(&5&0)/*%D*2&6,&54*2&7. Los uifeientes
mouos ue seleccion son: SingleSelection (un solo elemento), NultiSelection (vaiios elementos a la
vez), ContiguousSelections (vaiios elementos contiguos a la vez) y NoSelection (no se pueue
seleccionai naua).
La iazon ue usai QListWiugetItem en vez ue QStiings en la inseicion ue elementos, es
poique, ste peimite no solo inseitai texto en las listas, si no tambin iconos. Asi tambien hay
uos Nouos ue vista: IconNoue (uiag & uiop uesabilitauo poi uefecto) y ListNoue (uianu & uiop
habilitauo poi uefecto). Tambin se pueue cambiai el tamao uel icono con ,&)G0*%(/J&6E(/J&7, y
el espaciauo con ,&)(-#0/%>6K#5+&7.
Paia boiiai items, se pueue usai )#L&G)&46$*B7, y los Items pueuen apaiecei en la lista
maicauos con EF/,)M/&BG)&4NN,&)81&0L()#)&6E)NN81&0L()#)&7.
La nica seal que usamos en esta clase es 0+$$&%)G)&481#%>&260+$$&%)O-$&K/*+,7, que se
piouuce al cambiai el foco ue item. La funcion 0+$$&%)G)&467, nos uevuelve el item actual, y
0+$$&%)H*B67, nos uevuelve el iow (fila) uel item actual.

()?HB6D43R69
Se pueue uimensionai en la cieacion en el constiuctoi (%&B EI#95&P/2>&)
6$*B,O0*5,O-#$&%)7 ), y luego ieuimensionaila con ,&)H*B8*+%)6$*B,7 y ,&)8*5+4%8*+%)60*5,7.
Pouemos aauii items con ,&)G)&46$*BO0*5O%&BG)&47, uonue newItem es un
QTableWiugetItem. Se pueuen boiiai items con )#L&G)&46$*BO0*57. Pouemos ponei etiquetas en
las cabeceias hoiizontales con ,&)Q*$/J*%)#5Q&#2&$F#9&5,6E()$/%>F/,)7 y en las cabeceias
%%


veiticales con ,&)M&$)/0#5Q&#2&$F#9&5,6E()$/%>F/,)7. Tambin oiuenai poi una columna usanuo
,*$)G)&4,60*5O E)N(*$)R$2&$7.
Con $*B8*+%)() pouemos contai las filas, con 0*5+4%8*+%)() las columnas, y con 05&#$()
boiiai touo el conteniuo ue las celuas.
QTableWiugetItem, tiene funciones inteiesantes como ,&)G0*%(), ,&).*%)() y ,&)I&S)().
Las seales ms usauas son: 0&5585/0L&26/%) $*BO/%) 0*57O 0&5581#%>&26/%) $*BO/%) 0*57O
/)&485/0L&26EI#95&P/2>&)G)&4 /)&47O /)&481#%>&26EI#95&P/2>&)G)&4 /)&47.

veamos ahoia un ejemplo ue tabla con las cosas que hemos visto:
#include <QtGui>

int main(int argc, char **argv)
{
QApplication app(argc,argv);

QTableWidget tabla(12,2);
QStringList headers;

headers << "Meses" << "Dias";
tabla.setHorizontalHeaderLabels(headers);

QStringList meses, dias;
meses << "Enero" << "Febrero" << "Marzo" << "Abril" << "Mayo" << "Junio" <<
"Julio" << "Agosto" << "Septiembre" << "Octubre" << "Noviembre" << "Diciembre";
dias << "31" << "28" << "31" << "30" << "31" << "30" << "31" << "31" << "30" <<
"31" << "30" << "31";

for(int mes=0; mes < 12; mes++){
tabla.setItem(mes,0,new QTableWidgetItem(meses[mes]));
}

for(int mes=0; mes < 12; mes++){
tabla.setItem(mes,1,new QTableWidgetItem(dias[mes]));
}

tabla.resize(240,400);
tabla.show();

return app.exec();
}











%&


)%/" ;[
(9 7$%")-$

Queiemos ueuicai un poco ue tiempo al entoino ue uesaiiollo integiauo ue Qt, su IBE
llamauo Qt Cieatoi. En un piincipio Qt no poseia un IBE, touo el couigo tenia que sei esciito en
un euitoi ue texto avanzauo, o integiauo en otio IBE como Eclipse. Y an se pueue seguii
hacienuo asi, peio uesue la veision 4.u uel SBK, Tiolltech incluyo Qt Cieatoi como un entoino ue
uesaiiollo completo, uesue uonue se pueue acceuei al Qt Assistant, al Qt Besignei, se pueue
compilai, uebugeai uesue l. Peio una ue las caiacteiisticas ms inteiesantes paia el que pica
couigo, es el autoiiellenauo, y las teclas ue acceso ipiuo. Poi ello, queiemos ueteneinos un
tiempo paia vei como pouemos sacai ventaja en nuestio uesaiiollo ue este IBE avanzauo.

%B ?I98A6BB62?38
Cuanuo abiimos un ficheio ue couigo *.h , *.cpp, y nos situamos en una linea paia
empezai a tecleai couigo, y queiemos que el sistema nos ayuue a iellenai, uesue un ficheio
cabeceia, una clase, una vaiiable ya uefiniua, solo tenemos que pulsai la tecla Ctil+espacio, paia
que apaiezca toua una seiie ue alteinativas factibles, ue acueiuo a lo que ya hay esciito y
ueclaiauo en el ficheio. Tecleanuo las piimeias letias ue lo que queiemos ponei, nos iin
apaiecienuo las opciones caua vez ms especificas ue maneia que muchas veces no hace falta
acoiuaise uel nombie exacto ue una clase, un ficheio o una vaiiable. Si entie las opciones que
nos uan, no apaiece una clase o vaiiable especifica, es que no es accesible uesue esa paite uel
uocumento, poi cualquiei iazon, que pueue sei uesue que no est incluiuo su ficheio cabeceia, a
que uicha vaiiable no es accesible en uicha zona.
Tambin nos ayuua a acceuei a los miembios ue las clases, y nos ua los aigumentos ue
las funciones cuanuo esciibimos tias ellas, los paintesis.
Cuanuo nos situamos sobie un elemento uel couigo, se nos iecuauia este, y touos los
mismos elementos uentio ue la misma zona ue mbito. Be esta foima pouemos vei los mbitos, y
haceile un seguimiento a una vaiiable.
Si necesitamos ayuua uel Qt Assistant sobie algn elemento uel couigo, solo hay que
situaise sobie l y pulsai F1, entonces se nos abiii a la ueiecha uel couigo la ventana ue ayuua
coiiesponuiente.
Confoime se esciibe, si hay algn eiioi sintctico, apaiece subiayauo en iojo, y si nos
situamos sobie l, nos apaiece un mensaje emeigente, uesciibienuo el eiioi.

"9?@8: 36 965B?38 Wm6KH8?A3 :T8A95I9:X
Ctil + cuisoi ueiecho .- Te lleva al final ue la linea actual.
Ctil + cuisoi izquieiuo .- Te lleva al piincipio ue la linea actual.
Shift + cuisoies .- Seleccion ue texto.
Ctil + 0pBown.- Pasa pginas ue couigo aiiiba y abajo.
Ctil + u (Cmu + 0 en Nac).- Seleccionas bloques, pulsanuo vaiias veces aumentas el bloque ue
seleccion.
Ctil + i (Cmu + i en Nac).- Bace que el couigo seleccionauo tome la sangiia iequeiiua.
%'


Ctil + Shift + 0pBown (Cmu + Shift + 0pBown en Nac).- Peimite movei lineas completas hacia
aiiiba o hacia abajo. Funciona tambin con selecciones completas, movienuo el texto
seleccionauo.
Ctil + (Cmu + en Nac).- Comenta y uescomenta touo un bloque seleccionauo.
Shift + Bel .- Boiia toua una linea completa.
F4 .- Pasa ue ficheio cabeceia a ficheio ue couigo y viceveisa.
F2 .- Pasa ue la ueclaiacion a la implementacion ue una funcion o mtouo.
Ctil + K .- Abie el localizauoi, paia pouei navegai poi ayuuas y uocumentos ipiuamente.
Ctil + Shift + R (Cmu + Shift + R en Nac).- Peimite cambiai el nombie ue una vaiiable a la vez en
touas las paites uonue tiene mbito.





















%(


)%/" ;i
/"0& D0&'-D+

Este es el tema ms impoitante ue touos los iefeientes al uesaiiollo gifico, ya que en l
se encuentia la base funuamental ue touas las aplicaciones gificas. La ventana piincipal
(QNainWinuow), es el componente funuamental, sobie la cual pueuen apaiecei toua una seiie ue
wiugets: QNenuBai (baiia ue menu), QToolBai (baiias ue heiiamientas), QStatusBai (baiia ue
estauo), QBockWiuget (wiugets acoplables), QNenu (menus en geneial, incluiuos los
contextuales) y otios que ya hemos visto o que veiemos.

El inteifaz piincipal ue una aplicacion, la Nain Winuow (ventana piincipal), posee los
elementos que vemos en la foto ue aiiiba: un men piincipal en la paite supeiioi, una o vaiias
baiias ue heiiamientas con iconos, justo uebajo, que piopoiciona las opciones uel men ms
tipicas en el uso cotiuiano, mejoianuo la iapiuez ue uso ue la aplicacion, luego esta el wiuget
piincipal (cential wiuget), que en este caso est en la zona cential izquieiua, y es un
QPlainTextEuit, a la ueiecha vemos una ventana auosable (uockable winuow), que se uifeiencia
poi el icono ue la esquina supeiioi ueiecha, que nos inuica que pulsanuo sobie la baiia supeiioi
y aiiastianuo, uicha ventana se sepaiaiia ue la ventana piincipal, piopoicionanuo otia ventana,
finalmente en la paite infeiioi, se encuentia la baiia ue estauo (status bai) uonue se suele ponei
mensajes infoimativos al usuaiio al iespecto ue lo que esta acontecienuo en la aplicacion en caua
momento. Tambin caua elemento ue la ventana piincipal, pueue tenei un men contextual
asociauo, que al pulsai el boton ueiecho uel iaton nos peimita llevai a cabo acciones piopias ue
uicho elemento gifico. A paite ue estos elementos, una aplicacion pueue aauii ventanas ue
uilogo, ueiivauas ue QBialog, que pouin apaiecei como consecuencia ue acciones uel usuaiio,
como pulsai sobie una opcion uel men, una atajo uel teclauo, un mens contextual, o algn
evento cualquieia (infoimacion, aviso, eiioi, etc).

("59482
La piincipal mision ue una QNainWinuow, es centializai touo el inteifaz que comunica
al usuaiio, con la activiuau que la aplicacion lleva a cabo, poi ello touos los elementos que la
componen estn enfocauos a piopoicionai uicha inteifaz. Sin embaigo, una aplicacion pueue
iecibii oiuenes poi paite uel usuaiio paia llevai a cabo una misma accion uesue uifeientes
&*


componentes, como poi ejemplo, pegai una seleccion pievia en el wiuget piincipal, pouiia
haceise seleccionauo la opcion Euitai->Pegai en el men piincipal, o pulsanuo sobie el icono
coiiesponuiente en la baiia ue heiiamientas, o seleccionauo Pegai, uel men contextual uel
wiuget piincipal, o simplemente pulsanuo una combinacion ue teclas (shoitcut) que lleve a cabo
uicha accion. Bebiuo a que una misma accion pouiia uesencauenaila uifeientes elementos, es poi
lo que touas las acciones se han centializauo entoino a una clase que no tiene iepiesentacion
gifica fisica, llamaua QAction. Caua opcion uel men piincipal, ue las toolbais o ue los context
menus, se coiiesponuen con un objeto QAction (una accion), y una misma accion pueue sei
alcanzaua uesue vaiios ue estos elementos, lo cual va a iepeicutii en como ha ue uefiniise una
accion. vamos a vei la uefinicion ue una accion:
QAction *actionNew = new QAction("&New",this);
actionNew->setIcon(QIcon(":/images/new.png"));
actionNew->setShortcut("Ctrl+N");
actionNew->setStatusTip("Crear un nuevo documento");
actionNew->setToolTip("Crear un nuevo documento");
actionNew->setCheckable(false); // set
connect(actionNew, SIGNAL(triggered()), this, SLOT(newFile()));

Pouemos vei que piimeio cieamos un objeto accion que tenui el texto asociauo "&New" (uonue
el & va uelante ue la letia que queiemos vaya subiayaua inuicanuo la combinacion ue teclas al
usuaiio que nos llevai tambin a la misma accion). Luego meuiante una seiie ue mtouos ue
QAction, vamos uefinienuo la accion, que pueue tenei asociauo un icono (ya veiemos ms
auelante esto con ms uetalle), establecemos el shoitcut ue teclauo, establecemos el texto que
apaiecei en el status bai, al ejecutai esta accion, tambien el tooltip o texto emeigente con la
uesciipcion ue uicha accion si nos situamos sobie ella con el punteio uel iaton, ueciuiiemos si es
una opcion checkable, es uecii que pueua llevai una maica ue activaua o uesactivaua, finalmente
establecemos la conexion entie la seal tiiggeieu(), que se piouuce al pulsai sobie esa accion, y
el slot que en este caso pueue sei una funcion que nosotios mismos vamos a uefinii lo que va a
hacei.

/62j NA4254N?B
Caua opcion piincipal uel men piincipal, valga la ieuunuancia, es uecii, las que se ven
en la cabeceia ue la ventana sin pulsai sobie ellas, son objetos QNenuBai que son cieauos poi la
QNainWinuow, caua vez que se llama a su funcion miembio !"18L$4,-, y con ello pasan a sei
hechas hijas ue esta ventana. Caua opcion piincipal, poi tanto iequieie llamai la piimeia vez a
uicha funcion paia cieaise, y luego va aauienuo acciones (subopciones ue la misma) y
sepaiauoies.
QMenu *fileMenu;
fileMenu = menuBar()->addMenu("&File");
fileMenu->addAction(actionNew);
fileMenu->addAction(openAction);
fileMenu->addSeparator();
fileMenu->addAction(exitAction);


()88B>?A WH?AA? 36 T6AA?P4629?:X
QToolBar *toolbar =addToolBar("&File");
toolbar->addAction(actionNew);
toolbar->addAction(openAction);

La funcion miembio ue NainWinuow, auuToolBai, aaue una baiia con una seiia ue acciones,
que llevan su piopio icono.


&)


/62I 58296J9I?B W58296J9 P62IX
Se asocia uiiectamente el wiuget que lo va a mostiai, y solo hay que aauiile las acciones
que va a mostiai, y finalmente cambiai ue uicho wiuget la piopieuau ContextNenuPolicy paia
que apaiezca al pulsai clic ueiecho.
QPlainTextEdit *editor;
editor->addAction(copyAction);
editor->addAction(pasteAction);
editor->setContextMenuPolicy(Qt::ActionsContextMenu);

>?AA? 36 6:9?38 W:9?9I: H?AX
La baiia ue estauo noimalmente contenui wiugets uel tipo QLabel, paia mostiai texto
con avisos al usuaiio. Paia ello, piimeiamente iecogemos el punteio a la baiia ue estauo con la la
funcion ue QNainWinuow, '#$#8'L$4,-. Luego aauimos los wiugets, usanuo la funcion
?33D43R69WX, poi lo que como se ve, una statusbai es un conteneuoi.
QLabel *label = new QLabel();
label->setAlignment(Qt::AlignHCenter);
label->setMinimumSize(label->sizeHint());
statusBar()->addWidget(label);

<? V629?2? NA4254N?B W(/?42D4238EX
La ventana piincipal al sei ueclaiaua e implementaua, uebe ue contenei touos los
elementos que hemos uesciito antes, toua una seiie ue slots entie los cuales estain las funciones
que ejecutan las acciones, como newFile(), que hemos visto en el ejemplo ue QAction. Tambin es
inteiesante el ieuefinii la funcion viitual +3&'"H@"1#,6N3&'"H@"1# T"@"1#-, paia poi ejemplo
inteiceptai la seal ue cieiie ue la aplicacion con alguna ventana ue uilogo que pueua
pieguntai, si est seguio ue ceiiai. 0tia cosa esencial que uebe ue tenei en la implementacion ue
su constiuctoi, es la uesignacion como wiuget cential, esto se hace con su funcion miembio
'"#N"1#4$3D0%<"#,6D0%<"# T-.

]45T6A8: 36 A65IA:8: WoZSA5X
Los iecuisos que usa una aplicacion, como pueuen sei iconos, bitmaps y otios, van
uesciitos en un ficheio ue iecuisos multiplatafoima que lleva la extension qic. Qt sopoita
muchos tipos ue imgenes e iconos tales como: BNP, uIF, }Pu, PNu, PNN, XNB y XPN. El ficheio
qic foima paite uel pioyecto antes ue sei compilauo e incluiuo en el ejecutable. Se tiata ue un
ficheio esciito en XNL con el siguiente foimato:
<!uCC1?L 8CC>
<8CC verslon="1.0">
<qresource>
<flle>lmages/lcon.png</flle>
---
<flle>lmages/goLocell.png</flle>
</qresource>
</8CC>
En el ficheio ue pioyecto (*.pio) se aaue una linea que pone:
RES00RCES = iecuisos.qic
En el couigo C++ ya se pueue acceuei a esos ficheios uiiectamente meuiante la 0RL
":imagesicon.png", poi ejemplo:
action->setIcon(QIcon(":/images/new.png"));

&!


Bonue vemos que el ficheio uel icono se encuentia en la caipeta uel pioyecto en
"imagesnew.png".

(+69942R: W?@I:96:X
Es muy til y agiauable paia el usuaiio, que el aspecto que el inteiface tenia al cieiie,
vuelva a iecupeiaise al ieabiii la aplicacion al uia siguiente. Poi lo que, es muy usual que las
aplicaciones moueinas guaiuen una seiie ue paimetios que ueteiminan touo esto que
llamamos "settings", y lo iecupeien la pioxima vez que sea ejecutaua.
Caua sistema opeiativo o platafoima, gestiona esto ue una maneia uistinta, y lo guaiua
en sitios uifeientes, poi eso Qt, piovee ue una clase y mtouos paia tiatai este tema ue maneia
unifoime e inuepenuiente ue la platafoima. Bicha clase es QSettings, y meuiante sus mtouos
setvalue() y value(), el settei y gettei ue la misma, gestiona el almacenamiento y iecupeiacion ue
uichos ajustes (settings).
(+69942R:bb(+69942R: W 582:9 (+9A42R d&4<$10U$#0&1U 582:9 (+9A42R d$5530+$#0&1e (+9A42RWXU(-H@659 o5$4"1# e l X
Ejemplo ue cieacion ue settings:
QSettings settings("Qt Software, Inc", "TextEditor");

V843 (+69942R:bb:69n?BI6 W 582:9 (+9A42R dV"WU 582:9 (n?A4?29 d@$38"X
Ejemplo ue guaiuai cieitos settings:
settings.setValue("geometry", geometry());
settings.setValue("showGrid",showGridAction->isCheched());

(n?A4?29 (+69942R:bbV?BI6 W 582:9 (+9A42R dV"WU 582:9 (n?A4?29 d%"/$83#R$38" e (n?A4?29WX X 582:9
Ejemplo ue iecupeiai cieitos settings:
QRect rect = settings.value("geometry",QRect(200,200,400,400)).toRect();
bool showGrid = settings.value("showGrid",true).toBool();

+NB?:T :5A662:
Son las ventanas que apaiecen mientias se caigan los elementos ue un piogiama, poi
uiveisos motivos como, inuicai al usuaiio que se estn caiganuo y uaile infoimacion uuiante el
tiempo ue espeia o poi puia autopiomocion. En cualquiei caso es un elemento ms ue una
aplicacion que muy a menuuo se usa.
Lo ms habitual es que el couigo que muestia el splash scieen, se encuentie en main()
antes ue que se llame a QApplication::exec().
La clase que la uesciibe es 6C53$'2C+4""1, y usa funciones ue QWiuget como show()
paia mostiaise y setPixmap(QPixmap) paia establecei el fonuo a mostiai, finalmente el mtouo
showNessage() peimite sobieimpiesionai un mensaje sobie el fonuo ue uicha pantalla.
V843 (+NB?:T+5A662bb:69#4JP?N W 582:9 (#4JP?N d50B!$5X
V843 (+NB?:T+5A662bb:T8E/6::?R6 W 582:9 (+9A42R d!"''$<"U 429 $30<1!"1# e (9bb"B4R2<6O9U 582:9 (78B8A d+&3&4 e
(9bbHB?5m X


&"



veamos un ejemplo sencillo:
#include <QtGui/QApplication>
#include "mainwindow.h"

int main(int argc, char *argv[])
{
QApplication a(argc, argv);

QSplashScreen *splash = new QSplashScreen;
splash->setPixmap(QPixmap(":/images/splash.png"));
splash->show();
splash->showMessage("Iniciand ventana principal ...", Qt::AlignRight |
Qt::AlignTop, Qt::white);

MainWindow w;

splash->showMessage("Cargando modulos ...", topRight, Qt::white);

loadModules();

splash->showMessage("Estableciendo conexiones ...", Qt::AlignRight | Qt::AlignTop,
Qt::white);

establishConnections();

w.show();

splash->finish(&w);
delete splash;

return a.exec();
}

Bate cuenta ue que, se muestia el splash scieen con su gifico, luego se muestia el piimei
mensaje sobie el Pixmap en la zona supeiioi ueiecha en texto blanco, luego se lleva a cabo la
accion que inuica el mensaje, luego el siguiente mensaje, luego la accion que inuica el mismo, y
asi hasta que una vez touo esta caigauo e iniciauo, entonces muestia la ventana piincipal. La
funcion finish(const QWiuget&), lo que hace es espeiai a que se caigue completamente el Wiuget,
en este caso la NainWinuow, antes ue hacei un close() sobie l mismo.
En el pioximo tema, vamos a uesaiiollai uesue ceio una aplicacion completa con touo lo
que hemos apienuiuo hasta el uia ue hoy, y lo haiemos piimeio a couigo puio, sin uiseo visual,
paia compienuei y iepasai touos los conceptos bien, y finalmente veiemos como eso mismo se
pueue hacei ue maneia visual en el Qt Besignei. Poi lo tanto, es muy impoitante que touos los
conceptos queuen peifectamente aclaiauos con este ejemplo, ya que hasta aqui hemos
completauo el bloque piincipal y bsico paia constiuii aplicaciones en Qt, y sobie esta base
vamos a apoyai el iesto ue la enseanza que viene tias el tema 2u, uonue abunuaiemos en
conceptos ya piesentauos, e intiouuciiemos nuevos conceptos, peio touos funuamentauos en
esto piimeios 2u temas, que confoiman el nivel Bsico.







&#































&$



)%/" Gl
'%+"$$-<<- '% \&" "#<07"70Q& 7-/#<%)"

En este tema vamos a uesaiiollai un euitoi ue texto, con capaciuau paia cutpaste, con
men piincipal, baiia ue heiiamientas y status bai. Intiouuciiemos algunos conceptos nuevos,
peio pocos, como hemos hecho en los temas anteiioies, paia seguii sienuo fieles al estilo ue
enseanza giauual que estamos usanuo en este libio. El pioyecto pueues abiiilo uiiectamente en
el Qt Cieatoi, peio te iecomienuo que sigas las explicaciones que se van a uai en este tema, y que
luego poi tu cuenta, intentes uesaiiollai lo mismo, o algo similai uesue ceio.
vamos a cieai un nuevo pioyecto "Qt uui Application", al que llamaiemos "application",
la clase se llamai NainWinuow, su clase base sei QNainWinuow, y uesactivaiemos la opcion
"ueneiate foim" paia asi cieai nosotios mismos el inteifaz gifico en couigo puio. Lo siguiente
que vamos a hacei es copiai los iconos que vamos a usai (uiiectoiio images) en nuestio
pioyecto, tambin en una caipeta llamaua images, uentio ue nuestio pioyecto.
Be nuevo hacemos clic ueiecho sobie le nuevo pioyecto y aauimos un nuevo Qt->Qt
Resouice File, al que llamaiemos tambin "application". Al abiiise el ficheio qic en el Qt Cieatoi,
apaiece una ventana supeiioi vacia, y abajo un boton Auu. Pulsamos sobie l y luego sobie Auu
Piefix. En el campo ue texto Piefix, vamos a ponei "". volvemos a pulsai en Auu-> Auu Files, y
navegamos hasta el uiiectoiio images uonue hemos copiauo los iconos que vamos a usai,
seleccionamos los 6 iconos y los abiimos. Ya apaiecen los 6 iconos ausciitos al piefijo "", asi que
ya pouemos acceuei a ellos usanuo una 0RL uel tipo ":imagesicono.png", uonue ":" hace
iefeiencia a los iecuisos inteinos.

]45T6A8 P?42Z5NN
#include <QApplication>
#include "mainwindow.h"
int main(int argc, char *argv[])
{
Q_INIT_RESOURCE(application);

QApplication app(argc, argv);
app.setOrganizationName("Trolltech");
app.setApplicationName("Application Ejemplo");

MainWindow w;
w.show();

return app.exec();
}

0samos la macio Q_INIT_RES00RCE(nombie_base_uel_qic), aunque en la mayoiia ue los casos
no sea necesaiio y los iecuisos se caiguen automticamente, peio en algunas platafoimas, los
iecuisos se guaiuan en una libieiia esttica. Touo lo uems ya lo hemos visto anteiioimente, a
paite ue los uos miembios ue QApplication que se encaigan ue guaiuai en la aplicacion el
nombie ue la empiesa que hizo la aplicacion y el nombie ue la misma. Como vemos, vamos a usai
una NainWinuow que hemos ueiivauo ue QNainWinuow y que esta implementaua en los
ficheios mainwinuow.h y .cpp .

<? 5B?:6 /?42D4238E
&%


uian paite uel couigo y ue la estiuctuia uel mismo ue esta clase, pouin sei usauos en
otias aplicaciones. vamos a vei piimeiamente el wiuget que vamos a uesignai como wiuget
cential o piincipal ue la ventana Piincipal (NainWinuow).
Al sei una aplicacion euitoia ue texto, vamos a usai QPlainTextEuit como el wiuget
piincipal. Si consultas uicha clase en el asistente (Qt Assitant), pouis vei entie sus miembios,
los slots que usaiemos en los mens, como cut(), copy(), paste(). Tambin pouis vei la funcion
ms impoitante, que es uocument(), que uevuelve un punteio al texto uel mismo uel tipo
QTextBocument. Be entie los miembios ue ste ltimo, usaiemos isNouifieu() paia sabei si el
uocumento ha siuo mouificauo en algn momento.
Luego tenuiemos que miiai los slots que vamos a necesitai uefinii en la nueva clase.
Puesto que caua entiaua uel men iequieie ue una conexion entie la seal tiiggeieu() ue la
accion, y un slot que ejecuta la accion. Poi lo que tenuiemos que uai un iepaso a las opciones ue
men que vamos a ponei, paia sabei los slots que tenuiemos que ueclaiai en esta clase.
Tenuiemos un men File con los siguientes submens (Nuevo, Abiii, uuaiuai, uuaiuai
como y Salii). A excepcion ue la opcion Salii, que la ejecutaiemos con el slot close() ue QWiuget,
el iesto sein slots a ueclaiai e implementai.
Tenemos tambin el men Euit con los siguientes submens (Coitai, Copiai y Pegai).
Puesto que touos ellos pueuen ejecutaise uesue los slots pieuefiniuos en QPlainTextEuit,
iespectivamente cut(), copy() y paste(), no es necesaiio implementai nuevos slots paia este
men.
Finalmente tenemos el men Ayuua con los submens (Aceica ue y Aceica ue Qt), ue los
cuales, aceica ue Qt viene ya pieimplementauo como el slot aboutQt() ue QApplication.
Cuanuo el uocumento es mouificauo, uebe ue habei una accion que cambie la piopieuau
uel wiuget mouificauo, winuowNouifieu, que lo hace el settei setWinuowNouifieu. Poi tanto
vamos a cieai un slot que ejecute uicho cambio al que llamaiemos uocumentWasNouifieu().
Asi los slots que vamos a ueclaiai finalmente son:
private slots:
void newFile();
void open();
bool save();
bool saveAs();
void about();
void documentWasModified();

Lo siguiente que vamos a ueclaiai son la funciones piivauas, que se encaigain ue llevai
a cabo las taieas piincipales asignauas a los slots, y taieas secunuaiias piopias uel tipo ue
aplicacion. Touas las taieas piivauas que vamos a uefinii, son piopias ue una aplicacion u0I
geniica:
private:
void createActions();
void createMenus();
void createToolBars();
void createStatusBar();

void readSettings();
void writeSettings();

bool maybeSave();
void loadFile(const QString &fileName);
bool saveFile(const QString &fileName);

void setCurrentFile(const QString &fileName);
QString strippedName(const QString &fullFileName);

&&


vamos a veilas una poi una, ya que son funuamentales paia el uesaiiollo ue cualquiei aplicacion
u0I, aunque pueuan sei ueclaiauas e implementauas a gusto uel piogiamauoi, peio es
conveniente el estiuctuiai tus aplicaciones ue esta maneia paia hacei ms legible y mantenible
tu couigo.
0$&#)&T0)/*%,.- Aqui ponuiemos el couigo que ciea touas las acciones ue touos los mens, tal cual
vimos en el tema anteiioi con QAction, y las conectaiemos con los slots que ueclaiamos antes.
Tambin pouemos usai esta seccion paia ueshabilitai las acciones que inicialmente lo ueban ue
estai.
0$&#)&D&%+,.- Aqui es uonue vamos a ponei el couigo que ciea los mens, en nuestio caso
Ficheio, Euitai y Ayuua, con sus sepaiauoies y touo.
0$&#)&I**5!#$,.- Aqui es uonue ponuiemos el couigo que ciea las baiias ue heiiamientas, en
nuestio caso van a sei 2, una paia opciones ue Ficheio y la otia paia opciones ue Euitai.
0$&#)&()#)+,!#$.- Aqui es uonue ponuiemos el couigo paia cieai la baiia ue estauo, con touos sus
elementos, y pouiemos mostiai un mensaje inicial si lo vemos opoituno.
$&#2(&))/%>,.- Aqui ponuiemos el couigo que se va a encaigai ue leei los settings como vimos en
el tema anteiioi, y los va a aplicai.
B$/)&(&))/%>,.- Aqui pouiemos el couigo que se va a encaigai ue guaiuai los settings antes ue
salii ue la aplicacion.
,&)8+$$&%)./5&.- Es el settei ue la piopieuau CuiientFile que se encaigai ue llevai el nombie uel
ficheio actual al que se hace alusion. Poui hacei una seiie ue acciones ielacionauas con el
manejo ue ficheios y notificacion uel cambio en el conteniuo ue uicho ficheio.
5*#2./5&.- Este bloque se encaigai ue abiii el ficheio y leei su conteniuo caignuolo en
QPlainTextEuit con setPlainText(). Auems hai touas las notificaciones que iequieia sobie la
caiga uel ficheio, como establecei el nuevo CuiientFile o notificai su accion en el status bai.
,#K&./5&.- Este bloque se encaigai ue abiii el ficheio, esciibii su conteniuo y notificai
igualmente sobie el mismo.
4#:9&(#K&.- Este bloque pueue estai integiauo en los 2 anteiioies, o pueue sei sepaiauo paia
uejai ms claio el couigo. Su funcion seiia, si el uocumento ha siuo mouificauo, muestia una
ventana ue uilogo waining, paia que el usuaiio ueciua si guaiua o no guaiua los cambios. Es
muy tipico en las aplicaciones moueinas.
,)$/--&2<#4&.- Es una bloque simple que extiae el nombie uel ficheio, extiaynuolo uel path
completo.

Las vaiiables piivauas que vamos a usai coiiesponuen con: la piopieuau cuiientFile
uesciita antes, el wiuget cential que es un QPlainTextEuit, los S menus QNenu, las 2 baiias ue
heiiamientas QToolBai y las acciones piopias a los mens QAction. Estas son las vaiiables que
vamos a usai:
QString curFile;
QPlainTextEdit *textEdit;

QMenu *fileMenu;
QMenu *editMenu;
QMenu *helpMenu;

QToolBar *fileToolBar;
QToolBar *editToolBar;

QAction *newAct;
QAction *openAct;
QAction *saveAct;
QAction *saveAsAct;
&'


QAction *exitAct;
QAction *cutAct;
QAction *copyAct;
QAction *pasteAct;
QAction *aboutAct;
QAction *aboutQtAct;
Paia finalizai la ueclaiacion ue la clase NainWinuow, vamos tambin a ieimplementai
una funcion viitual ue QWiuget llamaua closeEvent(QCloseEvent) que nos peimitii inteiceptai
el cieiie ue la aplicacion, paia notificai al usuaiio si el uocumento tiene cambios sin guaiuai, una
caiacteiistica muy usual tambin en aplicaciones moueinas. La vamos a ueclaiai en la zona
piotecteu paia que pueua sei ieimplementaua en hijos que pueuan ueiivaise ue la clase
NainWinuow en futuias aplicaciones.


0PNB6P629?54C2 36 /?42D4238E

A continuacion vamos a vei la implementacion ue touos estos bloques y miembios que
hemos visto anteiioimente.

Comenzamos con el constiuctoi que uefine el inteifaz inicial ue la aplicacion:

MainWindow::MainWindow()
{
textEdit = new QPlainTextEdit;
setCentralWidget(textEdit);

createActions();
createMenus();
createToolBars();
createStatusBar();

readSettings();

connect(textEdit->document(), SIGNAL(contentsChanged()),
this, SLOT(documentWasModified()));

setCurrentFile("");
}

Queuan muy claias touas las acciones que lleva a cabo: establecei al QPlainText como el wiuget
cential, luego cieai las acciones paia los mens, luego cieai los menus, las baiias ue
heiiamientas, la baiia ue estauo, leei los settings ue el ltimo cieiie, conectai la seal ue
cambios en el uocumento con el slot que hemos cieauo paia ello, y establecei como ficheio actual
(CuiientFile) a ninguno.

void MainWindow::closeEvent(QCloseEvent *event)
{
if (maybeSave()) {
writeSettings();
event->accept();
} else {
event->ignore();
}
}

La funcion closeEvent(), es ejecutaua automticamente caua vez que un top-level wiuget es
ceiiauo. Si el evento es aceptauo (accept()) entonces sale sin pioblemas, si es ignoiauo (ignoie())
entonces no es ceiiauo. Aqui sei maybeSave quien muestia la ventana ue eleccion al usuaiio, y
uevolvei un bool ue acueiuo al boton pulsauo:

bool MainWindow::maybeSave()
{
if (textEdit->document()->isModified()) {
QMessageBox::StandardButton ret; // es un int con un codigo
ret = QMessageBox::warning(this, tr("Application"),
tr("El documento ha sido modificado.\n"
"_Quiere guardar los cambios?"),
QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
if (ret == QMessageBox::Save)
&(


return save();
else if (ret == QMessageBox::Cancel)
return false;
}
return true;
}

El iesto uel couigo pueue sei entenuiuo peifectamente con lo que hemos estuuiauo
hasta ahoia. Solo haiemos la intiouuccion a un concepto nuevo que es la funcion
Q0bject::ti(QStiing) que uevuelve la tiauuccion uel aigumento pasauo, y es usauo paia
inteinacionalizai una aplicacion.

Ahoia llego el momento ue hacei la misma aplicacion peio usanuo el Qt Besignei paia
uiseai el inteifaz gifico.


7A6?A B? ?NB45?54C2 RAYO45?P6296

Bacei uso ue Qt Besignei paia hacei una aplicacion, facilita mucho las cosas, no solo
paia uibujai el inteifaz si esto es necesaiio, si no paia cieai los menus, las acciones uel mismo, y
las conexiones con los slots. Pues bien vamos a abiii un nuevo pioyecto, y esta vez si vamos a
cieai el ficheio *.ui , le ponuiemos ue nombie application2. Al abiii el ui veiemos que apaiece un
foimulaiio como ste:



Asi que le aauimos un PlainTextEuit y ocupamos con l touo el iea que nos peimite,
veiemos que en el inspectoi ue objetos ue la ueiecha supeiioi, lo ha puesto como centialWiuget.

vamos a ii iellenauo los mens hacienuo uoble clic sobie "Type Beie" y pulsamos
sobie Auu Sepaiatoi paia aauii un sepaiauoi ue men, poi ejemplo antes uel Salii. Lo que
tenuiemos al final es algo como esto:

'*



Asi iiemos iellenanuo los mens confoime hemos uesciito al piincipio ue este tema, opcion a
opcion. veis que en la paite infeiioi, en el Action Euitoi, empieza a iellenaise el solo como esto:



Bacienuo uoble clic en caua accion, pouemos euitai sus paites ue la siguiente maneia:

Poi supuesto, se ha tenei ya cieauo y caigauo el qic tal como lo vimos en el ejemplo anteiioi,
paia que apaiezcan los iconos. En el inspectoi ue piopieuaues ponemos el statusTip a mano.
vamos a hacei lo mismo con touos los submens, y uejaiemos paia uespus la paite iefeiente a
las conexiones.

Ahoia vamos a cieai los slots que van a iecibii las acciones, excepto los que ya vienen
ue heiencia. Paia ello, hacemos clic ueiecho sobie accion_Nuevo, y elegimos "go to slot", y
pulsamos sobie la seal tiiggeieu(), que es la que vamos a conectai. Inmeuiatamente nos lleva al
couigo uel slot que se acaba ue cieai, *%U#0)/*%U<+&K*U)$/>>&$&267, que se ha cieauo
automticamente. Touos los slots cieauos en el Qt Besignei, llevan esta foima,
on_ActionName_SignalName(). Asi vamos a cieai slots tambin paia abiii, guaiuai, guaiuai
como, aceica ue. El iesto ue acciones las vamos a llevai a slots pieuefiniuos en las clases
coiiesponuientes ue Qt como hemos visto ya.

Los slots que se han cieauo automticamente ue esta maneia son:
')


private slots:
void on_actionAcerca_de_triggered();
void on_actionGuardar_como_triggered();
void on_actionGuardar_triggered();
void on_actionAbrir_triggered();
void on_action_Nuevo_triggered();

y auems se ha estableciuo la conexion automticamente entie la seal tiiggeieu() ue uicha
accion con uichos slots, poi lo que no hace falta estableceilas en el couigo fuente, ya estn en el
*.ui.

Ahoia, nos vamos al Signal & Slots euitoi, uonue esta touo vacio. Pulsamos sobie el
boton veiue +, y lo hacemos justo el nmeio ue veces que conexiones necesitamos paia las
acciones ue los mens que van a slots pieuefiniuos en Qt (son 4). Ahoia vamos a ii iellenanuo
touas las conexiones ue caua accion, con los slots que les coiiesponuen, con lo que una vez lleno
queuaiia ue esta maneia:




Como pueues obseivai no hemos pouiuo ponei la conexion uel aboutQtAct uebiuo a
que no apaiece el ieceivei qApp, poi lo que es paite tenuiemos que poneila en el constiuctoi ue
NainWinuow a mano.

volvamos a activai el Action Euitoi, y ahoia hacemos clic ueiecho en la clase
NainWinuow en el inspectoi ue objetos y elegimos "auu toolbai". Ya tenemos 2 toolbais, la
piimeia la llamamos fileToolBai y la segunua euitToolBai, cambianuo su objectName en el
inspectoi ue piopieuaues. Aiiastianuo los iconos uel Action euitoi ue Nuevo, Abieito y uuaiuai
sobie la piimeia ToolBai, cieamos los S botones ue uicha baiia ue heiiamientas. Bacemos lo
mismo con Coitai, Copiai y Pegai en la segunua baiia ue heiiamientas. El iesultauo final es algo
asi:



Ya tenemos toua la paite gifica constiuiua, y ya solo nos queua ii iellenanuo el
couigo coiiesponuiente ue la clase NainWinuow. Ahoia eligienuo las acciones ue Coitai y Pegai,
vamos a uesactivailas poi uefecto en el panel ue piopieuaues, ueshabilitanuo el cuauio
"enableu". veis que los iconos se vuelven ms apagauos. Y esto es touo lo que se pueue hacei
con el Qt Besignei, el iesto hay que tecleailo a mano.

'!


Si ievisamos el couigo ue mainwinuow.h, veiemos que hay algo nuevo que hace
iefeiencia al conteniuo que hay en el ficheio *.ui, y es el couigo:
namespace Ui {
class MainWindow;
}

private:
Ui::MainWindow *ui;

Lo que uesigna ese couigo es un punteio al inteiface que hay en ui, y poi lo tanto paia
acceuei a los objetos uentio uel mismo, tenuiemos que haceilo uesue ese punteio, lo cual es tan
sencillo como esto:

ui->actionGuardar->setEnabled(false);

que uesactivaiia uiiectamente la accion uuaiuai, y que si piuebas a esciibiilo en cualquiei paite
ue la implementacion ue NainWinuow, veis que el autoiellenauo te va uanuo pistas ue touos los
objetos y miembios accesibles uesue ui.

Bejamos poi tanto como ejeicicio ue iepaso paia el lectoi, la cumplimentacion uel
couigo necesaiio paia que esta aplicacion funcione igual que su antecesoia hecha completamente
en couigo. No obstante te obsequiamos con el couigo uel constiuctoi ue la clase NainWinuow
paia que te siiva como oiientacion:

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);

setCentralWidget(ui->plainTextEdit);

connect(ui->actionAcerca_de_Qt, SIGNAL(triggered()),
qApp, SLOT(aboutQt()));
connect(ui->plainTextEdit, SIGNAL(copyAvailable(bool)),
ui->actionCor_tar, SLOT(setEnabled(bool)));
connect(ui->plainTextEdit, SIGNAL(copyAvailable(bool)),
ui->action_Copiar, SLOT(setEnabled(bool)));

ui->statusBar->showMessage(tr("Preparado"));
readSettings();

connect(ui->plainTextEdit->document(), SIGNAL(contentsChanged()),
this, SLOT(documentWasModified()));

setCurrentFile("");
}


Resumiiemos poi tanto los 7 pasos a seguii paia cieai una aplicacion con ayuua uel Qt
Besignei (foima visual):

1.- Situai el centeiWiuget uebajo uel toolbai y encima uel status bai.
2.- Esciibii touas las opciones uel men piincipal.
S.- Euitai las acciones que se ciean con el men piincipal cumplimentauo paia aauiiles iconos,
status tips, su estauo inicial, etc.
4.- Cieai las toolbai que se iequieian aiiastianuo los iconos ue las acciones sobie aquellas.
S.- Cieai los slots que se iequieian ue las acciones con boton ueiecho-> go to slot, luego uailos ue
alta en el Qt Besignei como miembios ue NainWinuow.
6.- Bacemos touas las conexiones entie las acciones y los slots en el signal-slot euitoi.
7.- Ya pouemos aauii el couigo que haga falta, con ayuua uel nuevo punteio *ui paia uesignai el
uiseo.




'"


)%/" G;
<".-\) " ]-&'-

En el tema 12 ya tocamos el tema uel layout como el meuio meuiante el cual, los wiugets
negociaban el espacio ue la ventana que los contiene, cieanuo una inteiface flexible a mltiples
ciicunstancias como cambio ue iuiomas sin tiuncauo ue palabias, o auaptacion uel u0I a otias
platafoimas. En este capitulo vamos a aauii nuevas clases a este estuuio paia uisponei el
espacio ue una ventana vienuo QSplittei, que ciea baiias que uiviuen una ventana en vaiios
espacios, QSciollAiea, que peimite que una zona pueua veise en paite y el iesto pueua sei
acceuiuo meuiante una baiia ue scioll, QWoikSpace o QNuiAiea que nos intiouucii en las
aplicaciones NBI (multi-uocumento), uonue se pouin abiii ms ue un uocumento a la vez en la
misma ventana.
Como uijimos entonces, touo wiuget ocupa un espacio iectangulai, como una caja, y las
cooiuenauas ue las vitices supeiioi izquieiuo e infeiioi ueiecho se guaiuan en la piopieuau
"geometiy", que pueue sei acceuiua meuiante el gettei geometiy() como vimos en el ejemplo uel
tema anteiioi paia los settings, y pueue sei cambiauo meuiante el settei setueometiy(). Sin
embaigo, nauie usa estos mtouos paia posicionai ue maneia absoluta ningn wiuget uentio ue
la ventana, si no que usa ue layouts paia ello.

(+9?5m63<?K8I9
Esta clase ciea un conjunto ue wiugets hijos que piesentan pginas apilauas, y solo
pueue mostiai una a la vez, ocultanuo el iesto al usuaiio. QStackeuWiuget, es una wiuget que
piovee Qt, y que lleva uentio un QStackeuLayout. No se piovee ue ningn contiol paia que el
usuaiio pueua navegai poi las pginas, asi que esto solo pueue hacei meuiante el uso ue couigo.
Las pginas estn numeiauas uel u en auelante, y pouemos hacei una visible meuiante el settei
setCuiientInuex(page). Paia aveiiguai el inuex ue un wiuget conteniuo en este Layout se usa la
funcion inuex0f(QWiuget), que uevuelve su enteio.
Bien, una ue tantas foimas ue hacei funcionai este Layout, es vinculai las opciones ue un
wiuget con las uifeientes pginas uel stackeu layout. Esto se pueue hacei con un ComboBox, o
una QListWiuget. vamos a vei un ejemplo:
PreferenceDialog::PreferenceDialog(QWidget *parent) : QDialog(parent)
{
//appearancePage, webBrowserPage, mailAndNewsPage, advancedPage
listWidget = new QListWidget;
listWidget->addItem(tr("Apariencia"));
listWidget->addItem(tr("Navegador"));
listWidget->addItem(tr("Correo y foros"));
listWidget->addItem(tr("Avanzado"));

stackedLayout = new QStackedLayout;
stackedLayout->addWidget(appearancePage);
stackedLayout->addWidget(webBrowserPage);
stackedLayout->addWidget(mailAndNewsPage);
stackedLayout->addWidget(advancedPage);

connect(listWidget, SIGNAL(currentRowChanged(int)),
stackedLayout, SLOT(setCurrentIndex(int)));
.
listWidget->setCurrentRow(0);
}

Aqui pieviamente, appeaiancePage, webBiowseiPage, mailAnuNewsPage y auvanceuPage, son
wiugets, poi ejemplo layouts con toua una seiie ue wiugets uentio, que confoiman una ventana
ue uilogo completa. Son aauiuos como wiugets a su vez uel stackeu layout, y lo que hacemos es
vinculai una listWiuget con l meuiante la seal cuiientRowChangeu(int) que vimos en el tema
'#


17, con el settei y auems slot setCuiientInuex(int), ya que ambos pasan un inuice igual (uesue u
a N). Be esta maneia pouemos uisponei espacialmente a ambos wiugets contenenuoies, uentio
ue una ventana ue uilogo ue seleccion ue piefeiencias. Fijate en el uetalle, ue que fijamos la
posicion inicial uel ambos con setCuiientRow(u).
Como se haiia esto mismo en el Qt Besignei.. Pues siguienuo estos sencillos pasos:
1.- Cieai un foimulaiio nuevo basauo en QBialog o en QWiuget.
2.- Aauii un QListWiuget y un QStackeuWiuget al mismo.
S.- Rellenai caua pgina con wiugets y layouts confoime sea necesaiio. (hacienuo clic ueiecho
sobie el layout, y escogienuo "Inseit Page" paia aauii nuevas pginas, y paia navegai poi ellas,
usanuo las flechitas en la zona supeiioi ueiecha).
4.- Conectai ambos wiugets, pulsanuo en el boton "Euit signal" ue aiiiba uel Besignei, y pulsamos
sobie el ListWiuget y aiiastiamos hacia el StackeuWiuget, ue maneia que una flecha los
conectai. Al soltai el iaton apaiecei la ventana paia elegii la seal y el slot que estain
conectauos.


S.- Aauimos los items ue las opciones en el ListWiuget con clic ueiecho->euit items. Luego
ponemos la piopieuau cuiientRow uel listWiuget a u.
Asi ue fcil seiia uiseailo, luego habiia que aauii los botones ue la ventana ue uilogo tipicos,
0K y Cancel (QButtonBox), y ue igual maneia conectailos con la ventana ue uilogo, y conectai
las seales, accepteu() ue paite ue los botones, con accept() uel uilogo, y iejecteu() ue paite ue
'$


los botones, con ieject() uel uilogo. Ya pouiiamos usai este uilogo en la aplicacion completa,
usanuo uialog.exec() paia ejecutailo en mouo moual y que nos uevuelva un valoi con nuestia
seleccion, QBialog::Accepteu o QBialog::Rejecteu.

(+NB4996A
Es un wiuget que contiene otios wiugets, y estos estn sepaiauos poi sepaiauoies. Los
usuaiios pueuen cambiai el tamao ue los wiugets sepaiauos, uesplazanuo los sepaiauoies. Los
wiugets sepaiauos, se van ponienuo uno al lauo uel otio confoime se van cieanuo y segn la
uisposicion.
int main(int argc, char *argv[])
{
QApplication app(argc, argv);

QTextEdit *editor1 = new QTextEdit;
QTextEdit *editor2 = new QTextEdit;
QTextEdit *editor3 = new QTextEdit;

QSplitter splitter(Qt::Horizontal);
splitter.addWidget(editor1);
splitter.addWidget(editor2);
splitter.addWidget(editor3);

splitter.show();

return app.exec();
}

Los splitteis pueuen aniuaise hoiizontales con veiticales y cieai uisposiciones ms complejas.
Los setting pueuen guaiuai la posicion ue los mismos, usanuo giupos en la giabacion ue los
mismos.
void MailClient::writeSettings()
{
QSettings settings("Software Inc.", "Mail Client");

settings.beginGroup("mainWindow");
settings.setValue("size", size());
settings.setValue("mainSplitter", mainSplitter->saveState());
settings.setValue("rightSplitter", rightSplitter->saveState());
settings.endGroup();
}

void MailClient::readSettings() {
QSettings settings("Software Inc.", "Mail Client");

settings.beginGroup("mainWindow");
resize(settings.value("size", QSize(480, 360)).toSize());
mainSplitter->restoreState(settings.value("mainSplitter").toByteArray());
rightSplitter->restoreState(settings.value("rightSplitter").toByteArray());
settings.endGroup();
}

Como uiseai con splitteis en el Qt Besignei.. Es similai a como uisponiamos los wiugets con
layouts veiticales y hoiizontales. Pones 2 o ms wiugets juntos, los seleccionas, y en la baiia ue
heiiamientas supeiioi pouemos elegii, "Layout Boiizontally in Splittei" o "Layout veitically in
Splittei".

(+5A8BB"A6?
Piovee una zona visible (viewpoit) y 2 baiias ue scioll (veitical y hoiizontal). Paia
aauii baiias ue sciolling a un wiuget, solo hay que cieai un objeto QSciollAiea y aauiile uicho
'%


objeto con setWiuget(QWiuget *). Pouemos acceuei al wiuget y sus miembios meuiante
QSciollAiea ::viewpoit() que uevuelve un punteio uel mismo.
int main(int argc, char *argv[])
{
QApplication app(argc, argv);

IconEditor *iconEditor = new IconEditor;
iconEditor->setIconImage(QImage(":/images/mouse.png"));

QScrollArea scrollArea;
scrollArea.setWidget(iconEditor);
scrollArea.viewport()->setBackgroundRole(QPalette::Dark);
scrollArea.viewport()->setAutoFillBackground(true);
scrollArea.setWindowTitle(QObject::tr("Icon Editor"));
scrollArea.show();

return app.exec();
}

QTextEuit y QAbstiactItemview (y ueiivauos), al estai ueiivauos ue QAbstiactSciollAiea, no
iequieien esto paia poseei baiias ue uesplazamiento.

('85mD43R69 K (/?42D4238E
0n uock wiuget es un wiuget que pueue apaicaise en un lauo ue una NainWinuow, o
pueue queuaise flotanuo como una ventana apaite. Las iea ue enganche ue las uock winuows,
en NainWinuow son, una aiiiba, otia abajo, y una a caua lauo uel cential Wiuget.
Estas ventanas tiene su piopio titulo incluso enganchauas a la piincipal, y el usuaiio
pueue moveilas solo cogienuo uel titulo y aiiastianuo ue ellas. Pueuen sei ceiiauas como una
ventana noimal. Con la funcion setWiuget(QWiuget), se aaue un wiuget a un uock winuow.
QNainWinuow, tiene una funcion paia aauii uocks wiugets, que se llama
auuBockWiuget(zona, wiuget).
QDockWidget *shapesDockWidget = new QDockWidget(tr("Shapes"));
shapesDockWidget->setWidget(treeWidget);
shapesDockWidget->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
addDockWidget(Qt::RightDockWidgetArea, shapesDockWidget);

/'0
Toua aplicacion que uentio ue su ventana cential pueua abiii vaiios uocumentos a la
vez, es llamaua una aplicacion NBI. Se hace hacienuo que la clase QWoikspace sea el
centialWiuget, y entonces caua uocumento que se abia, que sea hijo ue QWoikspace.
Suele sei muy tipico que una aplicacion NBI, piovea ue un menu Winuow, que peimite
manejai los uistintos uocumentos, y activailos o uesactivailos, y esa opcion suele sei checkable
inuicanuo en caua momento la ventana uel uocumento que est activa.
MainWindow::MainWindow()
{
workspace = new QWorkspace;
setCentralWidget(workspace);
connect(workspace, SIGNAL(windowActivated(QWidget *)),
this, SLOT(updateMenus()));

createActions();
createMenus();
createToolBars();
createStatusBar();

setWindowTitle(tr("MDI Editor"));
setWindowIcon(QPixmap(":/images/icon.png"));
}
'&



Este es un constiuctoi tipico ue una aplicacion NBI. Conectamos la seal
winuowActivateu() con un slot nuestio que piogiamaiemos que actulizai el conteniuo ue los
mens (poi ejemplo, hacienuo toggle en el men Winuow).
Caua vez que se pulsa en el men Ficheio->Nuevo, no se boiiai el uocumento actual, si
no que se cieai uno nuevo uevolvienuo un punteio al mismo.
El constiuctoi ue los wiugets uocumentos que se abien, uebe ue activai el atiibuto ue
boiiauo al ceiiai, paia evitai los memoiy leaks.
setAttribute(Qt::WA_DeleteOnClose);

Paia pouei manejai caua uocumento, es necesaiio pouei iecupeiai un punteio al
mismo, lo cual seiia imposible sin el uso ue un casting uinmico.
Editor *MainWindow::activeEditor()
{
return qobject_cast<Editor *>(workspace->activeWindow());
}
Aqui, la funcion activeEuitoi ue NainWinuow, pueue iecupeiai el punteio a uicho uocumento (en
este caso es un Euitoi), hacienuo un casting al valoi uevuelto poi QWoikspace::activeWinuow(),
que es un QWiuget *. Si no hay activa ninguna ventana entonces uevolvei un N0LL pointei, poi
lo que es impoitante que cuanuo se llame a este mtouo uesue cualquiei paite, se obseive si
uevuelve un valoi nulo.
En este tema vamos a hacei que nuestia aplicacion euitoia ue texto uel tema 2u, pueua
sei NBI, peio lo haiemos usanuo QNuiAiea y QNuiSubWinuow, como nuevo enfoque a las
aplicaciones NBI.















''































'(


)%/" GG
>"+%+ '% '")-+

La gian mayoiia ue aplicaciones ue gestion, suelen guaiuai toua la ingente cantiuau ue
uatos que maneja en un motoi ue base ue uatos. Qt en su veision piivativa incluye los uiiveis ue
la mayoiia ue motoies ue uatos. Qt en su veision 0pen Souice, no incluye aquellos que tienen
licencia. Paia aquellos usuaiios acostumbiauos a usai la sintaxis SQL, Qt piovee ue la clase
QSqlQueiy. Paia usuaiios que piefieien evitai esto, y uesean tiabajai a un nivel ms alto, hay 2
mouelos incluiuos en las clases QSqlTableNouel y QSqlRelationalTableNouel, las cuales ya
mencionamos en el tema 16.

782659?A 6 4296AA8R?A 582 +(<
vamos a empezai tiatanuo la piimeia foima ue tiabajai con bases ue uatos, uonue
conectaiemos con una base ue uatos NySQL, y la inteiiogaiemos meuiante la sintaxis SQL.
bool createConnection()
{
QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");
db.setHostName("localhost");
db.setDatabaseName("megafonia");
db.setUserName("root");
db.setPassword("admin");
if (!db.open()) {
QMessageBox::critical(0, QObject::tr("Database Error"),db.lastError().text());
return false;
}
return true;
}

Esta es una conexion a la base ue uatos NySQL, en el host local, con nombie megafonia,
con el usuaiio y passwoiu uel usuaiio que tenga acceso a la misma, ue acueiuo a las queiies SQL
que vamos a enviaile.
Lo siguiente sei enviaile una queiy, y esto se hace asi:
QSqlQuery query;
query.exec("SELECT almacen, ntiendas FROM almacenes");
while (query.next()) {
QString almacen = query.value(0).toString();
int ntiendas = query.value(1).toInt();
qDebug("Nombre: %s - Tiendas: %d",qPrintable(almacen),ntiendas);
}

Como pueues vei la funcion exec() ejecuta el queiy, next() iecoiie el punteio poi la tabla
iespuesta, y value es una lista Qvaiiant, uonue los campos tienen inuices uel u en auelante, ue
esta foima value(u) contenuiia el campo almacen que es el piimeio en la iespuesta, y en value(1)
estaiia el campo ntienuas.
Paia que este couigo compile bien, es necesaiio que se aaua el mouulo sql al pioyecto,
es uecii al ficheio *.pio con la linea:
QT += sql



(*


/n7 ?NB45?38 ? >?:6: 36 '?98:
Como ya vimos en el tema 16, pouemos combinai una vista y un mouelo que acceua a la
base ue uatos como su fuente. Aqui la vista ms tipica paia vei una tabla ue uatos es QTableview,
y el mouelo pueue sei QSqlTableNouel, si vamos a vei una tabla en concieto, sin ms.
Las funciones ms tipicas ue este mouelo, son:
setTable(QStiing tableName) -> que fija la tabla ue la base ue uatos a fijai
setEuitStiategy(stiategy) -> Besciibe la estiategia a usai paia actualizai los uatos ue la base ue
uatos, que pueue sei: 0nFieluChange (touo cambio en la vista es inmeuiato en la base ue uatos),
0nRowChange(se guaiuan los uatos al cambiai ue fila o iegistio), 0nNanualSubmit (se guaiua en
una cache hasta que el piogiama ejecuta un submitAll() o un ieveitAll() ).
select() -> Rellena el mouelo con los uatos ue la tabla.
setBeaueiBata(int section, Qt::oiientation, Qvaiiant heauei) -> Naica los nombies ue las
cabeceias.
cleai() -> boiia el mouelo ue touos los uatos que pieviamente tuvieia caigauos en su cach
(buffei).
Paia los siguientes ejemplos vamos a usai una base ue uatos giabaua en SQLite en un
ficheio que llamaiemos uatabase.ub, en los ejeicicios veiemos como es esta base ue uatos.
#include <QtGui>
#include <QtSql>

static bool createConnection()
{
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("database.db");
if (!db.open()) {
QMessageBox::critical(0, "No se puede abrir la base de datos",
"Imposible establecer una conexi_n con la base de datos.\n"
"Pulsar Cancel para salir.", QMessageBox::Cancel);
return false;
}
return true;
}

void initializeModel(QSqlTableModel *model)
{
model->setTable("person");
model->setEditStrategy(QSqlTableModel::OnManualSubmit);
model->select();
model->setHeaderData(0, Qt::Horizontal, "ID");
model->setHeaderData(1, Qt::Horizontal, "First name");
model->setHeaderData(2, Qt::Horizontal, "Last name");
}

QTableView *createView(const QString &title, QSqlTableModel *model)
{
QTableView *view = new QTableView;
view->setModel(model);
view->setWindowTitle(title);
return view;
}

int main(int argc, char *argv[])
{
QApplication app(argc, argv);
if (!createConnection()) return 1;
QSqlTableModel model;
initializeModel(&model);
QTableView *view1 = createView("Table Model (Vista 1)", &model);
QTableView *view2 = createView("Table Model (Vista 2)", &model);
view1->show();
view2->move(view1->x() + view1->width() + 20, view1->y()); view2->show();
return app.exec();
}
()


Peio lo ms noimal es que tengamos vaiias tablas, ielacionauas entie ellas meuiante un
iuentificauoi numiico (en SQLite meuiante el iowiu), y lo que queiemos es piesentai una tabla
uonue apaiece la ielacion entie ellas. Paia ello usaiemos el mouelo QSqlRelationalTableNouel.
veamos un ejemplo similai con la misma base ue uatos y las S tablas.
#include <QtGui>
#include <QtSql>

static bool createConnection()
{
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("database.db");
if (!db.open()) {
QMessageBox::critical(0, "No se puede abrir la base de datos",
"Imposible establecer una conexi_n con la base de datos.\n"
"Pulsar Cancel para salir.", QMessageBox::Cancel);
return false;
}
return true;
}

void initializeModel(QSqlRelationalTableModel *model)
{
model->setTable("employee");
model->setEditStrategy(QSqlTableModel::OnManualSubmit);
model->setRelation(2, QSqlRelation("city", "id", "name"));
model->setRelation(3, QSqlRelation("country", "id", "name"));
model->setHeaderData(0, Qt::Horizontal, "ID");
model->setHeaderData(1, Qt::Horizontal, "Name");
model->setHeaderData(2, Qt::Horizontal, "City");
model->setHeaderData(3, Qt::Horizontal, "Country");
model->select();
}

QTableView *createView(const QString &title, QSqlTableModel *model)
{
QTableView *view = new QTableView;
view->setModel(model);
view->setItemDelegate(new QSqlRelationalDelegate(view));
view->setWindowTitle(title);
return view;
}

void createRelationalTables()
{
QSqlQuery query;
query.exec("create table employee(id int primary key, name varchar(20), city int,
country int)");
query.exec("insert into employee values(1, 'Espen', 5000, 47)");
query.exec("insert into employee values(2, 'Harald', 80000, 49)");
query.exec("insert into employee values(3, 'Sam', 100, 1)");
query.exec("create table city(id int, name varchar(20))");
query.exec("insert into city values(100, 'San Jose')");
query.exec("insert into city values(5000, 'Oslo')");
query.exec("insert into city values(80000, 'Munich')");
query.exec("create table country(id int, name varchar(20))");
query.exec("insert into country values(1, 'USA')");
query.exec("insert into country values(47, 'Norway')");
query.exec("insert into country values(49, 'Germany')");
}

int main(int argc, char *argv[])
{
QApplication app(argc, argv);
if (!createConnection()) return 1;
createRelationalTables();
QSqlRelationalTableModel model;
initializeModel(&model);
QTableView *view = createView("Relational Table Model", &model);
view->show();
return app.exec();
}


(!































("


)%/" GF
$%'%+ )7#p0#

7B46296 )7# W()5N+85m69X
Explicai los piotocolos TCPIP no es el objetivo ue este libio, poi lo que se ua poi
supuesto el pievio conocimiento y uifeienciacion entie piotocolos TCP y 0BP. Asi que
comenzaiemos con la implementacion ue un cliente TCP.
Se tiata ue un seiviuoi que una siive poi un pueito TCP, fiases ue la foituna, como las ue
los iollitos ue piimaveia. Asi que cuanuo el cliente se conecta, el seiviuoi le siive una fiase al
azai sobie su foituna.
vamos a usai QBataStieam paia enviai los uatos uesue el seiviuoi, y tambin paia
iecogeilas en el cliente. El flujo ue uatos es muy sencillo, tan solo lleva como cabeceia un quint16
con la longituu uel mensaje que le sigue, luego viene una cauena con la fiase.
Bien, en piogiamacion ue sockets hay 2 apioximaciones uistintas en cuanto a si la
conexion es bloqueante o no-bloqueante. 0na conexion bloqueante, es aquella que espeia y no
hace naua hasta que el seiviuoi ha iesponuiuo y ha siuo estableciua poi completo. Suele usaise
en aplicaciones multi-hilo o ue consola uonue se hai uso ue funciones como
QTcpSocket::waitFoiConnecteu. En nuestio caso, vamos a usai la apioximacion no-bloqueante,
uonue llamaiemos a la funcion connectToBost(), y seguiiemos a lo nuestio, y meuiante una
conexion ue Qt, una vez el socket se establezca QTcpSocket emitii la seal connecteu().
vamos a ueiivai la clase Cliente ue QBialog, y le vamos a aauii los slots necesaiios y las
piopieuaues piivauas necesaiias.
class Client : public QDialog
{
Q_OBJECT

public:
Client(QWidget *parent = 0);

private slots:
void requestNewFortune();
void readFortune();
void displayError(QAbstractSocket::SocketError socketError);
void enableGetFortuneButton();

private:
QLabel *hostLabel;
QLabel *portLabel;
QLineEdit *hostLineEdit;
QLineEdit *portLineEdit;
QLabel *statusLabel;
QPushButton *getFortuneButton;
QPushButton *quitButton;
QDialogButtonBox *buttonBox;

QTcpSocket *tcpSocket;
QString currentFortune;
quint16 blockSize;
};

Apaite ue los componentes visuales, vamos a usai la cauena cuiientFoitune paia guaiuai la fiase
actual, y su tamao en blockSize. Los slots que vamos a usai son:
iequestNewFoitune -> que va a sei ejecutauo cuanuo se haga clic en el boton ue "vei mi foituna".
(#


ieauFoitune -> que sei uispaiauo cuanuo el socket TCP meuiante el QBataStieam, envie la seal
QI0Bevice::ieauyReau(), uicienuo que nuevos uatos estn uisponibles en el uispositivo ue
entiauasaliua.
uisplayEiioi -> va a estai conectauo con la seal eiioi() que se uispaia si hay eiioi en la
conexion.
enableuetFoituneButton -> este es un meio slot ue u0I paia que se habilite un boton.
vamos ahoia a poi la implementacion uel constiuctoi que es uonue se inicia el socket:
CllenL::CllenL(CWldgeL *parenL)
: Culalog(parenL)
[
hosLLabel = new CLabel("&l Servldor:"),
porLLabel = new CLabel("&uerLo:"),
// 8usca Lodas las dlrecclones del hosL acLual
CSLrlng lpAddress,
CLlsL<CPosLAddress> lpAddressesLlsL = CneLworklnLerface::allAddresses(),
// va a usar la prlmera l no localhosL (127.0.0.1) Llpo lv4
for (lnL l = 0, l < lpAddressesLlsL.slze(), ++l) [
lf (lpAddressesLlsL.aL(l) != CPosLAddress::LocalPosL &&
lpAddressesLlsL.aL(l).Lolv4Address()) [
lpAddress = lpAddressesLlsL.aL(l).LoSLrlng(),
break,
}
}
// sl no encuenLra nlnguna usar la localhosL (127.0.0.1)
lf (lpAddress.lsLmpLy())
lpAddress = CPosLAddress(CPosLAddress::LocalPosL).LoSLrlng(),
hosLLlneLdlL = new CLlneLdlL(lpAddress),
porLLlneLdlL = new CLlneLdlL,
porLLlneLdlL->seLvalldaLor(new ClnLvalldaLor(1, 63333, Lhls)),
hosLLabel->seL8uddy(hosLLlneLdlL),
porLLabel->seL8uddy(porLLlneLdlL),
sLaLusLabel = new CLabel(("LsLe e[emplo requlere que usLed e[ecuLe el lorLune server")),
geLlorLune8uLLon = new Cush8uLLon("ver ml lorLuna"),
geLlorLune8uLLon->seLuefaulL(Lrue),
geLlorLune8uLLon->seLLnabled(false),
qulL8uLLon = new Cush8uLLon("Sallr"),
buLLon8ox = new Culalog8uLLon8ox,
buLLon8ox->add8uLLon(geLlorLune8uLLon, Culalog8uLLon8ox::AcLlon8ole),
buLLon8ox->add8uLLon(qulL8uLLon, Culalog8uLLon8ox::8e[ecL8ole),
LcpSockeL = new C1cpSockeL(Lhls),

connecL(hosLLlneLdlL, SlCnAL(LexLChanged(CSLrlng)),Lhls, SLC1(enableCeLlorLune8uLLon())),
connecL(porLLlneLdlL, SlCnAL(LexLChanged(CSLrlng)),Lhls, SLC1(enableCeLlorLune8uLLon())),
connecL(geLlorLune8uLLon, SlCnAL(cllcked()),Lhls, SLC1(requesLnewlorLune())),
connecL(qulL8uLLon, SlCnAL(cllcked()), Lhls, SLC1(close())),
connecL(LcpSockeL, SlCnAL(ready8ead()), Lhls, SLC1(readlorLune())),
connecL(LcpSockeL, SlCnAL(error(CAbsLracLSockeL::SockeLLrror)),Lhls, SLC1(dlsplayLrror(CAbsLracLSockeL::SockeLLrror))),

CCrldLayouL *malnLayouL = new CCrldLayouL,
malnLayouL->addWldgeL(hosLLabel, 0, 0),
malnLayouL->addWldgeL(hosLLlneLdlL, 0, 1),
malnLayouL->addWldgeL(porLLabel, 1, 0),
malnLayouL->addWldgeL(porLLlneLdlL, 1, 1),
malnLayouL->addWldgeL(sLaLusLabel, 2, 0, 1, 2),
malnLayouL->addWldgeL(buLLon8ox, 3, 0, 1, 2),
seLLayouL(malnLayouL),
seLWlndow1lLle("CllenLe 1C")),
porLLlneLdlL->seLlocus(),
}
Aqui a paite ue los wiugets visuales, inicializamos la IP uel oiuenauoi uonue estamos en la
LineEuit, tambin le aauimos un valiuauoi al LineEuit uel pueito paia que no aumita pueitos
fueia uel iango ue 1-6SSSS. Se inicializa el socket y se hacen las conexiones Qt entie slots y
seales comentauas antes.
($


Cuanuo se pulsa el boton ue vei Ni Foituna, se uispaia el slot coiiesponuiente que
establece la conexion con el seiviuoi ue esta maneia:
void Client::requestNewFortune()
{
getFortuneButton->setEnabled(false);
blockSize = 0;
tcpSocket->abort();
tcpSocket->connectToHost(hostLineEdit->text(),portLineEdit->text().toInt());
}
Inicializamos la piopieuau blockSize con el tamao a u, luego aboita la conexion actual si la hay,
ieseteanuo el socket, luego conecta con el host uanuo su uiieccion IP y pueito.
Cuanuo el socket ya haya siuo conectauo coiiectamente, y haya uatos nuevos en el
uispositivo, entonces se lanzai el slot coiiesponuiente:
void Client::readFortune()
{
QDataStream in(tcpSocket);
in.setVersion(QDataStream::Qt_4_6);

if (blockSize == 0) {
if (tcpSocket->bytesAvailable() < (int)sizeof(quint16))
return;
in >> blockSize;
}

if (tcpSocket->bytesAvailable() < blockSize)
return;

QString nextFortune;
in >> nextFortune;

if (nextFortune == currentFortune) {
QTimer::singleShot(0, this, SLOT(requestNewFortune()));
return;
}

currentFortune = nextFortune;
statusLabel->setText(currentFortune);
getFortuneButton->setEnabled(true);
}
Los uatos, no tienen poi qu venii touos ue golpe, y poi tanto iequieia ue vaiias ejecuciones ue
este slot, paia teneilos touos. Poi ello, si es la piimeia lectuia (blockSize == u), y si los bytes que
estn piepaiauos paia sei leiuos son menos que 2 bytes, el tamao uel heauei que inuica el
tamao ue la fiase, entonces salimos uel slot y espeiamos a que nos llamen con ms uatos. Si hay
ms uatos, pues leemos piimeio el blockSize. Luego igualmente salimos uel slot, mientias no
estn touos los uatos uisponibles. Finalmente leemos el mensaje que iecogemos en una cauena
QStiing. Si el mensaje es el mismo que el anteiioi que nos uio el seiviuoi, entonces usamos un
Timei ue nico uispaio, paia que uispaie ue nuevo el slot iequestNewFoitune que ya
uesciibimos antes, piuienuo un mensaje nuevo.
Finalmente vamos a vei el couigo que va a tiatai los uifeientes eiioies ue conexion:
void Client::displayError(QAbstractSocket::SocketError socketError)
{
switch (socketError) {
case QAbstractSocket::RemoteHostClosedError:
break;
case QAbstractSocket::HostNotFoundError:
QMessageBox::information(this, "Cliente TCP","No se encontr el servidor.");
break;
case QAbstractSocket::ConnectionRefusedError:
QMessageBox::information(this,"Cliente TCP","Conexin rechazada por el
cliente. Servidor apagado.");
break;
default:
QMessageBox::information(this, "Cliente TCP",
QString("Error: %1.")
.arg(tcpSocket->errorString()));
}
getFortuneButton->setEnabled(true);
}
(%


No hay comentaiios que aauii a esto.

+6AV438A )7# W()5N+85m69X
El seiviuoi, es tambin ueiivauo ue QBialog. Su nico slot es senuFoitune, que est
conectauo a la seal newConnection().
class Server : public QDialog
{
Q_OBJECT

public:
Server(QWidget *parent = 0);

private slots:
void sendFortune();

private:
QLabel *statusLabel;
QPushButton *quitButton;
QTcpServer *tcpServer;
QStringList fortunes;
};

La implementacion uel constiuctoi es muy simple:
Server::Server(QWidget *parent)
: QDialog(parent)
{
statusLabel = new QLabel;
quitButton = new QPushButton("Salir");
quitButton->setAutoDefault(false);
tcpServer = new QTcpServer(this);
if (!tcpServer->listen()) {
QMessageBox::critical(this, "Servidor TCP",
QString("Imposible iniciar servidor: %1.")
.arg(tcpServer->errorString()));
close();
return;
}
QString ipAddress;
QList<QHostAddress> ipAddressesList = QNetworkInterface::allAddresses();
for (int i = 0; i < ipAddressesList.size(); ++i) {
if (ipAddressesList.at(i) != QHostAddress::LocalHost &&
ipAddressesList.at(i).toIPv4Address()) {
ipAddress = ipAddressesList.at(i).toString();
break;
}
}
if (ipAddress.isEmpty())
ipAddress = QHostAddress(QHostAddress::LocalHost).toString();
statusLabel->setText(tr("Servidor corriendo en \n\nIP: %1\npuerto: %2\n\n"
"Ejecute el cliente TCP ahora.")
.arg(ipAddress).arg(tcpServer->serverPort()));
fortunes << tr("Has llevado una vida de perros. Bajate del sofa.")
<< tr("Tienes que pensar en el ma_ana.")
<< tr("Te ha sorprendido una sonido fuerte.")
<< tr("Tendr_s hambre dentro de una hora.")
<< tr("Tienes nuevo correo.");
connect(quitButton, SIGNAL(clicked()), this, SLOT(close()));
connect(tcpServer, SIGNAL(newConnection()), this, SLOT(sendFortune()));
QHBoxLayout *buttonLayout = new QHBoxLayout;
buttonLayout->addStretch(1);
buttonLayout->addWidget(quitButton);
buttonLayout->addStretch(1);
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addWidget(statusLabel);
mainLayout->addLayout(buttonLayout);
setLayout(mainLayout);
setWindowTitle("Servidor TCP");
}

(&


Apaite ue inicializai la u0I y ue buscai la IP local como el cliente, solamente inicia la escucha ue
clientes con listen() y conecta la seal newConnection() con el slot que va a enviai las fiases:
void Server::sendFortune()
{
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_4_6);

out << (quint16)0;
out << fortunes.at(qrand() % fortunes.size());
out.device()->seek(0);
out << (quint16)(block.size() - sizeof(quint16));

QTcpSocket *clientConnection = tcpServer->nextPendingConnection();
connect(clientConnection, SIGNAL(disconnected()),
clientConnection, SLOT(deleteLater()));

clientConnection->write(block);
clientConnection->disconnectFromHost();
}
0na vez iniciauo el BataStieam como un ByteAiiay, piimeio ponemos en el buffei uel mismo la
cabeceia a u, luego meuiante una funcion ianuom, se elije una fiase al azai, y se envia al buffei,
luego iebobinamos a la posicion u "out.device()->seek(0) , le ponemos el tamao ue solo la
fiase (poi eso iestamos al tamao uel bloque, el tamao ue la cabeceia - 2 bytes).
Llamanuo a nextPenuingConnection(), se uevuelve el socket que ha siuo conectauo.
Conectamos la seal ue uisconnecteu al slot Q0bject::ueleteLatei(), que hace que si hay
uesconexion uel socket, el objeto que iepiesenta uicha conexion sea boiiauo poi Qt.
Ya pouemos enviai el bloque completo, poi uicho socket conectauo, y una vez hecho, ya
pouemos uesconectai al cliente, y se boiiai el objeto uel socket como acabamos ue vei.

%P4:8A \'# W(\3N+85m69X
El emisoi ue uatagiamas 0BP va a usai un QTimei paia caua segunuo enviai paquetes
poi un pueito. veamos la implementacion completa:
Sender::Sender(QWidget *parent)
: QDialog(parent)
{
statusLabel = new QLabel("Preparado para enviar datagramas por el puerto 45454");
startButton = new QPushButton("Enviar");
quitButton = new QPushButton("Salir");
buttonBox = new QDialogButtonBox;
buttonBox->addButton(startButton, QDialogButtonBox::ActionRole);
buttonBox->addButton(quitButton, QDialogButtonBox::RejectRole);

timer = new QTimer(this);
udpSocket = new QUdpSocket(this);
messageNo = 1;

connect(startButton, SIGNAL(clicked()), this, SLOT(startBroadcasting()));
connect(quitButton, SIGNAL(clicked()), this, SLOT(close()));
connect(timer, SIGNAL(timeout()), this, SLOT(broadcastDatagram()));

QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addWidget(statusLabel);
mainLayout->addWidget(buttonBox);
setLayout(mainLayout);
setWindowTitle("Emisor UDP");
}



void Sender::startBroadcasting()
{
startButton->setEnabled(false);
timer->start(1000);
}

('


void Sender::broadcastDatagram()
{
statusLabel->setText(QString("Enviando datagrama %1").arg(messageNo));
QByteArray datagram = "Mensaje enviado " + QByteArray::number(messageNo);
udpSocket->writeDatagram(datagram.data(), datagram.size(),
QHostAddress::Broadcast, 45454);
++messageNo;
}

Iniciamos el timei con stait(1uuu) una vez apietamos el boton ue Enviai, como tenemos
conectaua la seal uel timei, timeout() con bioaucastBatagiam, sta se encaiga ue esciibii el
uatagiama a enviai con wiiteBatagiam(uatos, tamao_uatos, IP_ieceptoi, pueito). Nuy sencillo
como vemos.

$656N98A \'# W(\3N+85m69X
El ieceptoi, meiamente vincula el pueito y la uiieccion IP uel inteifaz ue ieu poi uonue
va a escuchai con binu(). Aqui ue nuevo conectamos QI0Bevice::ieauyReau(), que nos inuica que
hay nuevos uatos espeianuo sei leiuos, con nuestio slot ue lectuia piocessPenuingBatagiams.
Esto lo hace meuiante un bucle usanuo hasPenuingBatagiams() paia sabei si an queua
algo poi piocesai. La funcion penuingBatagiamSize() nos uevuelve los bytes que queuan
penuientes ue lectuia. Con ieauBatagiam(uatos, tamao) leemos los uatos que se ponuin en
QByteAiiay::uata().
veamos la implementacion:
Receiver::Receiver(QWidget *parent)
: QDialog(parent)
{
statusLabel = new QLabel("Escuchando mensajes enviados");
quitButton = new QPushButton("Salir");

udpSocket = new QUdpSocket(this);
udpSocket->bind(45454, QUdpSocket::ShareAddress);

connect(udpSocket, SIGNAL(readyRead()),this, SLOT(processPendingDatagrams()));
connect(quitButton, SIGNAL(clicked()), this, SLOT(close()));

QHBoxLayout *buttonLayout = new QHBoxLayout;
buttonLayout->addStretch(1);
buttonLayout->addWidget(quitButton);
buttonLayout->addStretch(1);
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addWidget(statusLabel);
mainLayout->addLayout(buttonLayout);
setLayout(mainLayout);
setWindowTitle("Receptor UDP");
}

void Receiver::processPendingDatagrams()
{
while (udpSocket->hasPendingDatagrams()) {
QByteArray datagram;
datagram.resize(udpSocket->pendingDatagramSize());
udpSocket->readDatagram(datagram.data(), datagram.size());
statusLabel->setText(QString("Datagrama
recibido:\"%1\"").arg(datagram.data()));
}
}

Con la ayuua uel tema siguiente, que tiata ue la piogiamacion concuiiente o multi-hilo,
vamos a implementai el ejemplo uel seiviuoi TCP, peio esta vez con mltiples hilos paia pouei
manejai a muchos clientes a la vez.

((


)%/" G*
#$-^$"/"70Q& 7-&7\$$%&)%

0na aplicacion noimalmente usa un solo hilo ue ejecucion, uonue lleva a cabo una sola
taiea a la vez. Peio existe la posibiliuau ue que la taiea piincipal, geneie nuevos hilos ue
ejecucion inuepenuientes, y que estos se comuniquen con la taiea piincipal, o que tiabajen juntos
en una misma cosa, tenienuo que sincionizai su tiabajo. No es nuestia iuea, explicai el tiasfonuo
ue la piogiamacion multi-hilo en este libio, ya que eso peitenece a un bagaje que se supone ya
auquiiiuo, lo que si vamos es a explicai ue qu maneia Qt implementa las aplicaciones ms
tipicas multi-hilo.

()TA6?3
Esta es la clase que piovee ue hilos ue maneia multiplatafoima. Caua objeto ue esta clase
iepiesenta un hilo ue ejecucion uifeiente a los uems y uifeiente al piincipal que se inicia y se
teimina con main(). 0n hilo compaite uatos con otios hilos, peio se ejecuta ue maneia
inuepenuiente ue los uems. En vez ue comenzai en main() como el hilo piincipal, los hilos
QThieaus comienzan y teiminan en su funcion iun(). Asi que iun() ejecutaiia un hilo e iniciaiia
su piopio bucle ue eventos con exec(), como hace main().
Paia cieai tus piopios hilos, solo hay que ueiivai una clase ue QThieau y ieimplementai
la funcion iun(), con las taieas que este hilo vaya a ejecutai.
class MyThread : public QThread
{
public:
void run();
};

void MyThread::run()
{
QTcpSocket socket;
// conecta las seales de QTcpSocket
...
socket.connectToHost(hostName, portNumber);
exec();
}

Esto seiia un hilo que conecta un socket con un host y luego inicia su piopio bucle ue
eventos. Paia comenzai la ejecucion ue un hilo, una vez se ha instanciauo en el hilo piincipal, es
usanuo la funcion stait(). Recueiua instanciai caua hilo, ponienuo como aigumento pauie al hilo
uel que nace, ue esa maneia, cuanuo el pauie finalice, touos los hilos cieauos ue l se boiiain
tambin, evitanuo memoiy leaks. La ejecucion ue un hilo acaba cuanuo se sale ue iun(), igual que
un piogiama cuanuo teimina main().
QThieau notifica con seales cuanuo un hilo, comienza (staiteu()) o finaliza (finisheu()).
Tambin se pueuen usai los getteis isFinisheu() o isRunning() paia sabei si ha finalizauo o an
esta coiiienuo.
No se pueuen usai wiugets en un hilo. Si se pueuen usai QTimeis y sockets, y se pueuen
conectai seales y slots entie uifeientes hilos.
Paia vei un uso ieal ue esta concuiiencia ue hilos, vamos a vei como queuaiia el couigo
uel seiviuoi TCP uel tema anteiioi, ue maneia que pueua aumitii mltiples conexiones ue
clientes, caua una en un hilo inuepenuiente.
)**


Como los wiugets, hemos uicho que no pueuen coiiei en un hilo, han ue coiiei en la
taiea piincipal que inicia main(), ha ue sepaiaise el couigo que geneia toua la inteifaz gifica y
que inicia la escucha con listen().
FortuneThread::FortuneThread(int socketDescriptor, const QString &fortune, QObject
*parent)
: QThread(parent), socketDescriptor(socketDescriptor), text(fortune)
{
}

void FortuneThread::run()
{
QTcpSocket tcpSocket;
if (!tcpSocket.setSocketDescriptor(socketDescriptor)) {
emit error(tcpSocket.error());
return;
}

QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_4_0);
out << (quint16)0;
out << text;
out.device()->seek(0);
out << (quint16)(block.size() - sizeof(quint16));

tcpSocket.write(block);
tcpSocket.disconnectFromHost();
tcpSocket.waitForDisconnected();
}
Ahoia, hemos cieauo una clase hilo uel seiviuoi que envia las fiases y en iun() es uonue se
encaiga ue hacei touo lo que hace, uesue que es uespeitauo paia conectaise con el cliente, hasta
que envia la fiase, se uesconecta y espeia la uesconexion (mouo bloqueo). Cieamos un
QTcpSocket y lo asociamos al uesciiptoi ue socket que nos va a pasai el seiviuoi
(socketBesciiptoi), que iuentifica a cual ue los clientes nos vamos a conectai. Bien, esto es lo que
hace el hilo que uespacha a un cliente.
FortuneServer::FortuneServer(QObject *parent)
: QTcpServer(parent)
{
fortunes << tr("Has llevado una vida de perros. Bajate del sofa.")
<< tr("Tienes que pensar en el ma_ana.")
<< tr("Te ha sorprendido una sonido fuerte.")
<< tr("Tendr_s hambre dentro de una hora.")
<< tr("Tienes nuevo correo.");
}

void FortuneServer::incomingConnection(int socketDescriptor)
{
QString fortune = fortunes.at(qrand() % fortunes.size());

FortuneThread *thread = new FortuneThread(socketDescriptor, fortune, this);
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
thread->start();
}

Y aqui est la paite piincipal uel seiviuoi, y esta vez se ueiiva ue QTcpSeivei, asi el couigo que
ponuiiamos en el hilo piincipal, cieaiia un seiviuoi FoituneSeivei al que ponemos a escuchai
con listen(), cuanuo un cliente conectaia su socket con l, automticamente se enviaiia la
ejecucion a incommingConnection, que pasa como paimetio el enteio que iepiesenta el
uesciiptoi uel socket conectauo. Y en esta funcion cieamos un hilo ue ejecucion paia uespachai
al cliente, como hemos visto aiiiba, que pasaiia el uesciiptoi uel socket TCP paia que no se
confunua ue cliente, y la fiase a enviaile. Tambin conectamos la seal finisheu() ue uicho hilo
con su boiiauo, paia que cuanuo acabe su ejecucion sea boiiauo, y finalmente iniciamos uicho
hilo con stait().


)*)


+425A824q?54C2 36 T4B8:
Ya hemos visto el ejemplo ms sencillo ue hilos, uonue un piogiama piincipal, geneia
hilos que hacen cosas uifeientes, y uonue no hay inteiaccion entie los hilos. Peio, hay casos
uonue vaiios hilos pueuen compaitii uatos o couigo ue maneia que pueua esto afectai al
iesultauo.
vamos a ponei 2 supuestos iesueltos ue maneia uifeiente. Supongamos que el couigo ue
vaiios hilos acceue a la vez al couigo que aumenta un contauoi comn. Pouiia ocuiiii que un hilo
acceua al valoi antes ue inciementailo, mientias otio hilo ya lo esta inciementanuo, ue maneia
que ambos uejaiian el mismo iesultauo en el contauoi, cuanuo uebieian contaise el paso ue los 2
hilos ue maneia inuepenuiente. La nica foima ue iesolvei esto, es usai un Nutex, es uecii una
zona bloqueaua, a uonue solo un hilo pueue entiai a la vez, ue esta maneia el hilo que entia,
bloquea esa zona, solo l iecoge el valoi uel contauoi ahoia, y lo aumenta, luego sale ue la zona,
peimitienuo que otio hilo entie, y asi, se evitaiia el pioblema inicial.
En Qt esto es hecho con la clase QNutex, que se ueclaiaiia como piivaua uentio uel
QThieau, y llamanuo a la funcion lock() se piouuce el bloqueo, y llamanuo a la funcion unlock() el
uesbloqueo ue la zona.
void Thread::run()
{
mutex.lock();
counter++;
mutex.unlock();
}

Paia ms comouiuau se cieo QNutexLockei(QNutex *) que el objeto que ciea, al nacei bloquea el
mutex, y al boiiaise, uesbloquea el mutex. Be esta maneia el mismo couigo queuaiia asi ue
simple:
void Thread::run()
{
QMutexLocker locker(&mutex);
counter++;
}

El segunuo supuesto, se tiata uel tipico pioblema uel piouuctoi-consumiuoi, uonue 2
hilos compaiten un mismo buffei ue memoiia, uonue un esciibe y el otio lee ue la siguiente
maneia. El hilo piouuctoi, esciibe en uicho buffei hasta que llega a su final, y una vez alli vuelve
ue nuevo al piincipio paia seguii esciibienuo. El hilo consumiuoi, lee lo que el otio esciibe
confoime es piouuciuo y lo saca poi la saliua estnuai ue eiioi (ceii).
Si usiamos solamente un mutex paia bloqueai el acceso simultneo al buffei, bajaiia la
piouuctiviuau uel mismo, ya que no peimitiiiamos acceuei al buffei a uno ue los hilos, mientias
el otio, est tiabajanuo en l, cuanuo iealmente no habiia pioblema alguno, si caua uno tiabajaia
en zonas uifeientes en touo momento.
Paia iesolveilo vamos a usai 2 QWaitConuition y 1 QNutex. veamos antes qu es
QWaitConuition.
QWaitConuition, piovee una vaiiable conuicion paia sincionizai hilos. Los hilos se
queuan en espeia cuanuo llegan a la funcion wait(&mutex). Wait lo que hace es que un mutex
pieviamente bloqueauo, es uesbloqueauo y el hilo, se queua en espeia, hasta que otio hilo lo
uespieite, cuanuo es uespeitauo, el mutex vuelve a bloqueaise y el hilo sigue la ejecucion
uespus ue wait(). Paia uespeitai a los hilos que espeian, un hilo exteino (poi ejemplo, el
piincipal), lo hace usanuo wakeAll() paia uespeitailos a touos o wake0ne() paia uespeitai solo a
uno ue ellos, el oiuen en que esto ocuiie es aleatoiio y no se pueue contiolai.
)*!


vamos entonces ahoia a iesolvei el pioblema uel piouuctoi y consumiuoi, paia ello
vamos a uefinii las siguientes vaiiables globales que van a compaitii touos los hilos, incluiuo el
piincipal:
const int DataSize = 100000;
const int BufferSize = 8192;
char buffer[BufferSize];

QWaitCondition bufferNotEmpty;
QWaitCondition bufferNotFull;
QMutex mutex;
int numUsedBytes = 0;

Batasize en la cantiuau ue bytes que va a esciibii el consumiuoi en buffei. El tamao uel
buffei es infeiioi a esa cantiuau, poi lo que el consumiuoi tenui que uai vaiias vueltas, lo que
hace con un couigo como ste:
buffer[i % BufferSize] = "ACGT"[(int)qrand() % 4];
Lo que esciibe son aleatoiiamente las letias ACuT (bases uel couigo gentico). Be esta maneia no
se sale uel buffei y lo esciibe ciclicamente.
La conuicion ue espeia buffeiNotEmpty, sei sealaua poi el piouuctoi cuanuo haya
esciito algn uato, uespeitanuo al consumiuoi paia que lo lea. La conuicion ue espeia
buffeiNotFull, la sealai el consumiuoi cuanuo haya leiuo algn uato, uespeitanuo al
consumiuoi paia que siga esciibienuo. num0seuBytes, va a sei el nmeio ue bytes en el buffei
que contiene uatos esciitos poi el piouuctoi, y que no han siuo leiuos poi el consumiuoi. El
mutex, se encaigai ue bloqueai el acceso a la vaiiable comn num0seuBytes, paia que sea leiua
y cambiaua poi un solo hilo en caua momento. num0seuBytes no poui exceuei el tamao uel
buffei nunca, o el consumiuoi estai sobiesciibienuo uatos an no leiuos poi el consumiuoi.
Poi lo tanto el couigo que gobieina el hilo piouuctoi es:
class Producer : public QThread
{
public:
void run();
};
void Producer::run()
{
qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));

for (int i = 0; i < DataSize; ++i) {
mutex.lock();
if (numUsedBytes == BufferSize)
bufferNotFull.wait(&mutex);
mutex.unlock();

buffer[i % BufferSize] = "ACGT"[(int)qrand() % 4];

mutex.lock();
++numUsedBytes;
bufferNotEmpty.wakeAll();
mutex.unlock();
}
}
Inicializa la semilla ianuom con el timei. Antes ue acceuei a num0seuBytes bloquea con el mutex
su acceso, si se ha llenauo el buffei completo ue uatos, entonces se queua en espeia ue la
conuicion buffeiNotFull y libeia el mutex. Si no ha llenauo el buffei, libeia el mutex, esciibe en la
posicion siguiente y ue nuevo antes ue inciementai num0seuBytes (el contauoi comn uel
buffei), bloque esta seccion, inciementa su valoi, y uespieita al hilo consumiuoi, luego libeia el
mutex, y sigue el bucle a su iitmo.



)*"


El couigo uel hilo consumiuoi seiia complementaiio a ste:
class Consumer : public QThread
{
public:
void run();
};

void Consumer::run()
{
for (int i = 0; i < DataSize; ++i) {
mutex.lock();
if (numUsedBytes == 0) bufferNotEmpty.wait(&mutex);
mutex.unlock();

fprintf(stderr, "%c", buffer[i % BufferSize]);

mutex.lock();
--numUsedBytes;
bufferNotFull.wakeAll();
mutex.unlock();
}
fprintf(stderr, "\n");
}

El hilo consumiuoi tambin tiene su bucle paia leei touos los uatos que el consumiuoi va
uejanuo en el buffei, y sacnuolos poi la saliua estnuai ue eiioi. Antes ue ievisai el valoi ue
num0seuBytes, bloquea la seccion con un mutex, si no hay uatos que leei nuevos, entonces se
queua espeianuo que se cumpla la conuicion ue espeia buffeiNotEmpty y libeia el mutex. Si no
es asi, tambin libeia el mutex, lee el siguiente uato uel buffei, y luego bloquea ue nuevo con el
mutex el cambio ue num0seuBytes, que es ueciementauo, inuicanuo que hay un uato menos poi
leei, luego uespieita al hilo piouuctoi con su seal buffeiNotFull, y libeia el mutex. Y sigue en su
bucle tambin a su iitmo.
Be esta maneia, ambos hilos se autosincionizan, sin pisaise el uno al otio. Sin embaigo,
existe una segunua foima ue hacei esto ue maneia tambin optima, usanuo semfoios. En Qt esto
se hace con la clase QSemaphoie. Poi tanto veamos antes como funciona esta clase.
QSemaphoie, piovee ue un contauoi geneial con semfoio. Nientias un mutex, solo
pueue sei bloqueauo una vez, hasta que es uesbloqueauo, un semfoio pueue sei bloqueauo
mltiples veces. Paia ello el semfoio inicia el contauoi con un nmeio que uefine los iecuisos
uisponibles, y caua vez que se llama al semfoio con la funcion acquiie() se piuen iecuisos, si lo
hay, el hilo sigue la ejecucion, peio si no los hay paia auquiiiilos, entonces se bloquea la
ejecucion uel hilo en ese punto hasta que hayan iecuisos suficientes paia sei auquiiiuos, poi lo
que iealmente funciona como un mutex especial. veamos un ejemplo sencillo:
QSemaphore bytes(6);
bytes.acquire(4);
bytes.acquire(3);

Aqui, se ciea un semfoio bytes con el contauoi a 6, cuanuo el hilo llega a la piimeia auquisicion
ue 4 bytes, no hay pioblema ya que an queuan 2, poi lo que la ejecucion sigue, peio en la
siguiente al intentai auquiiii S, ya no pueue, asi que el hilo se queuaiia ahi, hasta que haya bytes
uisponibles paia seguii. Paia uevolvei los bytes habiia que llamai a la funcion ielease(int n). Poi
uefecto si no se pone un nmeio en acquiie o en ielease, se piesupone que es 1.
Be esta maneia pouemos cieai 2 semfoios en nuestio caso, con los 2 casos extiemos
que paiaiian la ejecucion ue alguno ue los hilos. El semfoio fieeBytes poi ejemplo pouiia
inuicai el nmeio ue bytes libies paia sei esciitos, y que el piouuctoi pouiia auquiiii antes ue
vei si pueue seguii esciibienuo, y el consumiuoi pouiia libeiai con ielease(), una vez lo haya
leiuo. Lo inicializaiiamos con un valoi igual al nmeio total ue bytes uel buffei. Poi otio lauo otio
semfoio llamauo useuBytes pouiia inuicai el nmeio ue bytes uisponibles paia lectuia, el hilo
consumiuoi auquiiiiia antes uno, paia pouei leei, y si no lo hay, entonces queuaiia bloqueauo,
hasta que lo hubieia, y el piouuctoi, libeiaiia bytes en este semfoio una vez haya esciito en el
buffei. Bicho semfoio se inicializaiia con el valoi a u, o lo que es lo mismo instanciauo poi
)*#


uefecto. Be esta maneia, caua hilo tiene su piopio semfoio, y ambos hilos inuican al otio las
nuevas situaciones, libeianuo uel semfoio contiaiio, y auquiiienuo uel suyo piopio. Asi veis
que el couigo queua mucho ms sencillo que usanuo el mutex y las 2 conuiciones ue espeia.
const int DataSize = 100000;
const int BufferSize = 8192;
char buffer[BufferSize];

QSemaphore freeBytes(BufferSize);
QSemaphore usedBytes;

class Producer : public QThread
{
public:
void run();
};

void Producer::run()
{
qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
for (int i = 0; i < DataSize; ++i) {
freeBytes.acquire();
buffer[i % BufferSize] = "ACGT"[(int)qrand() % 4];
usedBytes.release();
}
}

class Consumer : public QThread
{
public:
void run();
};

void Consumer::run()
{
for (int i = 0; i < DataSize; ++i) {
usedBytes.acquire();
fprintf(stderr, "%c", buffer[i % BufferSize]);
freeBytes.release();
}
fprintf(stderr, "\n");
}

Compienuiuo el mecanismo que hemos explicauo ue los semfoios, su iniciacion, auquisicion y
libeiacion, no hay mucho que comentai ue este couigo.
Bueno y hemos uejauo paia el final, el hilo piincipal, que en ambos casos seiia el mismo.
Besue main(), se iniciaiian ambos hilos con stait(), y luego se llamaiia en ambos a wait(), paia
que no acabe la funcion main() y mueian los hilos antes ue que teiminen su tiabajo. Lo que hace
esa funcion (wait) es espeiai a que uicho hilo acabe, y una vez acaba, uevuelve #48".
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
Producer producer;
Consumer consumer;
producer.start();
consumer.start();
producer.wait();
consumer.wait();
return 0;
}

Ambos wait() se ejecutan uno uetis uel otio, ya que son hilos uifeientes, y se espeia a que estos
acaben, paia teiminai la ejecucion ue main().


)*$


)%/" G_
^$r]07-+ % 0/#$%+0Q&

Los gificos 2B en Qt estn basauos en QPaintei, que pueue uibujai uesue foimas
geomtiicas como, puntos, lineas, iectngulos, etc, hasta mapas ue bits, imgenes y textos. Pueue
aplicai efectos como antialiasing, alpha-blenuing, iellenauo con giauientes, etc. Pueue aplicai
tiansfoimaciones y ms cosas. Pueue hacei touo esto sobie un QWiuget, un QPixmap o un
QImage. Pueue sei usauo en conjuncion con QPiintei paia impiimii o paia geneiai PBFs, asi que
el mismo couigo que usamos paia uibujai nos pueue peimitii impiimii. 0na alteinativa a
QPaintei es el mouulo Qt0penuL, que acceue a la libieiia 2B y SB 0penuL.
La foima ms tipica ue usai QPaintei en un Wiuget es poi ejemplo ieuefinienuole la
funcion paintEvent() que se encaiga ue uibujailo. Esto es un ejemplo sencillo:
void SimpleExampleWidget::paintEvent(QPaintEvent *)
{
QPainter painter(this);
painter.setPen(Qt::blue);
painter.setFont(QFont("Arial", 30));
painter.drawText(rect(), Qt::AlignCenter, "Qt");
}

Touas las funciones uiaw.(), son las encaigauas ue uibujai con QPaintei. Pieviamente a
uibujai hay que uefinii las caiacteiisticas uel pintauo con las funciones settei setPen(),
setBiush() y setFont(), que uefinen el lpiz ue tiazauo ue uibujo, el iouillo ue iellenauo ue
foimas, y la fuente paia el texto, iespectivamente. Esas heiiamientas pueuen sei cambiauas en
cualquiei momento.
Las funciones ue uibujauo ue foimas ms impoitantes son: uiawPoint(), uiawLine(),
uiawPolyline(), uiawPoints(), uiawLines(), uiawPolygon, uiawRect(), uiawRounuRect(),
uiawEllipse(), uiawAic(), uiawChoiu(), uiawPie(), uiawText(), uiawPixmap() y uiawPath().
QPaintei sita el oiigen ue cooiuenauas poi uefecto en la esquina supeiioi izquieiua
(u,u). Sin embaigo seiia ms comouo tenei una ventana con cooiuenauas logicas y que el sistema
las pasaia a fisicas sin que el piogiamauoi tenga que hacei las conveision. Pues bin, llamamos
viewpoit al iectngulo con cooiuenauas fisicas, y Winuows al iectngulo con cooiuenauas
logicas. Esto se hace con QPaintei::setWinuow().
Luego esta la matiiz munuo, que es una matiiz paia aplicai tiansfoimaciones afines
como iotaciones y tianslaciones. QNatiix es quien implementa uicha matiiz, y usanuo sus
funciones iotate() y tianslate() se llevan a cabo las tiansfoimaciones, y finalmente se aplican al
QPaintei meuiante su funcion setNatiix(QNatiix).
Si iequeiimos ue ms caliuau, aunque esto ieuunua en menos velociuau, pouemos usai
QImage paia uibujai. Paia ello cieamos un objeto QImage() con un tamao y foimato ue coloi, y
luego instanciamos con QPaintei(QImage *), paia ii uibujanuo con l, seiia su uispositivo ue
pintauo.
(#A4296A
Impiimii en Qt es similai a uibujai con QPaintei y se tiata ue seguii los siguientes pasos:
1.- Cieai QPiintei paia que siiva como el uispositivo ue pintauo (painting uevice).
2.- Abiii una ventana QPiintBialog, que peimita al usuaiio ajustai la impiesoia y uems ajustes.
S.- Cieai un QPaintei que opeie con QPiintei.
4.- Pintai una pgina usanuo QPaintei.
)*%


S.- Llamai a QPiintei::newPage() paia avanzai a la pgina siguiente.
6.- Repetii los pasos 4 y S hasta que se impiima touo.
Se pueue tambin impiimii a un PBF llamanuo a set0utputFoimat(QPiintei::PufFoimat).
QPrinter printer(QPrinter::HighResolution);
QPrintDialog *dialog = new QPrintDialog(&printer, this);
dialog->setWindowTitle("Imprimir Documento");
if (dialog->exec() != QDialog::Accepted)
return;

QPainter painter;
painter.begin(&printer);

for (int page = 0; page < numberOfPages; ++page) {
// Usar painter para imprimir la pagina.

if (page != lastPage)
printer.newPage();
}

painter.end();

El tamao ue la zona impiimible uel papel viene ueteiminauo poi QPiintei:pageRect(), que
uevuelve el QRect ue la zona impiimible, con ello se pueuen hacei los clculos paia ueteiminai la
vaiiable numbei0fPages y lastPage.


















)*&


)%/" GL
$%7\$+-+ %M)%$&-+

Acabanuo ya los temas que iesumen touo lo que es necesaiio sabei paia uesaiiollai una
aplicacion ue pioposito geneial, hemos queiiuo metei en un mismo tema con el nombie ue
iecuisos exteinos, una seiie ue picticas que nos peimiten hacei colaboiai a Qt con su exteiioi.
Comenzanuo poi la posibiliuau ue caigai en tiempo ue ejecucion un uiseo ue ventana ue uilogo
en foimato *.ui con las uitools, pasanuo poi la posibiliuau ue ejecutai piocesos o aplicaciones
exteinas meuiante la clase QPiocess, y acabanuo poi la posibiliuau ue aauii la capaciuau ue uso
ue libieiias exteinas a Qt.

'4YB8R8: 342YP458: W(\4<8?36AX
Llamamos uilogos uinmicos a aquellos que han siuo cieauos en el Qt Besignei como
ficheios *.ui, peio que no han siuo compilauos junto con la aplicacion, poi lo que el uic (ui
compilei), no ha pouiuo pasailos a C++, y luego sei compilauos, si no que van a sei caigauos en
tiempo ue ejecucion poi la aplicacion piincipal como .ui tal cual. Paia ello existe una clase capaz
ue tal manejo, que es Q0ILoauei, que meuiante su funcion loau(QFile), pueue caigai uicho
ficheio con toua su inteifaz.
QUiLoader uiLoader;
QFile file("dialog.ui");

QWidget *dialog = uiLoader.load(&file);

if(dialog){
// cdigo para recoger los widgets
QComboBox *combo1 = dialog->findChild<QComboBox *>("combo1");
// si combo1 no existe devuelve un puntero nulo
if (combo1).........

}

Bate cuenta que aqui caigamos el ficheio .ui con el 0iLoauei, y iecupeiamos su
estiuctuia en un punteio QWiuget (uialog). 0sanuo ue la intiospeccion ue Qt, pouemos meuiante
finuChilu, ii iecupeianuo punteios a sus componentes, conociuos sus nombies (objectName).
Pouemos ue esta maneia ya usai uialog->show() paia mostiailo ue maneia no-moual o uialog-
>exec() paia haceilo ue maneia moual.
Paia usai Q0iLoauei tenemos que aauii a *.pio el mouulo uitools ue la siguiente
maneia:
C0NFIu += uitools
Si vas a usai el compilai NSvC 6, es necesaiio que en vez ue usai finuChilu<T>() ue
QWiuget, uses qFinuChilu<T> ue Qtulobal, ya que el piimeio no es sopoitauo poi uicho
compilauoi.

#A8RA?P?: 6J96A28: W(#A856::X
0na ue las utiliuaues ue uesaiiollai una u0I, es facilitai el manejo ue una aplicacion ue
consola que pieviamente existia, y cuya linea ue comanuos eia muy laiga e incomoua ue usai.
Nos pouemos planteai el constiuiile una u0I paia pouei usaila ue una maneia ms gifica y
comoua poi lo tanto. Qt, nos peimite eso meuiante la clase QPiocess.

)*'


Paia simplemente ejecutai una aplicacion exteina, usaiemos la funcion execute() ue
maneia similai a sta:
QString cmd = "cp a.txt b.txt";
QProcess::execute(cmd);

Si lo que queiemos es establecei una comunicacion entie el piogiama exteino y la
aplicacion, si aqul lo peimite, en ese caso usaiemos la funcion stait(), y usaiemos wiite() paia
enviaile uatos, y ieauAll() paia leei uel mismo. 0saiemos close() paia ceiiai el canal ue
comunicacion. 0n ejemplo ue este tipo ue comunicacion es posible con piogiamas como el bash
ue Linux, o Telnet, o cmu.exe ue Winuows. veamos un ejemplo:
QProcess bash;
bash.start("bash");
if(!bash.waitForStarted()){
qDebug() << "NO RULA";
return -1;
}
bash.write("ls");
bash.closeWriteChannel();
if(!bash.waitForFinished()){
qDebug() << "NO RULA";
return -1;
}
QByteArray response = bash.readAll();
qDebug() << response.data();
bash.close();


\:8 36 B4HA6Ak?: 6J96A2?:
Cuanuo queiemos usai libieiias paia linkailas nuestio piogiama, simplemente hay que
aauii a nuestio ficheio *.pio una linea como esta:
LIBS += -lnombie_libieiia
Siembie que compilemos con el uN0 Compilei. Asi la libieiia matemtica seiia -lm, la libieiia
cuil seiia -lcuil, y asi sucesivamente.
Peio hay veces que queiiemos llamai en tiempo ue ejecucion a funciones ue una libieiia
uinmica, que en Winuows tiene extension .ull, en Nac0SX suele sei .uylib, y en Linux es .so . Paia
tal caso, Qt piovee ue un sistema multiplatafoima a tiavs ue la clase QLibiaiy.
Toua libieiia tiene sus funciones expoitauas como simbolos. Supongamos que una
libieiia llamaua "mylib" con la extension coiiesponuiente uel opeiativo uonue est instalaua,
tiene una funcion que en C tiene como piototipo "int avg(int, int)" que lo que hace es iealizai la
meuia aiitmtica ue los 2 paimetios que se le pasan, y uevuelve esa meuia en foimato enteio. Si
queiemos llamai a uicha funcion uesue Qt, habiia que usai el siguiente couigo:
QLibrary library("mylib");
typedef int (*AvgFunction)(int, int);

AvgFunction avg = (AvgFunction) library->resolve("avg");
if (avg)
return avg(5, 8);
else
return -1;




)*(


)%/" Gg
>s+7")% <" n0'"

Si, has leiuo bien, este capitulo se llama "bscate la viua", esto no quieie uecii que ya me
haya cansauo ue esciibii este libio, ni ue explicai nuevas cosas. Qt es un Fiamewoik que ya tiene
casi la veintena ue aos, poi lo que a uia ue hoy ha cieciuo enoimemente, tanto que ningn libio
que lo tiate pueue aspiiai a tocai absolutamente touas sus clases. Tambin es cieito que hemos
tocauo las clases que ms vas a usai siempie que uesaiiolles aplicaciones ue pioposito geneial,
peio es posible que alguna vez te plantees hacei otia cosa, y esto no est cubieito en ningn
libio. Bay que pensai que Qt, seguii ciecienuo en el futuio, poi lo que la nica foima ue
manteneise al uia, es usanuo el Qt Assistant, es uecii, buscnuose uno mismo la viua.
Poi tanto, lo que pietenuemos con este capitulo es cubiii esa paite que viene uespus ue
cuanuo acabes este libio, y tengas que empezai a esciibii couigo, y en algunas ocasiones te
tiopieces con que tienes que usai cosas, que no has estuuiauo antes, y nunca las has usauo, e
incluso que no pueuas encontiai en los foios a nauie que lo haya usauo antes. Qt est muy bien
uocumentauo, peio en ingls, poi lo que es funuamental entenuei al menos el iuioma ue
Shakespeaie a nivel ue lectuia tcnica.
Pues bien, paia piacticai, se me ha ocuiiiuo planteai unas clases que no hemos visto, y
que cuiiosamente eches ue menos, si has piogiamauo en otios entoinos. Se tiata ue la hoia, la
fecha e incluso uel uso ue timeis, aunque en el tema 2S hemos visto un ejemplo ue ste ltimo.
Poi ello vamos a piacticai en este tema a buscainos la viua en el asistente. Realmente pouiia
habei centiauo la bsqueua en cualquiei otio tema ms complejo, peio simplemente lo seiia poi
tenei ms funciones, piopieuaues, seales y slots, o poi que el texto ue la uesciipcion es mucho
ms extensa. Asi que si seguimos bien estas S clases, no habiia poi qu habei ningn pioblema
en cualquiei otia.
Lo piimeio seiia sabei qu clases pouiian encaigaise ue la hoia, ue la fecha, o ue un
piopoicionai un timei. Bebiuo a que un poco ue ingls si que sabemos, y ms si hemos tiabajauo
con libieiias similaies en C, C++ u otio lenguaje, sabemos que la hoia es Time, que la fecha es
Bate y Timei est claio lo que es, asi que no seiia muy uescabellauo pensai que uichas clases se
llamen QTime, QBate y QTimei. Asi que nos vamos al asistente, y buscamos las S clases, veiemos
que hemos aceitauo en touo. Caiamba, que sueite tenemos . Be touas foimas si no tuviiamos
claio el concepto ue nuestia clase, siempie pueue uno uaise una paseo poi touas, paia uetectai
uentio ue su nombie un atisbo ue luz. Poi ejemplo, ue qu ciee que tiatai la clase QNimeBata
o QFtp ..

()4P6
Es eviuente que el constiuctoi ue esta clase, uebe ue peimitii iniciai una instancia con
una hoia ueteiminaua. vemos entie las public functions, siempie en piimei lugai los uistintos
constiuctoies, uno sin paimetios, poi lo que es una meia instanciacion, y uebe ue existii poi
tanto una funcion que ms taiue pueua ponei la hoia, que poi su piototipauo, uebe ue sei
setBNS().
0tia ue las cosas impoitantes que hay que miiai en una clase, es queuaise con las
piopieuaues o vaiiables piivauas, ya que asociauas a ellas vamos a encontiai una seiie ue
funciones settei y gettei impoitantes paia su manejo. Asi nos encontiamos con houi(), minute()
y seconu() en los gettei, y el ya mencionauo setBNS() como el nico settei.
Luego nos encontiaiemos con una seiie ue funciones que llevan a cabo una laboi
especial, que pouemos leei en su uesciipcion ue qu se tiata. Busca poi tanto, la laboi ue stait(),
iestait() y ellapseu(). Estn muy ielacionauas entie si, y asi apaiece en sus uesciipciones.
Tambin es muy impoitante aquella que iecoge la hoia exacta actual, que ue seguio es
))*


cuiientTime(), entie los static public. Bentio ue los opeiauoies, vemos que se pueuen compaiai
2 objetos QTime entie si, lo cual pueue sei muy til. Y an ms til una seiie ue funciones que
peimiten aauii a la hoia, inteivalos ue tiempo vaiiables, en segunuos (auuSecs).
Te animo a que hagas piuebas con ellas en un couigo sencillo ue consola.

('?96
Se tiata ue una clase ue similai uisposicion a la anteiioi. Poi ello te animamos a que la
uesciibas t mismo, y luego compiuebes su funcionaliuau en un couigo tambin sencillo.

()4P6A
Esta clase, eia funuamental explicaila, ya que es muy til siempie el uso ue timeis. El
uejaila paia un tema autosuficiente como ste, nos va a peimitii sei ms autonomos ue aqui en
auelante a la hoia ue manejai el Fiamewoik ue Qt, poique otia posibiliuau que nos pueue
ocuiiii, es que se nos olviue la funcionaliuau ue algunas ue las clases que ya hemos explicauo, y
no tengas ceica este libio paia iepasailas, mientias que tenienuo el asistente, siempie pouis
sacai el tiabajo auelante.
Lo piimeio que nos uice el asistente es que QTimei piovee ue timeis iepetitivos y ue un
solo uispaio. Los timeis iepetitivos son aquellos que caua inteivalo, se uispaia el evento uel
timei, y los ue un solo uispaio, solo se piogiamai y se uispaian una sola vez. Es ue suponei que
paia inuicai que ha llegauo al final ue su contauoi, uispaie una seal. Y asi es, ue hecho solo
pouemos vei la seal timeout().
veamos sus piopieuaues, que son: active, que es un bool que estai a tiue cuanuo est
activo, y false cuanuo no lo est; inteival, que es un enteio, que ue seguio contiene el inteivalo
piogiamauo; y singleShot que es un bool que estai tiue si es ue nico uispaio, o a false, si es
iepetitivo. En toino a estas piopieuaues, ueben hacei getteis y setteis. Como setteis tenemos
setInteival() y setSingleShot(), y como getteis tenemos, isActive() e isSingleShot().
Como public functions, tenemos las ms impoitantes, que son stait() paia ponei en
maicha el timei, y stop() paia paiailo en cualquiei momento. Bay otia funcion llamaua
singleShot() que nos peimite, piogiamai el inteivalo y el slot a ejecutai ue un ueteiminauo
objeto, cuanuo uicho inteivalo haya pasauo.
Puesto que QTimei piovee ue una seal, timeout() es tambin muy logico el usaila paia
conectaila a slots ue otios objetos que hagan algo una vez pasauo el tiempo.
Te animamos a que esciibas un piogiama sencillo, que caua segunuo, aumente el valoi
ue un contauoi en un QLCBNumbei.

Quizs este tema te haya paieciuo muy tiivial, si es asi, es que ya estas piepaiauo paia
nauai t solo en el univeiso Qt. Peio an no te vayas, poique el ltimo tema es el siguiente, y
tiata ue algo que muy pocos suelen tiatai, esto es, ue como piepaiai un instalauoi paia nuestia
aplicacion paia los S opeiativos ms impoitantes: Linux, Nac0SX y Winuows.




)))


)%/" G[
0&+)"<"'-$%+

Al final uel tema 2, cuanuo piepaiamos el entoino ue uesaiiollo, paia pouei uesaiiollai
touos los ejemplos uel libio sin pioblemas, avisbamos ue que las aplicaciones uesaiiollauas poi
uefecto con estas instalaciones poi uefecto uel SBK ue Qt, no pouian sei implementauas tal cual
en sistemas ue piouuccion uonue el SBK no va a estai instalauo.
Llego el momento ue tomai en consiueiacion qu aichivos uebemos ue llevainos con
nuestias aplicaciones fueia uel oiuenauoi uonue se efectuo uesaiiollo, paia que touo funcione
coiiectamente.
El entoino ue uesaiiollo instalauo poi uefecto, funciona con libieiias ue enlace
uinmico, poi lo que vamos a compilai ejecutables que son poco pesauos, peio que enlazan en
tiempo ue ejecucion con una seiie ue libieiias uinmicas, poi lo que nos tenuiemos que llevai
junto con el ejecutable, toua una seiie ue libieiias y plugins, sobie la que el mismo se va a apoyai
paia pouei funcionai. Poi ello es muy inteiesante uisponei, no solo ue un oiuenauoi opeiativo
paia el uesaiiollo, si no tambin, uisponei ue otio (mquina ieal o viitual) uonue est instalauo
el opeiativo poi uefecto sin ms, uonue vamos a piobai que entiegamos touo lo necesaiio paia
que nuestia aplicacion funcione. 0na vez tengamos en una caipeta a paite, touos los elementos
necesaiios paia que la aplicacion funcione autonomamente, pouiemos iecuiiii a cieai un
sistema ue instalacion que se encaigue ue copiai uichos elementos en la maneia uebiua al
sistema en piouuccion.
vamos poi tanto a seguii un ejemplo, en los S sistemas opeiativos ue siempie (Winuows,
Linux y Nac 0SX), y lo vamos a hacei con la aplicacion que uesaiiollamos en el tema 2u que es un
euitoi ue textos uonue estn piesentes los elementos tipicos ue una aplicacion ue pioposito
geneial. vamos pues a usaila paia cieai el paquete ue instalacion coiiesponuiente a caua uno ue
los sistemas opeiativos objetivo.

D4238E:
Si no lo has hecho anteiioimente, abie el aichivo ue pioyecto (.pio) en tu entoino ue
uesaiiollo (Qt Cieatoi), y pulsanuo en el mouo Piojects (iconos ue la izquieiua), selecciona en
"Euit Builu configuiation" la opcion Release. Luego, vamos a ieconstiuii la aplicacion con Rebuilu
Pioject. Pouemos incluso ejecutaila. No uebe ue habei ningn pioblema, ya que queuo
completamente cieaua y piobaua en el tema 2u. Ya tenemos en el uiiectoiio uonue guaiuemos
nuestios fuentes, una caipeta que se llamai application-builu-uesktop, en cuyo inteiioi
encontiaiemos en la caipeta Release, el ejecutable final (application.exe). Si usas visual Stuuio
2uu8 como compilauoi, y en el sistema est iegistiaua la iun-time ue visual C++ 9.u
"msvcp9u.ull", pouis ejecutai sin pioblemas la aplicacion. Si usas el compilauoi NinuW que va
en el paquete ue Qt4, las libeiias uinmicas coiiesponuientes no estain iegistiauas en el
sistema, y la ejecucion ue la aplicacion uesue su caipeta, te uai eiioi inuicnuote la piimeia
libieiia uinmica que intenta enlazai peio que no encuentia.
Sea como fueie, uebemos piepaiaile al ejecutable, touo lo que iequieie en su piopia
caipeta, asi que vamos a ello.
Paia sabei ue qu uepenue nuestia aplicacion, en Winuows vamos a tenei que usai una
heiiamienta que no viene incluiua en el SBK ue Qt, llamaua Bepenuency Walkei. Pueues bajaila
ue http:www.uepenuencywalkei.com. En nuestio caso hemos bajauo la veision ue S2 bits (foi
x86). Al ejecutaila, vamos a File -> 0pen, y abiimos nuestio ejecutable (application.exe). Se nos
uespliega en la ventana supeiioi izquieiua touo un ibol ue uepenuencias, peio lo que nos
inteiesa, est en las iamas piincipales ue uichos iboles. Si colapsamos uichas iamas, en un
sistema con vS2uu8 tenuiiamos algo asi:
))!



Como pouemos obseivai, nuestia aplicacion compilaua con visualC++ 2uu8 (9.u) uepenue ue 4
ulls, peio una ue ellas, ya viene piovista poi el sistema opeiativo Winuows (keinelS2.ull), poi lo
que iealmente vamos a iequeiii ue las Blls Qtuui4.ull, QtCoie4.ull y NSvCR9u.ull .
Be hecho estas S uepenuencias, las pouiamos pieveei, ya que si miiamos el conteniuo
uel ficheio ue pioyecto (application.pio) veiemos que piue aauii los mouulos "coie" y "gui":
QT += coie gui
Poi lo que, es ue suponei que iequeiii ambas libieiias uinmicas. La teiceia uepenuencia es
tipica ue quien usa el compilauoi vS2uu8. Quien use NinuW se encontiai con 2 uepenuencias,
las ue los ficheios mingwm1u.ull y libgcc_s_uw2-1.ull .
Bonue pouemos encontiai esas libieiias.. Pues las libieiias ue Qt se encuentian en el
uiiectoiio bin ue la instalacion uel Qt SBK. La libieiia ue visual C++ est en el uiiectoiio ue
instalacion ue vS2uu8 (Aichivos ue PiogiamasNiciosoft visual Stuuio 9.uvCceull), uonue
pouis elegii la aiquitectuia ue CP0, en nuestio caso en la caipeta x86 (paia PC).
Asi que tiaslauamos esas S uepenuencias al mismo sitio uonue esta nuestio ejecutable.
Si llevamos esos 4 ficheios en una caipeta a cualquiei PC con Winuows XP, vista o 7, veis que se
pueue ejecutai sin pioblema alguno.
Babin aplicaciones que hacen uso ue plugins, como pueuan sei uiiveis ue bases ue
uatos, uiiveis ue foimatos gificos, etc. veiemos luego en un apaitauo qu hacei en ese caso.

<42IJ
Si no lo has hecho anteiioimente, abie el aichivo ue pioyecto (.pio) en tu entoino ue
uesaiiollo (Qt Cieatoi), y pulsanuo en el mouo Piojects (iconos ue la izquieiua), selecciona en
"Euit Builu configuiation" la opcion Release. Luego, vamos a ieconstiuii la aplicacion con Rebuilu
Pioject. Pouemos incluso ejecutaila. No uebe ue habei ningn pioblema, ya que queuo
completamente cieaua y piobaua en el tema 2u. La aplicacion queuai en su uiiectoiio ue
maneia que pueue ejecutaise uiiectamente uesue l (.application). Paia compiobai sus
uepenuencias, hay una heiiamienta que ya viene con las heiiamientas uN0, que es 3%%.
luu .application
Nos iesponuei con una seiie ue libieiias uinmicas uel tipo .so . La gian mayoiia ue esas
libieiias suelen estai instalauas en un sistema limpio con gestoi ue ventanas unome o KBE. Peio
es conveniente que antes te ceicioies ue ello. Y si es asi, es posible que uicha libieiia se instale
meuiante algn paquete que se pueua bajai ue los iepositoiios oficiales ue la uistiibucion ue
Linux en cuestion. Finalmente uichas libieiias siempie acabain en lib, usilib o
usilocallib. Be esta maneia son siempie accesibles a la aplicacion. Peio a paite ue estas
libieiias veiemos otias que no estn en esos uiiectoiios que ue seguio son:
))"


libQtuui.so.4 y libQtCoie.so.4 . Estas las vamos a tenei que ponei al alcance ue nuestia aplicacion
en su piopio uiiectoiio. Puesto que se tiatan ue links a ficheios ue otio nombie lo hacemos ue la
maneia:
cp -R qtsukqtliblibQtuui.so.4* application_foluei
cp -R qtsukqtliblibQtCoie.so.4* application_foluei
Babin aplicaciones que hacen uso ue plugins, como pueuan sei uiiveis ue bases ue
uatos, uiiveis ue foimatos gificos, etc. veiemos luego en un apaitauo qu hacei en ese caso.

/?5 -+M
0na aplicacion paia Nac, lleva la extension .app, y en si mismo es una caipeta en cuyo
inteiioi lleva el veiuaueio ejecutable y touos los iecuisos, plugins, fiamewoiks, etc, que necesita
paia funcionai. En iealiuau un .app es un bunule y tiene la foima que uefinimos en el gifico
siguiente:

Si no lo has hecho anteiioimente, abie el aichivo ue pioyecto (.pio) en tu entoino ue
uesaiiollo (Qt Cieatoi), y pulsanuo en el mouo Piojects (iconos ue la izquieiua), selecciona en
"Euit Builu configuiation" la opcion Release. Luego, vamos a ieconstiuii la aplicacion con Rebuilu
Pioject. Pouemos incluso ejecutaila. No uebe ue habei ningn pioblema, ya que queuo
completamente cieaua y piobaua en el tema 2u. Inicialmente application.app contiene:
Info.plist Nac0S PkgInfo Resouices
Paia vei las uepenuencias uel ejecutable en si (no uel bunule), usamos una heiiamienta que lleva
el XCoue, que se llama &#&&3:
otool -L application.appContentsNac0sapplication
En nuestio caso iesponue asi en Nac 0SX 1u.6.4:
application.appContentsNac0sapplication:
Qtuui.fiamewoikveisions4Qtuui (compatibility veision 4.7.u, cuiient veision 4.7.u)
QtCoie.fiamewoikveisions4QtCoie (compatibility veision 4.7.u, cuiient veision 4.7.u)
usiliblibstuc++.6.uylib (compatibility veision 7.u.u, cuiient veision 7.9.u)
usiliblibgcc_s.1.uylib (compatibility veision 1.u.u, cuiient veision 62S.u.u)
usiliblibSystem.B.uylib (compatibility veision 1.u.u, cuiient veision 12S.2.u)

))#


Las S libieiias infeiioies (.uylib) son piopias ue touo sistema poi uefecto. Las 2 supeiioies, son
libieiias que se han instalauo en foima ue Fiamewoik, que es como se instalan poi uefecto las
libieiias uel Qt4 SBK en Nac. Be hecho pueues veilas a touas en LibiaiyFiamewoiks.
Como cieai a mano el bunule con touo lo que necesita, seiia laigo y teuioso, Nokia nos
ofiece una heiiamienta con el SBK que lo hace poi nosotios ue maneia sencilla y comoua. Se
llama "macueployqt", que piue los siguientes iequisitos paia la constiuccion uel bunule final:
1.- Las veisiones uebug ue los plugins no son aauiuas al bunule.
2.- Los plugins uesignei no son aauiuos al bunule.
S.- Los plugins paia foimato ue imgenes si que son aauiuos al bunule.
4.- SQL uiiveis, Sciipts plugins, Phonon back-enu plugins, Svu Icon plugins, siempie son
aauiuos al bunule si la aplicacion usa los mouulos coiiesponuientes QtSql, QtSciipt, Phonon y
QtSvg.
S.- Si quieies aauii una libieiia no-Qt al bunule, tenuis que antes aauiila al pioyecto .pio
como una libieiia explicita. En tal caso, se aauiiia sin pioblemas a bunule.
Bien, como en nuestio caso cumplimos sin pioblemas touas estas piemisas, vamos a
cieai el bunule ue una vez y poi touas hacienuo:
macueployqt application.app
Tias lo cual, el conteniuo uel bunule habi cambiauo a:
Fiamewoiks Info.plist Nac0S PkgInfo PlugIns Resouices
Pouemos vei que en Fiamewoiks se han aauiuo los que hacian falta, y alguno ms. Pouemos
boiiai a mano los que sobian si queiemos ahoiiai espacio.
Ya pouemos uistiibuii la aplicacion sin pioblemas, y paia instalaila en otio equipo el
usuaiio solamente tenuiia que aiiastiai el icono coiiesponuiente al .app a la caipeta
Aplicaciones.
Babin aplicaciones que hagan uso ue plugins, como pueuan sei uiiveis ue bases ue
uatos, uiiveis ue foimatos gificos, etc. veiemos en el siguiente apaitauo como hacei esto,
aunque nuestia heiiamienta ya se haya encaigauo tambin ue colocai los plugins que consiueia
necesaiios en sus iespectivas caipetas uentio uel bunule.

#BIR42:
Los plugins en Qt, peimiten aauii nuevas funcionaliuaues a las aplicaciones. Asi hay
plugins que peimiten aauii nuevos foimatos ue imgenes legibles en Qt, o nuevos tipos ue bases
ue uatos, etc. Los plugins incluiuos en el SBK, estn en el uiiectoiio qtplugins en su caipeta ue
instalacion. Los nombies ue esas caipetas son fijos, y si se tiaslauan tal cual a la caipeta uel
ejecutable ue la aplicacion, la misma no tenui pioblemas en encontiai uicho plugin si lo
iequieie, ya que poi uefecto es ahi uonue los buscai. Si queiemos poneilos en otio sitio
uifeiente, entonces en la funcion main() ue la aplicacion tenuiemos que ueciile uonue
encontiaila usanuo QCoieApplication::auuLibiaiyPath() .
Los plugins paia bases ue uatos que el SBK piovee son muy limitauos (0BBC y SQLite).
Nosotios hemos aauiuo el ue Postuiesql y el ue NySQL en nuestios ejemplos, paia cualquieia
ue las S platafoimas que hemos explicauo. Pueues compilai t mismo cualquiei plugin bajanuo
los fuentes uel SBK (qt-eveiyone-sic), y compilanuo lo que necesites confoime a los REABNE que
le acompaan. El ltimo paigiafo ue este tema explica el piocesos ue compilacion uel uiivei
paia NySQL.
))$


02:9?B?38A6: 62 D4238E: K <42IJ
Sabienuo ya el paquete que uebemos copiai, pouiiamos nosotios mismos cieai un
instalauoi meuiante una aplicacion, sciipt o similai. vamos a pioponeite una opcion ms sencilla
paia que pueuas tenei en cuenta a la hoia ue entiegai tus aplicaciones. Y vamos a empezai poi
Winuows y Linux. Aunque hay muchas aplicaciones que estn especializauas en hacei
instalauoies ue un paquete, nosotios hemos escogiuo una en paiticulai uesaiiollaua en TkTcl
que peimite cieai instalauoies paia Winuows, Linux y otios 0NIX. Su nombie es Install}ammei,
que es giatuito, ue couigo abieito y multiplatafoima, como a nosotios nos gusta.
Cieai un instalauoi con esta heiiamienta es muy sencillo e intuitivo a pesai ue que est
en ingls. vamos a seguii con nuestia aplicacion paia hacei el ejemplo ue cieacion uel instalauoi.
Al aiiancai Install}ammei, pulsamos en New Pioject, y se nos abie un wizaiu paia cieai
el pioyecto uel instalauoi. Rellenamos los uatos que se nos van piuienuo. Contestauas touas las
pieguntas, pulsamos en Finish, y se nos abie el Install Besignei con una seiie ue items que
pouemos ii cambianuo a nuestio gusto, o uejanuo su valoi poi uefecto. Bejamos al usuaiio el
husmeai poi toua una ingente cantiuau ue paimetios. vamos a constiuii con los valoies poi
uefecto paia Winuows o paia Linux confoime necesitemos. Pulsamos sobie Builu Install, y vemos
en la ventana como se nos ciea Application-1.u-Setup.exe (poi ejemplo paia Winuows). Si
pulsamos sobie su link, se nos abie la caipeta uonue se ha cieauo el ejecutable instalauoi, listo
paia sei usauo.
Asi ue sencillo es cieai un instalauoi con este sencillo piogiama.

02:9?B?38A6: 62 /?5 -+M
Paia cieai instalauoies en Nac, no hay ninguna aplicacion simple y libie como la que
acabamos ue vei, peio si pouemos usai heiiamientas que vienen en nuestio sistema poi uefecto,
una vez hemos instalauo XCoue, y que nos peimitiin cieai un instalauoi con aspecto
piofesional. vamos a haceilo ue 2 maneias uifeientes: una meuiante una imagen .umg uonue se
aiiastia el .app sobie la caipeta Aplicacion, y otia cieanuo una paquete instalable meuiante la
heiiamienta PackageNakei ue XCoue.
Seguimos usanuo nuestio ejemplo ya empaquetauo en un bunule completo, tal como lo
uejamos, piepaiauo paia llevai a otio equipo (application.app).
vamos a cieai una imagen BNu con la utiliuau ue uiscos. Pulsaiemos sobie Nueva
Imagen, y vamos a ponei los ajustes ue la imagen ue a continuacion:

))%


La cieamos uel tamao suficiente paia que quepan .app y una fonuo en PNu que cieaiemos ue
7uux4uu, similai a ste:

Nontamos con un uoble clic la imagen BNu vacia iecin cieaua, y aiiastiamos a ella el bunule
.app. Luego nos vamos al uisco iaiz, y cieamos un alias ue la caipeta Aplicacion, la aiiastiamos al
BNu y le cambiamos el nombie a Aplicacion. Con el BNu montauo y abieito en el finuei,
pulsamos Cmu+}. Se abien las opciones ue caipeta, y hacemos algo como esto:

El fonuo lo elegimos hacienuo uoble click en el cuauio ue aiiastiai la
imagen, y seleccionamos el PNu. Ya se vei el BNu montauo con la imagen
ue fonuo, y pouiemos situai los iconos, y ieuimensionai la ventana paia
ajustaila al tamao uel fonuo. Expulsamos el BNu montauo, y nos vamos a
la utiliuau ue uiscos, y eligienuo la imagen BNu cieaua, pulsamos en
conveitii, y la guaiuamos esta vez compiimiua. Se ciea el BNu final
piepaiauo paia sei uistiibuiuo. Al montailo queuai algo como esto:


Bonue queua claia la intencion ue que se aiiastie el icono ue application.app sobie la caipeta
Applicaciones, paia que se piouuzca la instalacion.
Pasemos a la segunua opcion, que consiste en cieai un paquete ue instalacion uel tipo
*.pkg con el PackageNakei uel XCoue. Bicha aplicacion la pueues encontiai en
BevelopeiApplications0tilitiesPackageNakei. Al aiiancaila, lo piimeio que nos piue es la
oiganizacion (tipo com.nombie_oiganizacion), y el opeiativo objetivo minimo. Pulsanuo sobie el
))&


+ en la esquina infeiioi izquieiua pouemos aauii los componentes a instalai, que en nuestio
caso es solamente uno (application.app).
Si navegas poi esta
heiiamienta, veis que
tambin es muy intuitiva y
potente, y est en ingls. En
la zona ue conteniuos, se
pueuen ponei vaiios
elementos (aplicaciones,
libieiias, fiamewoiks,
ayuuas, etc). En
Configuiation, pouemos
elegii qu vamos a instalai
y uonue, si vamos a
peimitii que el usuaiio
ieubique la instalacion y si
se va a iequeiii
autentificacion poi paite
uel auministiauoi paia
instalaila, ue maneia que
pouiemos tambin copiai
ficheios en zonas uel
sistema. En Contents pouemos elegii el usuaiio y giupo al que peitenecei este conteniuo y sus
peimisos. Si seleccionamos el paquete ue uistiibucion (encima ue Contents), pouiemos euitai las
opciones uel paquete completo, poninuole un nombie, los tipos ue seleccion accesibles al
usuaiio, el uestino ue instalacion, pouiemos piogiamai iequisitos paia instalailo, como espacio
libie en uisco uuio, CP0, veision uel sistema opeiativo y muchos ms, tambin se pouin
piogiamai acciones a llevai a cabo antes ue pioceuei a la instalacion, y una vez sta ha
finalizauo. En la zona supeiioi ueiecha, tenemos el icono "Euit Inteiface", que nos peimite euitai
el inteifaz ue instalacion, cambianuo su fonuo, y el texto ue caua uno ue los pasos ue la
instalacion.
0na vez, ya tenemos touas las opciones iellenauas confoime a nuestia necesiuau,
pouemos pulsai en el icono ue la zona supeiioi izquieiua "Builu", que constiuii el paquete ue
instalacion. Bicho paquete pueue entiegaise como tal, o pueue meteise en una BNu tal como
apienuimos anteiioimente.

78PN4B?54C2 36 I2 3A4V6A +(<
El ltimo ue los escollos a soiteai paia uistiibuii nuestia aplicacion es que tengamos el
uiivei uel tipo ue base ue uatos que vamos a usai en nuestia aplicacion compilauo. La veision
0pen Souice ue Qt4, poi cuestiones ue licencias no lleva compilauos los uiiveis ms que ue 0BBC
y SQLite (que va integiauo en Qt4), y quizs con esto haya suficiente paia muchos, peio una gian
cantiuau ue gente usa otias bases ue uatos, y aunque pouiian usai el uiivei 0BBC paia ello,
siempie es iecomenuable usai el uiivei nativo sin ms aauiuos.
vamos poi tanto a explicai, como compilai el uiivei paia una ue las bases ue uatos ms
usauas, que es sin uuua NySQL. Paia pouei haceilo, auems ue tenei instalauo el sistema ue
uesaiiollo completo, como ya tenemos, paia pouei ejecutai qmake, g++ y make uesue la linea ue
comanuos, tenuiemos que bajainos los fuentes ue NySQL y ue Qt4.
Los fuentes ue NySQL, pouemos bajailos ue http:www.mysql.comuownloausmysql
en la veision essentials. A paite ue la instalacion completa, tenuiemos uos caipetas
funuamentales que son lib y incluue, uonue tenuiemos iespectivamente la libieiia necesaiia
paia nuestio cliente, y los fuentes ue NySQL.
))'


Los fuentes ue Qt4, estn en la web ue Nokia http:qt.nokia.com , y se llama qt-
eveiywheie-opensouice-sic-4.x.x . En este paquete encontiaiemos los fuentes que necesitamos
ue nuestio uiivei en la caipeta $QT_S00RCESsicpluginssqluiiveismysql. Ahi encontiaiemos
un ficheio main.cpp con el couigo uel uiivei y el ficheio ue pioyecto mysql.pio .
Situauos en el uiiectoiio ue los fuentes uel uiivei paia Qt4, ejecutaiemos los siguientes
comanuos en linea:
1.- Winuows (vS2uu8):
Piesuponemos PATB_NYSQL como el iaiz ue los fuentes ue NySQL.
qmake INCL0BEPATB+=PATB_NYSQLincluue LIBS+=PATB_NYSQL liboptlibmysql.lib mysql.pio
nmake uebug
nmake ielease

Tenuiemos al final las veisiones uebug y ielease ue los uiiveis, esttica y uinmica
(qsqlmysql4.ull qsql_mysql.lib).

2.- Linux:
Piesuponemos $PATB_NYSQL como la iaiz ue los fuentes ue NySQL
qmake INCL0BEPATB+=$PATB_NYSQLincluue LIBS+=-L$PATB_NYSQLlib -lmysqlclient_i mysql.pio
make

Se cieai la veision ielease uinmica libqsqlmysql.so .

S.- Nac 0SX:
Piesuponemos $PATB_NYSQL como la iaiz ue los fuentes ue NySQL
qmake -spec macx-g++ INCL0BEPATB+=PATB_NYSQLincluue LIBS+=-LPATB_NYSQLlib -lmysqlclient_i mysql.pio
make uebug
make ielease

Se cieain la veision ielease y uebug uinmicas libqsqlmysql.uylib y libqsqlmysql_uebug.uylib .

Con esto uamos poi finalizauo el conteniuo ue este libio, en el que hemos intentauo
uotailo ue touo el conteniuo pictico necesaiio paia el uesaiiollo eficaz ue aplicaciones ue
pioposito geneial en Qt4, peio an queua mucho camino poi anuai, peio sin uuua ya tenemos los
funuamentos paia que este viaje sea ms agiauable y sencillo.






))(


>0><0-^$"]0"

An lnLroducLlon Lo deslgn paLLerns ln C++ wlLh CL4 - renLlce Pall - Alan & aul LzusL

1he book of CL4. 1he arL of bulldlng CL appllcaLlons - no SLarch ress - uanlel MolkenLln

C++ Cul rogrammlng wlLh CL4 - renLlce Pall - !asmln 8lancheLLe & Mark Summerfeld

CL AsslsLanL - C1 nCklA Suk
1he C++ rogrammlng Language - Addlson Wesley - 8[arne SLrousLrup
























)!*
































!"#$%"&$'( *% +, '* -./012* '* +,3, 4 $#5#"6(

También podría gustarte