原文: http://zetcode.com/gui/qtjambi/painting/

在 QtJambi 编程教程的这一部分中,我们将进行绘图。

我们什么时候需要油漆? 在某些情况下,当我们需要从头开始创建小部件时。 在这种情况下,我们需要绘图。 或者我们想创建图表,特殊装饰,效果或小部件增强。

当我们在 QtJambi 库中进行绘图时,QPainter类将发挥作用。 绘图事件通过paintEvent()方法接收。 若要进行自定义绘图,我们必须重新实现此方法。

图案

在 QtJambi 中,我们可以使用各种图案来填充形状的内部。

  1. package com.zetcode;
  2. import com.trolltech.qt.core.Qt;
  3. import com.trolltech.qt.gui.QApplication;
  4. import com.trolltech.qt.gui.QPaintEvent;
  5. import com.trolltech.qt.gui.QPainter;
  6. import com.trolltech.qt.gui.QPen;
  7. import com.trolltech.qt.gui.QWidget;
  8. /**
  9. * ZetCode QtJambi tutorial
  10. *
  11. * This program draws nine rectangles.
  12. * The interiors are filled with
  13. * different built-in patterns.
  14. *
  15. * @author jan bodnar
  16. * website zetcode.com
  17. * last modified March 2009
  18. */
  19. public class JambiApp extends QWidget {
  20. public JambiApp() {
  21. setWindowTitle("Patterns");
  22. resize(350, 280);
  23. move(400, 300);
  24. show();
  25. }
  26. @Override
  27. protected void paintEvent(QPaintEvent event) {
  28. QPainter painter = new QPainter(this);
  29. drawPatterns(painter);
  30. }
  31. private void drawPatterns(QPainter painter) {
  32. painter.setPen(QPen.NoPen);
  33. painter.setBrush(Qt.BrushStyle.HorPattern);
  34. painter.drawRect(10, 15, 90, 60);
  35. painter.setBrush(Qt.BrushStyle.VerPattern);
  36. painter.drawRect(130, 15, 90, 60);
  37. painter.setBrush(Qt.BrushStyle.CrossPattern);
  38. painter.drawRect(250, 15, 90, 60);
  39. painter.setBrush(Qt.BrushStyle.Dense7Pattern);
  40. painter.drawRect(10, 105, 90, 60);
  41. painter.setBrush(Qt.BrushStyle.Dense6Pattern);
  42. painter.drawRect(130, 105, 90, 60);
  43. painter.setBrush(Qt.BrushStyle.Dense5Pattern);
  44. painter.drawRect(250, 105, 90, 60);
  45. painter.setBrush(Qt.BrushStyle.BDiagPattern);
  46. painter.drawRect(10, 195, 90, 60);
  47. painter.setBrush(Qt.BrushStyle.FDiagPattern);
  48. painter.drawRect(130, 195, 90, 60);
  49. painter.setBrush(Qt.BrushStyle.DiagCrossPattern);
  50. painter.drawRect(250, 195, 90, 60);
  51. painter.end();
  52. }
  53. public static void main(String[] args) {
  54. QApplication.initialize(args);
  55. new JambiApp();
  56. QApplication.exec();
  57. }
  58. }

在代码示例中,我们将绘制九个矩形,并用不同的画笔图案填充它们。

  1. @Override
  2. protected void paintEvent(QPaintEvent event) {
  3. QPainter painter = new QPainter(this);
  4. drawPatterns(painter);
  5. }

当需要重绘窗口区域时,将调用paintEvent()方法。 当我们调整窗口大小,最大化或最小化窗口时,就会发生这种情况。在此方法中,我们创建了QPainter对象。 此对象用于完成 QtJambi 中的所有绘图。 绘图本身被委托给drawPatterns()方法。

  1. painter.setPen(QPen.NoPen);

笔对象用于绘制形状的轮廓。 在我们的示例中,我们将不使用笔。

  1. painter.setBrush(Qt.BrushStyle.HorPattern);

我们将水平图案设置为画笔。

  1. painter.drawRect(10, 15, 90, 60);

我们使用当前的笔和画笔绘制一个矩形。 该方法的前两个参数是 x,y 坐标。 最后两个参数是矩形的宽度和高度。

  1. painter.end();

结束绘图。 释放绘图时使用的所有资源。 根据文档,在 QtJambi 中不需要此调用。 资源由析构器释放。

QtJambi 中的绘图 - 图1

图:图案

形状

