Sistema de coordenadas
El sistema de coordenadas está controlado por la clase QPainter. Junto con las clases QPaintDevice y QPaintEngine, QPainter forma la base del sistema de pintura de Qt, Arthur. QPainter se utiliza para realizar operaciones de dibujo, QPaintDevice es una abstracción de un espacio bidimensional sobre el que se puede pintar utilizando una QPainter, y QPaintEngine proporciona la interfaz que el pintor utiliza para dibujar sobre diferentes tipos de dispositivos.
La clase QPaintDevice es la clase base de los objetos que pueden pintarse: Sus capacidades de dibujo son heredadas por las clases QWidget, QImage, QPixmap, QPicture, y QOpenGLPaintDevice. El sistema de coordenadas por defecto de un dispositivo de pintura tiene su origen en la esquina superior izquierda. Los valores x aumentan hacia la derecha y los valores y aumentan hacia abajo. La unidad por defecto es un píxel en dispositivos basados en píxeles y un punto (1/72 de pulgada) en impresoras.
La asignación de las coordenadas lógicas de QPainter a las coordenadas físicas de QPaintDevice se realiza mediante la matriz de transformación de QPainter, la ventana gráfica y la "ventana". Los sistemas de coordenadas lógicas y físicas coinciden por defecto. QPainter también admite transformaciones de coordenadas (por ejemplo, rotación y escalado).
Representación
Representación lógica
El tamaño (anchura y altura) de una primitiva gráfica corresponde siempre a su modelo matemático, ignorando la anchura del lápiz con el que se renderiza:
| QRect(QPoint(1, 2), QPoint(7, 6)) | QLine(QPoint(2, 7), QPoint(6, 1)) |
| QLine(2, 7, 6, 1) | |
| QRect(QPoint(1, 2), QSize(6, 4)) | |
| QRect(1, 2, 6, 4) |
Aliased Painting
Al dibujar, el renderizado de píxeles se controla mediante la sugerencia de renderizado QPainter::Antialiasing.
El enum RenderHint se utiliza para especificar banderas a QPainter que pueden o no ser respetadas por cualquier motor dado. El valor QPainter::Antialiasing indica que el motor debe antialiasear los bordes de las primitivas si es posible, es decir, suavizar los bordes utilizando diferentes intensidades de color.
Pero por defecto el pintor tiene alias y se aplican otras reglas: Cuando se renderiza con un lápiz de un píxel de ancho los píxeles se renderizarán a la derecha y por debajo de los puntos matemáticamente definidos. Por ejemplo:
Al renderizar con un lápiz con un número par de píxeles, los píxeles se renderizarán simétricamente alrededor de los puntos definidos matemáticamente, mientras que al renderizar con un lápiz con un número impar de píxeles, el píxel sobrante se renderizará a la derecha y debajo del punto matemático como en el caso de un píxel. Véanse ejemplos concretos en los siguientes diagramas de QRectF.
| QRectF | |
|---|---|
![]() | ![]() |
| Representación lógica | Lápiz de un píxel de ancho |
![]() | ![]() |
| Lápiz de dos píxeles de ancho | Lápiz de tres píxeles de ancho |
Tenga en cuenta que, por razones históricas, el valor de retorno de las funciones QRect::right() y QRect::bottom() se desvía de la verdadera esquina inferior derecha del rectángulo.
QRectLa función right() devuelve left() + width() - 1 y la función bottom() devuelve top() + height() - 1. El punto verde inferior derecho de los diagramas muestra las coordenadas de retorno de estas funciones.
Te recomendamos que utilices QRectF en su lugar: La clase QRectF define un rectángulo en el plano utilizando coordenadas de coma flotante para mayor precisión (QRect utiliza coordenadas enteras) , y las funciones QRectF::right() y QRectF::bottom() devuelven la verdadera esquina inferior derecha.
Alternativamente, utilizando QRect, aplique x() + width() y y() + height() para encontrar la esquina inferior derecha, y evite las funciones right() y bottom().
Pintura suavizada
Si establece QPainter's anti-aliasing render hint, los píxeles se renderizarán simétricamente a ambos lados de los puntos definidos matemáticamente:
Transformaciones
Por defecto, QPainter opera en el propio sistema de coordenadas del dispositivo asociado, pero también tiene soporte completo para transformaciones de coordenadas afines.
Puede escalar el sistema de coordenadas con un desplazamiento determinado mediante la función QPainter::scale(), puede girarlo en el sentido de las agujas del reloj mediante la función QPainter::rotate() y puede trasladarlo (es decir, añadir un desplazamiento determinado a los puntos) mediante la función QPainter::translate().
También puede girar el sistema de coordenadas alrededor del origen utilizando la función QPainter::shear(). Todas las operaciones de transformación operan sobre la matriz de transformación de QPainter que puedes recuperar utilizando la función QPainter::worldTransform(). Una matriz transforma un punto del plano en otro punto.
Si necesita las mismas transformaciones una y otra vez, también puede utilizar los objetos QTransform y las funciones QPainter::worldTransform() y QPainter::setWorldTransform(). En cualquier momento puede guardar la matriz de transformación de QPainter llamando a la función QPainter::save(), que guarda la matriz en una pila interna. La función QPainter::restore() la recupera.
Una necesidad frecuente de la matriz de transformación es cuando se reutiliza el mismo código de dibujo en una variedad de dispositivos de pintura. Sin transformaciones, los resultados están estrechamente ligados a la resolución del dispositivo de pintura. Las impresoras tienen una alta resolución, por ejemplo 600 puntos por pulgada, mientras que las pantallas suelen tener entre 72 y 100 puntos por pulgada.
| Ejemplo de reloj analógico | |
|---|---|
![]() | El ejemplo del reloj analógico muestra cómo dibujar el contenido de un widget personalizado utilizando la matriz de transformación de QPainter. Le recomendamos que compile y ejecute este ejemplo antes de seguir leyendo. En particular, intente redimensionar la ventana a diferentes tamaños. |
void AnalogClock::paintEvent(QPaintEvent *) { static const QPoint hourHand[4] = { QPoint(5, 14), QPoint(-5, 14), QPoint(-4, -71), QPoint(4, -71) }; static const QPoint minuteHand[4] = { QPoint(4, 14), QPoint(-4, 14), QPoint(-3, -89), QPoint(3, -89) }; static const QPoint secondsHand[4] = { QPoint(1, 14), QPoint(-1, 14), QPoint(-1, -89), QPoint(1, -89) }; const QColor hourColor(palette().color(QPalette::Text)); const QColor minuteColor(palette().color(QPalette::Text)); const QColor secondsColor(palette().color(QPalette::Accent)); int side = qMin(width(), height()); QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); painter.translate(width() / 2, height() / 2); painter.scale(side / 200.0, side / 200.0); Trasladamos el sistema de coordenadas para que el punto (0, 0) esté en el centro del widget, en lugar de estar en la esquina superior izquierda. También escalamos el sistema en Esto nos dará un área cuadrada de 200 x 200, con el origen (0, 0) en el centro, sobre la que podemos dibujar. Lo que dibujemos se mostrará en el cuadrado más grande posible que quepa en el widget. Ver también la sección Conversión Ventana-Vista. {
QPainterStateGuard guard(&painter);
painter.rotate(30.0 * ((time.hour() + time.minute() / 60.0)));
painter.drawConvexPolygon(hourHand, 4);
}Dibujamos la aguja horaria del reloj rotando el sistema de coordenadas y llamando a QPainter::drawConvexPolygon(). Gracias a la rotación, se dibuja apuntando en la dirección correcta. El polígono se especifica como una matriz de valores x, y alternos, almacenados en la variable estática Las llamadas a QPainter::save() y QPainter::restore() que rodean el código garantizan que el código que sigue no se verá perturbado por las transformaciones que hemos utilizado. painter.setBrush(minuteColor); { QPainterStateGuard guard(&painter); painter.rotate(6.0 * time.minute()); painter.drawConvexPolygon(minuteHand, 4); } Después de eso, dibujamos los marcadores de las horas para la esfera del reloj, que consiste en doce líneas cortas a intervalos de 30 grados. Cuando ese bucle termina, el pintor ha girado un círculo completo de vuelta a su estado original, así que no necesitamos guardar y restaurar el estado. {
QPainterStateGuard guard(&painter);
painter.rotate(6.0 * time.second());
painter.drawConvexPolygon(secondsHand, 4);
painter.drawEllipse(-3, -3, 6, 6);
painter.drawEllipse(-5, -68, 10, 10);
}Hacemos lo mismo con el minutero del reloj, que está definido por los tres puntos (7, 8), (-7, 8), (0, -70). Estas coordenadas especifican una aguja más fina y más larga que el minutero. for (int j = 0; j < 60; ++j) { painter.drawLine(92, 0, 96, 0); painter.rotate(6.0); } Por último, dibujamos los marcadores de minutos de la esfera del reloj, que consisten en sesenta líneas cortas a intervalos de 6 grados. Nos saltamos uno de cada cinco marcadores de minutos porque no queremos dibujar encima de los marcadores de horas. Al final de eso, el pintor se gira de una manera que no es muy útil, pero hemos terminado con la pintura por lo que no importa. | |
Para más información sobre la matriz de transformación, consulte la documentación de QTransform.
Conversión Ventana-Puerto de Vista
Al dibujar con QPainter, especificamos puntos utilizando coordenadas lógicas que luego se convierten en las coordenadas físicas del dispositivo de pintura.
El mapeo de las coordenadas lógicas a las coordenadas físicas es manejado por QPainter's world transformation worldTransform() (descrito en la sección Transformaciones ), y QPainter's viewport() y window(). El "viewport" representa las coordenadas físicas especificando un rectángulo arbitrario. La "ventana" describe el mismo rectángulo en coordenadas lógicas. Por defecto, los sistemas de coordenadas lógicas y físicas coinciden, y son equivalentes al rectángulo del dispositivo de pintura.
Mediante la conversión ventana-puerta de vista puede hacer que el sistema de coordenadas lógicas se ajuste a sus preferencias. Este mecanismo también puede utilizarse para que el código de dibujo sea independiente del dispositivo de pintura. Puede, por ejemplo, hacer que las coordenadas lógicas se extiendan desde (-50, -50) hasta (50, 50) con (0, 0) en el centro llamando a la función QPainter::setWindow():
Ahora, las coordenadas lógicas (-50,-50) corresponden a las coordenadas físicas del dispositivo de pintura (0, 0). Independientemente del dispositivo de pintura, su código de pintura siempre operará en las coordenadas lógicas especificadas.
Al establecer la "ventana" o el rectángulo de la ventana gráfica, se realiza una transformación lineal de las coordenadas. Tenga en cuenta que cada esquina de la "ventana" se asigna a la esquina correspondiente de la ventana gráfica, y viceversa. Por esta razón, normalmente es una buena idea dejar que la ventana gráfica y la "ventana" mantengan la misma relación de aspecto para evitar deformaciones:
int side = qMin(width(), height()); int x = (width() - side / 2); int y = (height() - side / 2); painter.setViewport(x, y, side, side);
Si hacemos que el sistema de coordenadas lógico sea un cuadrado, también deberíamos hacer que la ventana gráfica sea un cuadrado utilizando la función QPainter::setViewport(). En el ejemplo anterior lo hacemos equivalente al cuadrado más grande que quepa en el rectángulo del dispositivo de pintura. Al tener en cuenta el tamaño del dispositivo de pintura al establecer la ventana o la ventana gráfica, es posible mantener el código de dibujo independiente del dispositivo de pintura.
Tenga en cuenta que la conversión ventana-puerta de vista es sólo una transformación lineal, es decir, no realiza recorte. Esto significa que si pintas fuera de la "ventana" actualmente establecida, tu pintura se transformará a la ventana gráfica utilizando el mismo enfoque algebraico lineal.

La ventana gráfica, la "ventana" y la matriz de transformación determinan cómo las coordenadas lógicas de QPainter se asignan a las coordenadas físicas del dispositivo de pintura. Por defecto, la matriz de transformación del mundo es la matriz de identidad, y la configuración de la "ventana" y la ventana gráfica son equivalentes a la configuración del dispositivo de pintura, es decir, el mundo, la "ventana" y los sistemas de coordenadas del dispositivo son equivalentes, pero como hemos visto, los sistemas pueden ser manipulados mediante operaciones de transformación y conversión ventana-puerta gráfica. La ilustración anterior describe el proceso.
Véase también Reloj analógico.
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.








