Tabla de Contenidos

Qt4

Conceptos

Clases importantes

QStrings

Para trabajar con strings, si queremos mostrarlos por consola haremos (el segundo necesita incluir QTextStream):

std::cout << qPrintable(d.getValue()) << std::endl;
QTextStream(stdout) << d.getValue();

Para compararlos:

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

Leer archivos

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();

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:

El moc lee los ficheros C++ y para las declaraciones Q_OBJECT produce archivos C++ que serán los que se acabarán siendo compilados por el compilador.

El moc

QObject

Métodos de un QObject:

Problemas con los que te puedes encontrar

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.

connect(&obj_signal, SIGNAL(funcionSignal(type_pars)), &obj_slot, SLOT(funcionSlot(type_pars));
CONFIG += no_keywords

Sintaxis de los apartados de signals y slots en la definición de una clase:

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;
};

Sintaxis de una conexión:

Counter a, b;
QObject::connect(&a, SIGNAL(valueChanged(int)), &b, SLOT(setValue(int)));

Componentes

QWidget

Es la clase base para todos los objetos GUI. Recibe los eventos (ratón, teclado…) de la ventana y se pinta a sí mismo en la pantalla.
Todo widget es rectangular y se ordena en Z-order en la ventana donde es colocado. Si no se coloca en ninguna ventana entonces él mismo será la ventana. Las ventanas tienen un frame y una barra de título (aunque se pueden crear sin ellos). En Qt las clases especiales para crear ventanas son QMainWindow y QDialog.
El constructor acepta los siguientes argumentos:

  1. QWidget *parent, el widget padre, si es 0 (por defecto) el widget será una ventana.
  2. Qt::WindowFlags f, las flagas correspondientes a la ventana creada.

QMainWindow

Es la ventana para la aplicación principal. Tendrá la siguiente estructura (requerirá siempre deun widget central):

Es decir, si queremos añadirle un layout lo que tendremos que hacer es añadir un widget y a este el layout.

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.

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…).

Siendo openDialog y exitAct objetos QAction dentro de la clase, fileMenu un objeto QMenu, y createDialog un slot público dentro de esta también.

void MainWindow::createActions() {
    openDialog = new QAction("Hola", this);
    connect(openDialog, SIGNAL(triggered()), this, SLOT(createDialog()));
    exitAct = new QAction ("Exit", this);
    connect(exitAct, SIGNAL(triggered()), qApp, SLOT(closeAllWindows()));
}
 
void MainWindow::createMenus() {
    fileMenu = menuBar()->addMenu("File");
    fileMenu->addSeparator();
    fileMenu->addAction(openDialog);
    fileMenu->addAction(exitAct);
}
 
void MainWindow::createDialog() {
    std::cout << "abre!" << std::endl;
}

Layouts

Componentes para tratar con OpenGL

En la configuración ha de estar agregada la opción de trabajar con opengl:

QT       += core gui opengl

Y se ha de incluir QtOpenGL.

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:

Cómo hacer otras funciones con él:

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 (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).
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().

QGLShader *vshader = new QGLShader(QGLShader::Vertex, this);
QGLShader *fshader = new QGLShader(QGLShader::Fragment, this);
 
// 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);
 
QGLShaderProgram *program = new QGLShaderProgram(this);
program->addShader(vshader);
program->addShader(fshader);
 
program->bindAttributeLocation("vPosition", PROGRAM_VERTEX_ATTRIBUTE);
program->bindAttributeLocation("vColor", PROGRAM_COLOR_ATTRIBUTE);
program->link();
 
program->bind();

Otros

QTimer

Para utilizarlo has de incluir QTimer.
Su uso es algo así:

QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(processOneThing()));
timer->start();

Cómo...

... Gestionar los eventos de ratón\teclado en un widget?

Sobreescribiendo los métodos mousePressEvent, mouseMoveEvent, keyPressEvent
Aquí algunos ejemplos:

void Window::keyPressEvent(QKeyEvent *e) {
    if (e->key() == Qt::Key_Escape)
        close();
    else
        QWidget::keyPressEvent(e);
}

Herramientas

QtCreator

Diseñador

// en clase MainWindow, npd es un QDialog:
connect(this->ui->actionNew_Planet, SIGNAL(triggered()), npd, SLOT(show()));

Cómo...

... Configurar un proyecto C++ simple, sin utilizar Qt?

Para añadir librerías lo haremos desde el archivo .pro agregando (este ejemplo utiliza GLUT):

LIBS += -lglut -lGL -lGLU

Notas

if (QLabel *label = qobject_cast<QLabel *>(obj)) {
   label->setText(tr("Ping"));
} else if (QPushButton *button = qobject_cast<QPushButton *>(obj)) {
   button->setText(tr("Pong!"));
}