うまくいけば、タスクを達成するために利用する必要があるメカニズムを理解するのに役立つ簡単な例を設定しました。
これはListener
、データをリッスンして描画用に送信するクラスで構成されていWidget
ます。私の例では、データがランダムに生成され、タイマーを使用して定期的に送信されるように設定しましたが、あなたの場合はシリアルポートデータになります。
あなたがやりたいことはプロットだと思うので、 を使用しpaintEvent
て単一のポイントを描画することはできません。毎回 1 つのポイントしか表示されず、ポイント データが蓄積されないためです。そのため、ピックスマップに描画する必要があります。に表示しますpaintEvent
。
Widget クラスと Listener クラスは次のとおりです。
class Widget : public QWidget {
Q_OBJECT
public:
Widget(QWidget *parent = 0) : QWidget(parent) {
resize(200, 200);
p = new QPixmap(200, 200);
}
protected:
void paintEvent(QPaintEvent *) {
QPainter painter(this);
painter.drawPixmap(0, 0, 200, 200, *p);
}
public slots:
void receiveData(int x, int y) {
QPainter painter(p);
painter.setBrush(Qt::black);
QPoint point(x, y);
painter.drawPoint(point);
data.append(point);
repaint();
}
private:
QPixmap *p;
QVector<QPoint> data;
};
class Listener : public QObject {
Q_OBJECT
public:
Listener(QObject *p = 0) : QObject(p) {
QTimer * t = new QTimer(this);
t->setInterval(200);
connect(t, SIGNAL(timeout()), this, SLOT(sendData()));
t->start();
}
signals:
void dataAvaiable(int, int);
public slots:
void sendData() {
emit dataAvaiable(qrand() % 200, qrand() % 200);
}
};
...そしてメイン:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
Listener l;
QObject::connect(&l, SIGNAL(dataAvaiable(int,int)), &w, SLOT(receiveData(int,int)));
w.show();
return a.exec();
}
So what happens is a random data will be generated every 200 msec, sent to the Widget, where it is added to the pixmap and the Widget
is updated to show the new entry.
EDIT: Considering how small a point (pixel) is, you may want to draw small circles instead. You can also color the point based on its data values, so you can get a gradient, for example low values might be green, but the higher it gets it can turn yellow and finally red...
You also might want to add the received data to a QVector<QPoint>
if you will need it later, this can be done in the receiveData
slot.
Another thing that might be worth mentioning - in the example everything is in range 0-200, the data, the plot window - very convenient. In reality this won't be the case, so you will need to map the data to the plot size, which may be changing depending on the widget size.
Here is a template I commonly use to normalize values in some range. You may want to simplify it a bit depending on your requirements.
template <typename Source, typename Target>
Target normalize(Source s, Source max, Source min, Target floor, Target ceiling) {
return ((ceiling - floor) * (s - min) / (max - min) + floor);
}
Edit2: Added the data
vector to store all the received points in numerical form.