Muestra las diferencias entre dos versiones de la página.
| Ambos lados, revisión anterior Revisión previa Próxima revisión | Revisión previa | ||
|
fw:qt4 [2013/02/25 20:59] alfred [Componentes para tratar con OpenGL] |
fw:qt4 [2020/05/09 09:25] (actual) |
||
|---|---|---|---|
| Línea 6: | Línea 6: | ||
| * ''QApplication'', es la clase que gestiona el bucle principal de una aplicación con GUI y todo lo que lo envuelve (inicialización de la aplicación, finalización, sesión...). | * ''QApplication'', es la clase que gestiona el bucle principal de una aplicación con GUI y todo lo que lo envuelve (inicialización de la aplicación, finalización, sesión...). | ||
| * ''QCoreApplication'', es la clase que gestiona una aplicación Qt sin GUI. | * ''QCoreApplication'', es la clase que gestiona una aplicación Qt sin GUI. | ||
| + | |||
| + | === QStrings === | ||
| + | Para trabajar con strings, si queremos mostrarlos por consola haremos (el segundo necesita incluir ''QTextStream''): | ||
| + | <code cpp> | ||
| + | std::cout << qPrintable(d.getValue()) << std::endl; | ||
| + | QTextStream(stdout) << d.getValue(); | ||
| + | </code> | ||
| + | Para compararlos: | ||
| + | <code cpp> | ||
| + | int x = QString::compare("aUtO", "AuTo", Qt::CaseInsensitive); // x == 0 | ||
| + | int y = QString::compare("auto", "Car", Qt::CaseSensitive); // y > 0 | ||
| + | int z = QString::compare("auto", "Car", Qt::CaseInsensitive); // z < 0 | ||
| + | </code> | ||
| + | |||
| + | === Leer archivos === | ||
| + | <code cpp> | ||
| + | QFile file("/home/hamad/lesson11.txt"); | ||
| + | if(!file.open(QIODevice::ReadOnly)) { | ||
| + | QMessageBox::information(0, "error", file.errorString()); | ||
| + | } | ||
| + | QTextStream in(&file); | ||
| + | while(!in.atEnd()) { | ||
| + | QString line = in.readLine(); | ||
| + | QStringList fields = line.split(","); | ||
| + | model->appendRow(fields); | ||
| + | } | ||
| + | file.close(); | ||
| + | </code> | ||
| ==== El sistema de meta-objetos ==== | ==== El sistema de meta-objetos ==== | ||
| Es el procedimiento que Qt tiene de trabajar. Es el que añade al sistema de C++ la capacidad de utilizar signals y slots, información en tiempo de ejecución y propiedades dinámicas. En el entran en juego los siguientes elementos: | Es el procedimiento que Qt tiene de trabajar. Es el que añade al sistema de C++ la capacidad de utilizar signals y slots, información en tiempo de ejecución y propiedades dinámicas. En el entran en juego los siguientes elementos: | ||
| Línea 29: | Línea 57: | ||
| ==== Signals y Slots ==== | ==== Signals y Slots ==== | ||
| + | Es la forma que tiene Qt de manejar los eventos. Un ''signal'' se emite cuando un evento concreto ocurre, un ''slot'' es una función que se llama cuando ese signal se ha producido. | ||
| + | * La definición de un signal ha de coincidir con la del slot que la recibe. | ||
| + | * Las clases que hereden de QObject o de sus subclases pueden contener signals y slots. | ||
| + | * Puedes conectar tantos slots a un signal como desees igual que un slot puede ser conectado a varios signals. | ||
| + | * También es posible conectar un signal a otro, esto emitiría el segundo cuando el primero fuese llamado. | ||
| + | * Los signals y slots se declaran en la clase en un apartado concreto para ellos. | ||
| + | * La sintaxis para conectar un signal a un slot es la siguiente: | ||
| + | <code> | ||
| + | connect(&obj_signal, SIGNAL(funcionSignal(type_pars)), &obj_slot, SLOT(funcionSlot(type_pars)); | ||
| + | </code> | ||
| + | * Si no hay ningún slot conectado a un signal, cuando se emita el signal no ocurrirá nada. | ||
| + | * Se pueden emitir signals usando la clausula ''emit'' de la siguiente forma ''emit funcion_signal(pars)''. | ||
| + | * Se pueden desconectar todos los slots de un signal utilizando la clausula ''disconnect()''. | ||
| + | * Se puede indicar que una conexión no puede duplicarse (un mismo slot conectado a un mismo signal varias veces) pasandole a ''connect'' el flag ''Qt::UniqueConnection''. Cuando ocurra la conexión duplicada se retornará false. | ||
| + | * Cuando el signal se emite los slots son ejecutados inmediatamente. Se pueden usar ''queued connections'' para que se ejecuten independientemente del curso de la aplicación. | ||
| + | * Cuando se utiliza algún framework que tenga las clausulas ''emit'', ''signals'' o ''slot'' declaradas podremos seguir utilizando las de Qt mediante las macros ''Q_SIGNALS'', ''Q_SIGNAL'', ''Q_SLOT'', ''Q_SLOTS'' y ''Q_EMIT''. Colocando en la configuración del proyecto lo siguiente: | ||
| + | <code> | ||
| + | CONFIG += no_keywords | ||
| + | </code> | ||
| + | |||
| + | * Podemos pasar parámetros al a los slots según el objeto que lo llame utilizando la clase ''QSignalMapper''. | ||
| + | * Qt también da la posibilidad de acceder a un puntero al objeto que llamó a un slot mediante la función ''sender()''. | ||
| + | |||
| + | Sintaxis de los apartados de signals y slots en la definición de una clase: | ||
| + | <code cpp> | ||
| + | class Counter : public QObject { | ||
| + | Q_OBJECT | ||
| + | public: | ||
| + | Counter() { m_value = 0; } | ||
| + | int value() const { return m_value; } | ||
| + | public slots: | ||
| + | void setValue(int value); | ||
| + | signals: | ||
| + | void valueChanged(int newValue); | ||
| + | private: | ||
| + | int m_value; | ||
| + | }; | ||
| + | </code> | ||
| + | |||
| + | Sintaxis de una conexión: | ||
| + | <code cpp> | ||
| + | Counter a, b; | ||
| + | QObject::connect(&a, SIGNAL(valueChanged(int)), &b, SLOT(setValue(int))); | ||
| + | </code> | ||
| ===== Componentes ===== | ===== Componentes ===== | ||
| ==== QWidget ==== | ==== QWidget ==== | ||
| Línea 41: | Línea 113: | ||
| Es la ventana para la aplicación principal. Tendrá la siguiente estructura (requerirá siempre deun widget central): \\ | Es la ventana para la aplicación principal. Tendrá la siguiente estructura (requerirá siempre deun widget central): \\ | ||
| {{:fw:qt4:mainwindowlayout.png?direct&300|}} \\ | {{:fw:qt4:mainwindowlayout.png?direct&300|}} \\ | ||
| + | Es decir, si queremos añadirle un layout lo que tendremos que hacer es añadir un widget y a este el layout. | ||
| ==== QDialog ==== | ==== QDialog ==== | ||
| Es la base clase para crear ventanas de diálogo. Estas son utilizadas para que el usuario realice pequeñas tareas. Pueden ser modales o no, devolver un valor y tener botones por defecto. | Es la base clase para crear ventanas de diálogo. Estas son utilizadas para que el usuario realice pequeñas tareas. Pueden ser modales o no, devolver un valor y tener botones por defecto. | ||
| + | * El método ''exec()'' muestra el diálogo y hasta que no se cierre no continua con la ejecución. El ''show()'' sí continua. | ||
| + | * El método\signal ''accept()'' cerrará el formulario indicando que el usuario acepta. | ||
| ==== Menús principales y acciones ==== | ==== Menús principales y acciones ==== | ||
| Para crear un menú dentro de una QMainWindow lo que haremos será llamar a ''menuBar()->addMenu()'' que devolverá un objeto ''QMenu'' al cual podremos añadir objetos ''QAction'' (acciones dentro del programa que se pueden enlazar a menús, atajos de teclado...). | Para crear un menú dentro de una QMainWindow lo que haremos será llamar a ''menuBar()->addMenu()'' que devolverá un objeto ''QMenu'' al cual podremos añadir objetos ''QAction'' (acciones dentro del programa que se pueden enlazar a menús, atajos de teclado...). | ||
| Línea 72: | Línea 145: | ||
| * ''QHBoxLayout'' y ''QVBoxLayout'', para colocar los controles uno al lado del otro en horizontal y en vertical respectivamente. | * ''QHBoxLayout'' y ''QVBoxLayout'', para colocar los controles uno al lado del otro en horizontal y en vertical respectivamente. | ||
| ==== Componentes para tratar con OpenGL ==== | ==== Componentes para tratar con OpenGL ==== | ||
| + | En la configuración ha de estar agregada la opción de trabajar con opengl: | ||
| + | <code> | ||
| + | QT += core gui opengl | ||
| + | </code> | ||
| + | Y se ha de incluir ''QtOpenGL''. | ||
| === QGLWidget === | === QGLWidget === | ||
| Un objeto QGLWidget es un widget para renderizar gráficos OpenGL en aplicaciones Qt. Se hereda de él y se usa la subclase como cualquier QWidget. Las funciones para reescribir son: | Un objeto QGLWidget es un widget para renderizar gráficos OpenGL en aplicaciones Qt. Se hereda de él y se usa la subclase como cualquier QWidget. Las funciones para reescribir son: | ||
| Línea 84: | Línea 161: | ||
| === QGLShaderProgram y QGLShader === | === QGLShaderProgram y QGLShader === | ||
| - | ''QGLShader'' es la clase que recoge código GLSL para ser compilado y ''QGLShaderProgram'' se encarga de realizar dicha compilación de los diferentes shaders pasados. \\ | + | ''QGLShader'' es la clase que recoge código GLSL para ser compilado y ''QGLShaderProgram'' se encarga de realizar dicha compilación de los diferentes shaders pasados (se han de crear durante la inicialización de OpenGL). \\ |
| Debemos indicar en el constructor ''QGLShader'' qué tipo de shader es (QGLShader::Vertex o QGLShader::Fragment). \\ | Debemos indicar en el constructor ''QGLShader'' qué tipo de shader es (QGLShader::Vertex o QGLShader::Fragment). \\ | ||
| - | Para posteriormente pasar valores a los atributos de input a los shaders debemos usar el método ''bindAttributeLocation'' pasándole el nombre de este y su posición (antes de linkar el programa). \\ | + | Para posteriormente pasar valores a los atributos de input a los shaders debemos usar el método ''bindAttributeLocation'' pasándole el nombre de este y su posición (antes de linkar el programa). Si no se enlazasen las posiciones entonces serían cogidas automáticamente. |
| Para lincar el programa se utiliza ''link()'' y luego, para enlazarlo al contexto actual, ''bind()''. | Para lincar el programa se utiliza ''link()'' y luego, para enlazarlo al contexto actual, ''bind()''. | ||
| Línea 93: | Línea 170: | ||
| QGLShader *fshader = new QGLShader(QGLShader::Fragment, this); | QGLShader *fshader = new QGLShader(QGLShader::Fragment, this); | ||
| - | // Se lee el contenido de dos programas glsl y se vuelca sobre shader_source[0] el primero y shader_source[1] el segundo | + | // Se lee el contenido de dos ficheros de código glsl y se vuelcan sobre shader_source |
| + | |||
| + | vshader->compileSourceFile(vShaderFile); // De archivo | ||
| + | |||
| + | const char *fsrc = | ||
| + | "uniform sampler2D texture;\n" | ||
| + | "varying mediump vec4 texc;\n" | ||
| + | "void main(void)\n" | ||
| + | "{\n" | ||
| + | " gl_FragColor = texture2D(texture, texc.st);\n" | ||
| + | "}\n"; | ||
| + | fshader->compileSourceCode(fsrc); | ||
| - | vshader->compileSourceCode(shader_source[0].source); | ||
| - | fshader->compileSourceCode(shader_source[1].source); | ||
| QGLShaderProgram *program = new QGLShaderProgram(this); | QGLShaderProgram *program = new QGLShaderProgram(this); | ||
| program->addShader(vshader); | program->addShader(vshader); | ||
| Línea 107: | Línea 193: | ||
| program->bind(); | program->bind(); | ||
| </code> | </code> | ||
| - | |||
| ==== Otros ==== | ==== Otros ==== | ||
| === QTimer === | === QTimer === | ||
| Línea 119: | Línea 204: | ||
| ==== Cómo... ==== | ==== Cómo... ==== | ||
| * Cerrar la aplicación? Llamando al método ''closeAllWindows()'' de la aplicación. | * Cerrar la aplicación? Llamando al método ''closeAllWindows()'' de la aplicación. | ||
| + | * Mostrar un diálogo de abrir fichero ''QString fileName = QFileDialog::getOpenFileName(this);''. | ||
| === ... Gestionar los eventos de ratón\teclado en un widget? === | === ... Gestionar los eventos de ratón\teclado en un widget? === | ||
| Línea 135: | Línea 221: | ||
| * **qtconfig**: Configura el aspecto y el comportamiento de las interficies creadas con Qt en esa máquina. | * **qtconfig**: Configura el aspecto y el comportamiento de las interficies creadas con Qt en esa máquina. | ||
| ==== QtCreator ==== | ==== QtCreator ==== | ||
| + | ==== Diseñador ==== | ||
| + | * Si queremos acceder a los elementos agregados por el diseñador desde el código lo haremos a partir del objeto ''ui'' que hay en la clase: | ||
| + | <code cpp> | ||
| + | // en clase MainWindow, npd es un QDialog: | ||
| + | connect(this->ui->actionNew_Planet, SIGNAL(triggered()), npd, SLOT(show())); | ||
| + | </code> | ||
| ==== Cómo... ==== | ==== Cómo... ==== | ||
| === ... Configurar un proyecto C++ simple, sin utilizar Qt? === | === ... Configurar un proyecto C++ simple, sin utilizar Qt? === | ||