我已经设置了一个快速示例,希望能帮助您了解完成任务所需使用的机制。
它由一个Listener
侦听数据并将其发送到Widget
绘图的类组成。在我的示例中,我对其进行了设置,以便使用计时器随机生成并定期发送数据,但在您的情况下,这将是您的串行端口数据。
由于我假设您要做的是一个绘图,因此您不能使用paintEvent
来绘制单点,因为每次它只会显示一个点并且点数据不会累积,所以您需要绘制一个像素图,您只需显示在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();
}
所以发生的情况是每 200 毫秒生成一个随机数据,发送到小部件,在那里它被添加到像素图并Widget
更新以显示新条目。
编辑:考虑到一个点(像素)有多小,你可能想画小圆圈。您还可以根据其数据值对点进行着色,这样您就可以获得渐变,例如低值可能是绿色,但它得到的越高,它会变成黄色,最后变成红色......
如果您以后需要它,您还可能希望将接收到的数据添加到 a QVector<QPoint>
,这可以在receiveData
插槽中完成。
可能值得一提的另一件事 - 在示例中,所有内容都在 0-200 范围内,数据,绘图窗口 - 非常方便。实际上情况并非如此,因此您需要将数据映射到绘图大小,这可能会根据小部件大小而变化。
这是我常用来规范化某个范围内的值的模板。您可能希望根据您的要求对其进行一些简化。
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:添加了data
向量以数字形式存储所有接收到的点。