QtJambi 绘图 API 可以绘制各种形状。 以下编程代码示例将显示其中的一些。

  1. package com.zetcode;
  2. import com.trolltech.qt.core.QPoint;
  3. import com.trolltech.qt.core.QPointF;
  4. import com.trolltech.qt.gui.QApplication;
  5. import com.trolltech.qt.gui.QBrush;
  6. import com.trolltech.qt.gui.QColor;
  7. import com.trolltech.qt.gui.QFont;
  8. import com.trolltech.qt.gui.QPaintEvent;
  9. import com.trolltech.qt.gui.QPainter;
  10. import com.trolltech.qt.gui.QPainterPath;
  11. import com.trolltech.qt.gui.QPen;
  12. import com.trolltech.qt.gui.QPolygon;
  13. import com.trolltech.qt.gui.QWidget;
  14. import java.util.ArrayList;
  15. import java.util.List;
  16. /**
  17. * ZetCode QtJambi tutorial
  18. *
  19. * This program draws basic shapes
  20. * available in QtJambi
  21. *
  22. * @author jan bodnar
  23. * website zetcode.com
  24. * last modified March 2009
  25. */
  26. public class JambiApp extends QWidget {
  27. public JambiApp() {
  28. setWindowTitle("Shapes");
  29. resize(350, 280);
  30. move(400, 300);
  31. show();
  32. }
  33. @Override
  34. protected void paintEvent(QPaintEvent event) {
  35. QPainter painter = new QPainter(this);
  36. drawShapes(painter);
  37. }
  38. private void drawShapes(QPainter painter) {
  39. painter.setRenderHint(QPainter.RenderHint.Antialiasing);
  40. painter.setPen(new QPen(new QBrush(QColor.darkGray), 1));
  41. painter.setBrush(QColor.darkGray);
  42. QPainterPath path1 = new QPainterPath();
  43. path1.moveTo(5, 5);
  44. path1.cubicTo(40, 5, 50, 50, 99, 99);
  45. path1.cubicTo(5, 99, 50, 50, 5, 5);
  46. painter.drawPath(path1);
  47. painter.drawPie(130, 20, 90, 60, 30*16, 120*16);
  48. painter.drawChord(240, 30, 90, 60, 0, 16*180);
  49. painter.drawRoundRect(20, 120, 80, 50);
  50. List<QPoint> points = new ArrayList<QPoint>();
  51. points.add(new QPoint(130, 140));
  52. points.add(new QPoint(180, 170));
  53. points.add(new QPoint(180, 140));
  54. points.add(new QPoint(220, 110));
  55. points.add(new QPoint(140, 100));
  56. QPolygon polygon = new QPolygon(points);
  57. painter.drawPolygon(polygon);
  58. painter.drawRect(250, 110, 60, 60);
  59. QPointF baseline = new QPointF(20, 250);
  60. QFont font = new QFont("Georgia", 55);
  61. QPainterPath path2 = new QPainterPath();
  62. path2.addText(baseline, font, "Q");
  63. painter.drawPath(path2);
  64. painter.drawEllipse(140, 200, 60, 60);
  65. painter.drawEllipse(240, 200, 90, 60);
  66. }
  67. public static void main(String[] args) {
  68. QApplication.initialize(args);
  69. new JambiApp();
  70. QApplication.exec();
  71. }
  72. }

在此代码示例中,我们在窗口上绘制了九种不同的形状。 复杂路径,饼图,和弦,圆角矩形,多边形,矩形,基于字符的形状,圆形和椭圆形。

  1. painter.setRenderHint(QPainter.RenderHint.Antialiasing);

我们在示例中使用抗锯齿。 抗锯齿形状看起来更好,但是绘制它们需要更多时间。

  1. painter.setPen(new QPen(new QBrush(QColor.darkGray), 1));
  2. painter.setBrush(QColor.darkGray);

我们使用深灰色的笔和画笔绘制形状。

  1. QPainterPath path1 = new QPainterPath();
  2. path1.moveTo(5, 5);
  3. path1.cubicTo(40, 5, 50, 50, 99, 99);
  4. path1.cubicTo(5, 99, 50, 50, 5, 5);
  5. painter.drawPath(path1);

使用QPainterPath对象创建第一个复杂形状。 QPainterPath类为绘图操作提供了一个容器。 画家路径是由许多图形构造块(例如矩形,椭圆形,直线和曲线)组成的对象。

  1. painter.drawPie(130, 20, 90, 60, 30*16, 120*16);
  2. painter.drawChord(240, 30, 90, 60, 0, 16*180);
  3. painter.drawRoundRect(20, 120, 80, 50);

