あなたが見ている効果は純粋に精神的なものです。これは人間の欠陥であり、ソフトウェアの欠陥ではありません。私は真剣です。 x
の値を固定することで確認することができます。フリッカーはないので、ウィンドウ上のピクスマップ全体をまだ再ペイントしていますが、フリッカーはありません。
スクロール速度がリアルタイムの経過に拘束されていない場合、心理的フリッカーが発生します。場合によっては、アップデートの間隔がCPUの負荷やシステムタイマーの不正確さのために変化する場合、我々のビジュアルシステムは2つのイメージを統合し、全体の明るさが変更されたかのように見えます。
背景を灰色に設定して画像のコントラスト比を下げると、知覚されるちらつきが減少することに気付きました。これは、その効果が精神的なものであるというさらなる手がかりです。
以下はこの効果を防ぐ方法です。スクロール距離が時間とどのように結びついているかに注目してください(ここでは1ms = 1ピクセル)。
#include <QElapsedTimer>
#include <QPaintEvent>
#include <QBasicTimer>
#include <QApplication>
#include <QPainter>
#include <QPixmap>
#include <QWidget>
#include <QDebug>
static inline int rand(int range) { return (double(qrand()) * range)/RAND_MAX; }
class Widget : public QWidget
{
float fps;
qint64 lastTime;
QPixmap pixmap;
QBasicTimer timer;
QElapsedTimer elapsed;
void timerEvent(QTimerEvent * ev) {
if (ev->timerId() == timer.timerId()) update();
}
void paintEvent(QPaintEvent * ev) {
qint64 time = elapsed.elapsed();
qint64 delta = time - lastTime;
lastTime = time;
if (delta > 0) {
const float weight(0.05);
fps = (1.0-weight)*fps + weight*(1E3/delta);
if (pixmap.size() != size()) {
pixmap = QPixmap(size());
pixmap.fill(Qt::black);
}
int dy = qMin((int)delta, pixmap.height());
pixmap.scroll(0, dy, pixmap.rect());
QPainter pp(&pixmap);
pp.fillRect(0, 0, pixmap.width(), dy, Qt::black);
for(int i = 0; i < 30; ++i){
int x = rand(pixmap.width());
pp.fillRect(x, 0, 3, dy, Qt::green);
}
}
QPainter p(this);
p.drawPixmap(ev->rect(), pixmap, ev->rect());
p.setPen(Qt::yellow);
p.fillRect(0, 0, 100, 50, Qt::black);
p.drawText(rect(), QString("FPS: %1").arg(fps, 0, 'f', 0));
}
public:
explicit Widget(QWidget *parent = 0) : QWidget(parent), fps(0), lastTime(0), pixmap(size())
{
timer.start(1000/60, this);
elapsed.start();
setAttribute(Qt::WA_OpaquePaintEvent);
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
ペイントイベント間でピックスマップペイントのQPainterインスタンスを保持することは非常に珍しいことです。 QPainterがまだpixmap上で開いている間に別のペイントデバイスにピックスマップをペイントすると、その動作が未定義になることがあります。 –
私はちらつきのない応答(メモリを犠牲にして)を得るために起動する必要があるダブルバッファリングについて何か覚えています。 – RedX
@RedX、AFAIK、Qtは現在ダブルバッファリングをサポートしており、追加のダブルバッファリングコードを書く必要はありません。 – Anony