Исчезающий виджет в QT C

#c #qt #qt4 #fedora #qpainter

#c #qt #qt4 #fedora #qpainter

Вопрос:

Я хочу, чтобы простой QWidget, представляющий собой простой прямоугольник, исчез. Основная проблема заключается в том, что событие рисования каждый раз рисует в одном и том же месте, фактически создавая противоположный эффект, оно усиливает цвет. Есть ли какой-либо способ достижения этой функциональности? Не могли бы вы привести какой-нибудь простой пример?

Мой код: `

 #ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QTimer>

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    void paintEvent(QPaintEvent*);
    ~Widget();

private:
    Ui::Widget *ui;
    int alfa;
    int i;
    QTimer time;

};

#endif // WIDGET_H
  

`

и cpp:

 #include "widget.h"
#include "ui_widget.h"
#include <QColor>
#include <QPainter>
#include <QBrush>
#include <QTimer>
#include <QDebug>

Widget::Widget(QWidget *parent) :
    QWidget(parent,Qt::Popup | Qt::FramelessWindowHint),
    ui(new Ui::Widget),
    time()
{
    ui->setupUi(this);
    setAttribute(Qt::WA_NoSystemBackground, true);
    setAttribute(Qt::WA_TranslucentBackground, true);
    setAttribute(Qt::WA_PaintOnScreen);
    time.setInterval(500);
    time.start();
    connect(amp;time,SIGNAL(timeout()),this,SLOT(update()));
    alfa=100;
    i=0;

}

void Widget::paintEvent(QPaintEvent *)
{
    QPainter painter(this);

    int rectBase = height();

    QColor c(255,0,255);
    alfa=alfa-(i*10);
    c.setAlpha(alfa);
    qDebug()<<c.alpha();
    i  ;

    painter.setBrush(QBrush(c));
    painter.drawRect(0, 0, width(),height());


}

Widget::~Widget()
{
    delete ui;
}
  

Ответ №1:

Вам не следует полагаться на QWidget::paintEvent() изменение вашего альфа-уровня, поскольку он может быть вызван меньше или больше, чем вы хотите (несколько update() вызовов могут привести только к одному paintEvent() и paintEvent() могут быть вызваны, когда вы этого не ожидаете).

Таким образом, более надежный способ получить результат — это иметь отдельный слот, в котором вы уменьшаете альфа-уровень, а затем вызываете update() . Ваше определение класса может выглядеть следующим образом:

 class Widget : public QWidget
{
    Q_OBJECT
public:
    Widget( QWidget * inParent );

private:
    void paintEvent(QPaintEvent *);

private slots:
    void animate();

private:
    QTimer * mTimer;
    int mAlpha;
};
  

И объявление:

 Widget::Widget( QWidget * inParent )
    :
      QWidget( inParent ),
      mTimer( new QTimer( this ) ),
      mAlpha( 255 )
{
    setAttribute(Qt::WA_NoSystemBackground, true);
    setAttribute(Qt::WA_TranslucentBackground, true);
    setAttribute(Qt::WA_PaintOnScreen);
    mTimer->setInterval( 40 );
    mTimer->setSingleShot( false );
    connect( mTimer, SIGNAL(timeout()), this, SLOT(animate()) );
    mTimer->start();
}

void
Widget::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    painter.setBrush( QColor(255,0,255,mAlpha ) );
    painter.drawRect(rect());
}

void
Widget::animate()
{
    if ( mAlpha > 0 )
    {
        mAlpha -= 3;
    }
    else
    {
        mTimer->stop();
    }
    update();
}
  

Обратите внимание, что я уменьшил интервал таймера. Вы вызывали update() только каждые полсекунды. Обычно это не приводит к плавной анимации.

Комментарии:

1. У меня проблема с setAttribute (Qt::WA_PaintOnScreen); похоже, что он нужен для старой fedora и не может быть установлен на новой Ubuntu, есть предложения?

2. Я полностью замял update() проблему; очень наблюдательный. 🙂

Ответ №2:

Я получаю предупреждение с этим кодом в Kubuntu Linux, под Qt5:

QWidget::paintEngine: больше не должен вызываться

Исходная строка находится в qWarning("QWidget::paintEngine: Should no longer be called"); , в src/widgets/kernel/qwidget_qpa.cpp и немного обсуждался в этом тикете:

https://qt.gitorious.org/qt/qtbase-harmattan/commit/3037525

Вы можете заставить предупреждение прекратиться, удалив setAttribute(Qt::WA_PaintOnScreen); , что я и сделал. После удаления этой строки у меня это работает — хотя ваша модель вычитания странная. Вы изменяете альфа-значение, а также изменяете значение вычитания на каждой итерации; вы, вероятно, не собирались делать и то, и другое. Так что либо измените его на:

 QColor c (255, 0, 255);
alfa = alfa - 10;
if (alfa >= 0) {
    c.setAlpha(alfa);
} else {
    time.stop();
}
  

…или:

 QColor c(255,0,255);
if (alfa - i * 10 >= 0) {
    c.setAlpha(alfa - i * 10);
    i  ;
} else {
   time.stop();
}
  

И т.д. (Смотрите Также Примечание @PrisonMonkeys о том, что ваш таймер не обязательно является единственным источником update() вызовов.)Что касается придания этим предупреждениям более громкого звучания, чтобы вы их не пропустили, вы могли бы взглянуть на необходимый отладочный хук Noisy для Qt, который я должен обновить.

Если после изменения окно с альфа-смешением вообще не работает на вашей платформе, вам следует явно указать, каковы ваши обстоятельства is…as у меня это работает.

Комментарии:

1. есть ли какой-либо способ оставить атрибут WA_PaintOnScreen включенным? Я почти уверен, что он мне нужен в Fedora, где я тестирую приложение. Если не установлен, я получаю черный прямоугольник в качестве фона.

2. @MarcinG Интересно, что вы говорите, что используете linux / Fedora, и это не работает. Если у вас нет веских причин не использовать Qt5 и, возможно, Qt Creator , я мог бы предложить попробовать это, учитывая мой успех с этим на Kubuntu.