这三行画出一个饼图,一个和弦和一个圆角矩形。

  1. List<QPoint> points = new ArrayList<QPoint>();
  2. points.add(new QPoint(130, 140));
  3. points.add(new QPoint(180, 170));
  4. points.add(new QPoint(180, 140));
  5. points.add(new QPoint(220, 110));
  6. points.add(new QPoint(140, 100));
  7. QPolygon polygon = new QPolygon(points);
  8. painter.drawPolygon(polygon);

我们使用五个点的列表来创建多边形。

  1. QPointF baseline = new QPointF(20, 250);
  2. QFont font = new QFont("Georgia", 55);
  3. QPainterPath path2 = new QPainterPath();
  4. path2.addText(baseline, font, "Q");
  5. painter.drawPath(path2);

这些线创建基于字符的形状。

  1. painter.drawEllipse(140, 200, 60, 60);
  2. painter.drawEllipse(240, 200, 90, 60);

这两条线分别创建一个圆和一个椭圆。

QtJambi 中的绘图 - 图2

图:形状

透明矩形

透明性是指能够透视材料的质量。 了解透明度的最简单方法是想象一块玻璃或水。 从技术上讲,光线可以穿过玻璃,这样我们就可以看到玻璃后面的物体。

在计算机图形学中,我们可以使用 alpha 合成来实现透明效果。 Alpha 合成是将图像与背景组合以创建部分透明外观的过程。 合成过程使用 Alpha 通道。 (wikipedia.org,answers.com)

  1. package com.zetcode;
  2. import com.trolltech.qt.gui.QApplication;
  3. import com.trolltech.qt.gui.QColor;
  4. import com.trolltech.qt.gui.QPaintEvent;
  5. import com.trolltech.qt.gui.QPainter;
  6. import com.trolltech.qt.gui.QPen;
  7. import com.trolltech.qt.gui.QWidget;
  8. /**
  9. * ZetCode QtJambi tutorial
  10. *
  11. * This program draws ten
  12. * rectangles with different
  13. * levels of transparency
  14. *
  15. * @author jan bodnar
  16. * website zetcode.com
  17. * last modified March 2009
  18. */
  19. public class JambiApp extends QWidget {
  20. public JambiApp() {
  21. setWindowTitle("Transparent rectangles");
  22. resize(590, 90);
  23. move(400, 300);
  24. show();
  25. }
  26. @Override
  27. protected void paintEvent(QPaintEvent event) {
  28. QPainter painter = new QPainter(this);
  29. drawRectangles(painter);
  30. }
  31. private void drawRectangles(QPainter painter) {
  32. painter.setPen(QPen.NoPen);
  33. for (int i=1; i<11; i++) {
  34. painter.setBrush(new QColor(0, 0, 255, i*25));
  35. painter.drawRect(50*i, 20, 40, 40);
  36. }
  37. }
  38. public static void main(String[] args) {
  39. QApplication.initialize(args);
  40. new JambiApp();
  41. QApplication.exec();
  42. }
  43. }

在示例中,我们将绘制十个具有不同透明度级别的矩形。

  1. painter.setPen(QPen.NoPen);

我们不用笔。

  1. for (int i=1; i<11; i++) {
  2. painter.setBrush(new QColor(0, 0, 255, i*25));
  3. painter.drawRect(50*i, 20, 40, 40);
  4. }

QColor 对象的最后一个参数是 alpha 透明度值。

QtJambi 中的绘图 - 图3

图:透明矩形

甜甜圈形状

在下面的示例中,我们通过旋转一堆椭圆来创建复杂的形状。

  1. package com.zetcode;
  2. import com.trolltech.qt.core.QPoint;
  3. import com.trolltech.qt.gui.QApplication;
  4. import com.trolltech.qt.gui.QColor;
  5. import com.trolltech.qt.gui.QPaintEvent;
  6. import com.trolltech.qt.gui.QPainter;
  7. import com.trolltech.qt.gui.QPen;
  8. import com.trolltech.qt.gui.QWidget;
  9. /**
  10. * ZetCode QtJambi tutorial
  11. *
  12. * This program draws a donut
  13. * shape
  14. *
  15. * @author jan bodnar
  16. * website zetcode.com
  17. * last modified March 2009
  18. */
  19. public class JambiApp extends QWidget {
  20. public JambiApp() {
  21. setWindowTitle("Donut");
  22. resize(350, 280);
  23. move(400, 300);
  24. show();
  25. }
  26. @Override
  27. protected void paintEvent(QPaintEvent event) {
  28. QPainter painter = new QPainter(this);
  29. drawDonut(painter);
  30. }
  31. private void drawDonut(QPainter painter) {
  32. QColor color = new QColor();
  33. color.setNamedColor("#333333");
  34. painter.setPen(new QPen(color, 0.5));
  35. painter.setRenderHint(QPainter.RenderHint.Antialiasing);
  36. int w = width();
  37. int h = height();
  38. painter.translate(new QPoint(w/2, h/2));
  39. for (double rot=0; rot < 360.0; rot+=5.0 ) {
  40. painter.drawEllipse(-125, -40, 250, 80);
  41. painter.rotate(5.0);
  42. }
  43. }
  44. public static void main(String[] args) {
  45. QApplication.initialize(args);
  46. new JambiApp();
  47. QApplication.exec();
  48. }
  49. }

在此示例中,我们创建一个甜甜圈。 形状类似于曲奇,因此得名“甜甜圈”。

  1. QColor color = new QColor();
  2. color.setNamedColor("#333333");

我们可以使用十六进制表示法来创建颜色对象。

  1. int w = width();
  2. int h = height();

在这里,我们确定窗口的宽度和高度。

  1. painter.translate(new QPoint(w/2, h/2));

我们将坐标系移到窗口的中间。 这样,我们使绘图在数学上更容易。

  1. for (double rot=0; rot < 360.0; rot+=5.0 ) {
  2. painter.drawEllipse(-125, -40, 250, 80);
  3. painter.rotate(5.0);
  4. }

我们绘制一个椭圆对象 72 次。 每次,我们将椭圆旋转 5 度。 这将创建我们的甜甜圈形状。

QtJambi 中的绘图 - 图4

图:多纳圈

绘制文字

在最后一个示例中,我们将在窗口上绘制文本。

  1. package com.zetcode;
  2. import com.trolltech.qt.core.QPoint;
  3. import com.trolltech.qt.gui.QApplication;
  4. import com.trolltech.qt.gui.QColor;
  5. import com.trolltech.qt.gui.QFont;
  6. import com.trolltech.qt.gui.QPaintEvent;
  7. import com.trolltech.qt.gui.QPainter;
  8. import com.trolltech.qt.gui.QWidget;
  9. /**
  10. * ZetCode QtJambi tutorial
  11. *
  12. * This program draws text
  13. * on the window
  14. *
  15. * @author jan bodnar
  16. * website zetcode.com
  17. * last modified March 2009
  18. */
  19. public class JambiApp extends QWidget {
  20. public JambiApp() {
  21. setWindowTitle("Soulmate");
  22. resize(370, 240);
  23. move(400, 300);
  24. show();
  25. }
  26. @Override
  27. protected void paintEvent(QPaintEvent event) {
  28. QPainter painter = new QPainter(this);
  29. drawLyrics(painter);
  30. }
  31. private void drawLyrics(QPainter painter) {
  32. painter.setBrush(new QColor(25, 25, 25));
  33. painter.setFont(new QFont("Purisa", 10));
  34. painter.drawText(new QPoint(20, 30),
  35. "Most relationships seem so transitory");
  36. painter.drawText(new QPoint(20, 60),
  37. "They're good but not the permanent one");
  38. painter.drawText(new QPoint(20, 120),
  39. "Who doesn't long for someone to hold");
  40. painter.drawText(new QPoint(20, 150),
  41. "Who knows how to love without being told");
  42. painter.drawText(new QPoint(20, 180),
  43. "Somebody tell me why I'm on my own");
  44. painter.drawText(new QPoint(20, 210),
  45. "If there's a soulmate for everyone");
  46. }
  47. public static void main(String[] args) {
  48. QApplication.initialize(args);
  49. new JambiApp();
  50. QApplication.exec();
  51. }
  52. }

我们在窗口上画一首歌歌词。

  1. painter.setFont(new QFont("Purisa", 10));

我们为文本设置了 Purisa 字体。

  1. painter.drawText(new QPoint(20, 30),
  2. "Most relationships seem so transitory");

drawText()方法用于绘制文本。

QtJambi 中的绘图 - 图5

图:绘制文本

在 QtJambi 编程教程的这一部分中,我们做了一些绘图。