Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Qt中使用Clipping_Qt_Qt4_Qpainter_Qtembedded_Qstyle - Fatal编程技术网

在Qt中使用Clipping

在Qt中使用Clipping,qt,qt4,qpainter,qtembedded,qstyle,Qt,Qt4,Qpainter,Qtembedded,Qstyle,如果小部件使用样式表,是否可以在小部件painEvent中使用剪辑 我的问题的背景和原因是,我想让小部件在出现和消失时都有动画效果。(类似于调整大小的圆形或方形,从中心开始的小区域会变大) 关于如何解决这个问题,我的第一个(也是唯一一个)想法是使用QPainter的剪裁,以便只绘制所需的区域 如果我将小部件的背景设置为透明,并使用QPainter中的基本绘图功能,则效果良好。但是,如果小部件应用了样式表,我如何解决这个问题呢?有可能吗 使用的Qt版本是Qt 4.8.6 我的问题是: 是否有可能

如果小部件使用样式表,是否可以在小部件
painEvent
中使用剪辑

我的问题的背景和原因是,我想让小部件在出现和消失时都有动画效果。(类似于调整大小的圆形或方形,从中心开始的小区域会变大)

关于如何解决这个问题,我的第一个(也是唯一一个)想法是使用
QPainter
的剪裁,以便只绘制所需的区域

如果我将小部件的背景设置为透明,并使用
QPainter
中的基本绘图功能,则效果良好。但是,如果小部件应用了样式表,我如何解决这个问题呢?有可能吗

使用的Qt版本是Qt 4.8.6

我的问题是:

  • 是否有可能通过上述策略实现我想要的目标
  • 有没有可能把所有的孩子都剪掉
  • 我的策略是否恰当,或者用这种方式解决是个坏主意
  • 是否还有其他想法、最佳实践、Qt类。。。那能给我想要的吗

其他信息

我没有太多的代码要显示,因为我一直在剪辑东西。但这里有一些东西可以让我了解我的尝试:

这很有效

/* Shows a small red circle inside the widget as expected */
void MyAnimatingWidget::paintEvent(QPaintEvent *ev) {
    QPainter painter(this);
    QRect rect = this->geometry()
    QStyleOption opt;

    painter.setClipRegion(QRegion(rect.width()/2, 
                                  rect.height()/2,
                                  150, 150, 
                                  QRegion::Ellipse));
    painter.setPen(QColor(255, 0, 0));
    painter.setBrush(QColor(255, 0, 0));
    painter.setOpacity(1);

    painter.drawRect(rect);
}
但以下内容不会改变任何事情:

/* This shows the widget as usual */
void MyAnimatingWidget::paintEvent(QPaintEvent *ev) {
    QPainter painter(this);
    QRect rect = this->geometry();
    QStyleOption opt;

    painter.setClipRegion(QRegion(rect.width()/2, 
                                  rect.height()/2,
                                  150, 150, 
                                  QRegion::Ellipse));
    painter.setRenderHint(QPainter::Antialiasing);
    painter.setOpacity(1);

    opt.init(this);
    style()->drawPrimitive(QStyle::PE_Widget, &opt, &painter, this);
}

此外,我注意到,即使我删除
style()->drawPrimitive(QStyle::PE_小部件,&opt,&painter,this),样式表也会被绘制行。

应用于小部件的样式表覆盖了默认情况下小部件配备的操作系统特定样式。如果您希望有(比如)Windows外观,但仍然希望使用样式表,这甚至会导致问题。无论如何,您可以检查每个样式在Qt源目录中的作用:
src/gui/styles
。对于
style(),代码如下:

case PE_Widget:
    if (w && !rule.hasDrawable()) {
        QWidget *container = containerWidget(w);
        if (styleSheetCaches->autoFillDisabledWidgets.contains(container)
            && (container == w || !renderRule(container, opt).hasBackground())) {
            //we do not have a background, but we disabled the autofillbackground anyway. so fill the background now.
            // (this may happen if we have rules like :focus)
            p->fillRect(opt->rect, opt->palette.brush(w->backgroundRole()));
        }
        break;
    }
if (q->testAttribute(Qt::WA_StyledBackground)) {
    painter->setClipRegion(rgn);
    QStyleOption opt;
    opt.initFrom(q);
    q->style()->drawPrimitive(QStyle::PE_Widget, &opt, painter, q);
}
正如您所看到的,剪辑不会以任何方式受到干扰,因此设置剪辑区域的想法应该是可行的。现在是绘画之谜。背景的绘制在
void QWidgetPrivate::paintBackground(QPainter*painter,const QRegion&rgn,int flags)const
中进行,它是从
void QWidgetPrivate::drawWidget调用的(QPaintDevice*pdev,const QRegion&rgn,const QPoint&offset,int flags,QPainter*sharedPainter,QWidgetBackingStore*backingStore)
。您可以在以下位置找到代码:
/src/gui/kernel/qwidget.cpp
。有关守则如下:

case PE_Widget:
    if (w && !rule.hasDrawable()) {
        QWidget *container = containerWidget(w);
        if (styleSheetCaches->autoFillDisabledWidgets.contains(container)
            && (container == w || !renderRule(container, opt).hasBackground())) {
            //we do not have a background, but we disabled the autofillbackground anyway. so fill the background now.
            // (this may happen if we have rules like :focus)
            p->fillRect(opt->rect, opt->palette.brush(w->backgroundRole()));
        }
        break;
    }
if (q->testAttribute(Qt::WA_StyledBackground)) {
    painter->setClipRegion(rgn);
    QStyleOption opt;
    opt.initFrom(q);
    q->style()->drawPrimitive(QStyle::PE_Widget, &opt, painter, q);
}
也许关闭属性会有所帮助?你应该从我的回答中得到的基本教训是习惯于源头潜水。Qt背后的想法很好(实例化控件,而不必担心实现细节),但它在实践中很少起作用,也就是说,您经常需要进行源代码挖掘

要将小部件的子项剪辑到任意剪辑区域,可以将它们捕获到一个pixmap中,例如:

QPixmap pixmap(widget->size());
widget->render(&pixmap);

然后手动绘制pixmap。您还可以防止它们自动重新绘制(通过
setUpdatesEnabled()
或隐藏它们),然后在
paintEvent
处理程序中手动调用它们的
render

您检查了吗?不太多,但据我所知,QAnimation和friends是用于动画本身的(随时间改变值)。但我的问题在于图纸(目前)动画中没有。你需要告诉我们,你使用的是哪个版本的Qt。@user1095108是的,对不起。版本是Qt 4.8.6。我也编辑了这个问题。谢谢你的课。我还没有试过,但是你在这里看到的方法非常有用,我想把它标记为已接受的答案。这里有一个问题:你是怎么做的你找到了相关的源代码位置?只是grepping?如果是的话,你grep/搜索了什么?我正试图尽可能多地“潜入”代码,但往往以搜索失败告终。那么你是如何做到的呢?@exilit我经常grepping是的。在大量的源代码潜入之后,你会知道感兴趣的东西驻留在哪里。但是潜入是不完整的首先进行编译。尝试执行
find-tf-name“*.cpp”| xargs grep
这非常好用!!非常感谢。现在我也会尝试剪掉孩子们。也许我可以学一点代码潜水。@exilit孩子们会自动剪掉到家长的rect,这对一些人来说是小部件的麻烦。我会用其他剪辑区域的方法更新答案。