📄 qpainter.cpp
字号:
p.drawLine(...); // drawing code p.end(); } \endcode The same example using this constructor: \code void MyWidget::paintEvent(QPaintEvent *) { QPainter p(this); p.drawLine(...); // drawing code } \endcode Since the constructor cannot provide feedback when the initialization of the painter failed you should rather use begin() and end() to paint on external devices, e.g. printers. \sa begin(), end()*/QPainter::QPainter(QPaintDevice *pd){ d_ptr = new QPainterPrivate(this); d_ptr->init(); Q_ASSERT(pd != 0); begin(pd);}/*! Destroys the painter.*/QPainter::~QPainter(){ if (isActive()) end(); delete d_ptr;}/*! Returns the paint device on which this painter is currently painting, or 0 if the painter is not active. \sa isActive()*/QPaintDevice *QPainter::device() const{ Q_D(const QPainter); return d->original_device;}/*! Returns true if begin() has been called and end() has not yet been called; otherwise returns false. \sa begin(), QPaintDevice::paintingActive()*/bool QPainter::isActive() const{ Q_D(const QPainter); if (d->engine) { return d->engine->isActive(); } return false;}/*! Initializes the painters pen, background and font to the same as the given \a widget. Call this function after begin() while the painter is active. \sa begin(), {QPainter#Settings}{Settings}*/void QPainter::initFrom(const QWidget *widget){ Q_ASSERT_X(widget, "QPainter::initFrom(const QWidget *widget)", "Widget cannot be 0"); if (!isActive()) { qWarning("QPainter::initFrom: Painter is not active, aborted"); return; } const QPalette &pal = widget->palette(); Q_D(QPainter); d->state->pen = QPen(pal.brush(widget->foregroundRole()), 0); d->state->bgBrush = pal.brush(widget->backgroundRole()); d->state->deviceFont = QFont(widget->font(), d->device); d->state->font = d->state->deviceFont; if (d->engine) { d->engine->setDirty(QPaintEngine::DirtyPen); d->engine->setDirty(QPaintEngine::DirtyBrush); d->engine->setDirty(QPaintEngine::DirtyFont); } d->state->layoutDirection = widget->layoutDirection();}/*! Saves the current painter state (pushes the state onto a stack). A save() must be followed by a corresponding restore(); the end() function unwinds the stack. \sa restore()*/void QPainter::save(){#ifdef QT_DEBUG_DRAW if (qt_show_painter_debug_output) printf("QPainter::save()\n");#endif if (!isActive()) { qWarning("QPainter::save(), painter not active"); return; } Q_D(QPainter); d->updateState(d->state); d->state = new QPainterState(d->states.back()); d->states.push_back(d->state); d->engine->state = d->state;}/*! Restores the current painter state (pops a saved state off the stack). \sa save()*/void QPainter::restore(){#ifdef QT_DEBUG_DRAW if (qt_show_painter_debug_output) printf("QPainter::restore()\n");#endif Q_D(QPainter); if (d->states.size()<=1) { qWarning("QPainter::restore(), unbalanced save/restore"); return; } else if (!isActive()) { qWarning("QPainter::restore(), painter not active"); return; } QPainterState *tmp = d->state; d->states.pop_back(); d->state = d->states.back(); d->txinv = false; // trigger clip update if the clip path/region has changed since // last save if (!d->state->clipInfo.isEmpty() && (tmp->changeFlags & (QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyClipPath))) { // reuse the tmp state to avoid any extra allocs... tmp->dirtyFlags = QPaintEngine::DirtyClipPath; tmp->clipOperation = Qt::NoClip; tmp->clipPath = QPainterPath(); d->engine->updateState(*tmp); // replay the list of clip states, for (int i=0; i<d->state->clipInfo.size(); ++i) { const QPainterClipInfo &info = d->state->clipInfo.at(i); tmp->matrix.setMatrix(info.matrix.m11(), info.matrix.m12(), info.matrix.m21(), info.matrix.m22(), info.matrix.dx() - d->redirection_offset.x(), info.matrix.dy() - d->redirection_offset.y()); tmp->clipOperation = info.operation; if (info.clipType == QPainterClipInfo::RegionClip) { tmp->dirtyFlags = QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyTransform; tmp->clipRegion = info.region; } else { // clipType == QPainterClipInfo::PathClip tmp->dirtyFlags = QPaintEngine::DirtyClipPath | QPaintEngine::DirtyTransform; tmp->clipPath = info.path; } d->engine->updateState(*tmp); } //Since we've updated the clip region anyway, pretend that the clip path hasn't changed: d->state->dirtyFlags &= ~(QPaintEngine::DirtyClipPath | QPaintEngine::DirtyClipRegion); tmp->changeFlags &= ~(QPaintEngine::DirtyClipPath | QPaintEngine::DirtyClipRegion); tmp->changeFlags |= QPaintEngine::DirtyTransform; } d->updateState(d->state); delete tmp;}/*! \fn bool QPainter::begin(QPaintDevice *device) Begins painting the paint \a device and returns true if successful; otherwise returns false. Notice that all painter settings (setPen(), setBrush() etc.) are reset to default values when begin() is called. The errors that can occur are serious problems, such as these: \code painter->begin(0); // impossible - paint device cannot be 0 QPixmap image(0, 0); painter->begin(&image); // impossible - image.isNull() == true; painter->begin(myWidget); painter2->begin(myWidget); // impossible - only one painter at a time \endcode Note that most of the time, you can use one of the constructors instead of begin(), and that end() is automatically done at destruction. \warning A paint device can only be painted by one painter at a time. \sa end(), QPainter()*/bool QPainter::begin(QPaintDevice *pd){ Q_ASSERT(pd); Q_D(QPainter); if (d->engine) { qWarning("QPainter::begin(): Painter is already active." "\n\tYou must end() the painter before a second begin()"); return false; } // Ensure fresh painter state d->state->init(d->state->painter); d->original_device = pd; QPaintDevice *rpd = redirected(pd, &d->redirection_offset); if (rpd) { pd = rpd; }#ifdef QT_DEBUG_DRAW if (qt_show_painter_debug_output) printf("QPainter::begin(), device=%p, type=%d\n", pd, pd->devType());#endif d->state->bgOrigin = QPointF(); d->device = pd; d->engine = pd->paintEngine(); if (!d->engine) { qWarning("QPainter::begin(), paintdevice returned engine == 0, type: %d\n", pd->devType()); return true; } switch (pd->devType()) { case QInternal::Widget: { const QWidget *widget = static_cast<const QWidget *>(pd); Q_ASSERT(widget); if(!d->engine->hasFeature(QPaintEngine::PaintOutsidePaintEvent) && !widget->testAttribute(Qt::WA_PaintOutsidePaintEvent) && !widget->testAttribute(Qt::WA_WState_InPaintEvent)) { qWarning("QPainter::begin: Widget painting can only begin as a " "result of a paintEvent"); return false; } break; } case QInternal::Pixmap: { const QPixmap *pm = static_cast<const QPixmap *>(pd); Q_ASSERT(pm); if (pm->isNull()) { qWarning("QPainter::begin: Cannot paint on a null pixmap"); return false; } const_cast<QPixmap *>(pm)->detach(); if (pm->depth() == 1) { d->state->pen = QPen(Qt::color1); d->state->brush = QBrush(Qt::color0); } break; } default: break; } if (d->state->ww == 0) // For compat with 3.x painter defaults d->state->ww = d->state->wh = d->state->vw = d->state->vh = 1024; // Slip a painter state into the engine before we do any other operations d->engine->state = d->state; d->engine->setPaintDevice(pd); bool begun = d->engine->begin(pd); if (!begun) { qWarning("QPainter::begin(), QPaintEngine::begin() returned false\n"); return false; } else { d->engine->setActive(begun); } // Copy painter properties from original paint device, // required for QPixmap::grabWidget() if (d->original_device->devType() == QInternal::Widget) { QWidget *widget = static_cast<QWidget *>(d->original_device); initFrom(widget); } else { d->state->layoutDirection = QApplication::layoutDirection(); // make sure we have a font compatible with the paintdevice d->state->deviceFont = d->state->font = QFont(d->state->deviceFont, d->device); } QRect systemRect = d->engine->systemRect(); if (!systemRect.isEmpty()) { d->state->ww = d->state->vw = systemRect.width(); d->state->wh = d->state->vh = systemRect.height(); } else { d->state->ww = d->state->vw = pd->metric(QPaintDevice::PdmWidth); d->state->wh = d->state->vh = pd->metric(QPaintDevice::PdmHeight); } d->redirection_offset += d->engine->coordinateOffset(); Q_ASSERT(d->engine->isActive()); if (!d->redirection_offset.isNull()) d->updateMatrix(); Q_ASSERT(d->engine->isActive()); d->state->renderHints = QPainter::TextAntialiasing; ++d->device->painters; d->state->emulationSpecifier = 0; return true;}/*! Ends painting. Any resources used while painting are released. You don't normally need to call this since it is called by the destructor. \sa begin(), isActive()*/bool QPainter::end(){#ifdef QT_DEBUG_DRAW if (qt_show_painter_debug_output) printf("QPainter::end()\n");#endif if (!isActive()) { qWarning("QPainter::end: Painter is not active, aborted"); return false; } Q_D(QPainter); if (d->states.size()>1) { qWarning("QPainter::end(), painter ended with %d saved states", d->states.size()); } bool ended = d->engine->end(); d->updateState(0); --d->device->painters; if (d->device->painters == 0) { d->engine->setPaintDevice(0); d->engine->setActive(false); } if (d->engine->autoDestruct()) { delete d->engine; } d->engine = 0; d->device = 0; return ended;}/*! Returns the paint engine that the painter is currently operating on if the painter is active; otherwise 0. \sa isActive()*/QPaintEngine *QPainter::paintEngine() const{ Q_D(const QPainter); return d->engine;}/*! Returns the font metrics for the painter if the painter is active. Otherwise, the return value is undefined. \sa font(), isActive(), {QPainter#Settings}{Settings}*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -