C ++和Qt - 2D图形问题

时间:2023-02-09 08:39:01

Mission: Draw two lines with different color on one graph with automatic cliping, by adding points bit by bit.

任务:通过自动剪裁在一个图形上绘制两条不同颜色的线条,逐点添加点。

So, what am I doing. Create class GraphWidget, inherited from QGraphicsView. Create member of QGraphicsScene. Create 2 QPainterPath instances, and add them to graphicsScene.

那么,我在做什么。创建继承自QGraphicsView的GraphWidget类。创建QGraphicsScene的成员。创建2个QPainterPath实例,并将它们添加到graphicsScene。

Then, I eventually call graphWidget.Redraw(), where call for QPainterPath.lineTo() for both instances. And I expect appearance of that lines of graphics view, but it doesn't.

然后,我最终调用graphWidget.Redraw(),其中为两个实例调用QPainterPath.lineTo()。我希望看到那些图形视图的外观,但事实并非如此。

I tired from reading Qt's doc and forums. What am I doing wrong?

我厌倦了阅读Qt的文档和论坛。我究竟做错了什么?

2 个解决方案

#1


We need to know more, what does not happen? Does the window appear at all? Are the lines not drawn? In the meantime try out this sample code if you want :) Edit: updated to show updating.

我们需要了解更多,不会发生什么?窗口是否出现?线条没有画出来吗?在此期间,如果您需要,请尝试使用此示例代码:)编辑:更新以显示更新。

#include ...

class QUpdatingPathItem : public QGraphicsPathItem {
    void advance(int phase) {
        if (phase == 0)
            return;
        int x = abs(rand()) % 100;
        int y = abs(rand()) % 100;
        QPainterPath p = path();
        p.lineTo(x, y);
        setPath(p);
    }
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QGraphicsScene s;
    QGraphicsView v(&s);

    QUpdatingPathItem item;
    item.setPen(QPen(QColor("red")));
    s.addItem(&item);
    v.show();

    QTimer *timer = new QTimer(&s);
    timer->connect(timer, SIGNAL(timeout()), &s, SLOT(advance()));
    timer->start(1000);

    return a.exec();
}

You should get something like this:

你应该得到这样的东西:

C ++和Qt  -  2D图形问题

The path in any QGraphicsPathItem can of course be updated later. You might want to keep the original painter path somewhere to avoid performance hit caused by all the path copying (I'm not sure if QPainterPath is implicitly shared...)

任何QGraphicsPathItem中的路径当然可以在以后更新。您可能希望将原始画家路径保留在某处以避免因所有路径复制而导致性能损失(我不确定是否隐式共享QPainterPath ...)

QPainterPath p = gPath.path();
p.lineTo(0, 42);
gPath.setPath(p);

Animation

It seems that you're trying to do some sort of animation/on-the-fly updating. There is entire framework for this in Qt. In the simplest form you can subclass QGraphicsPathItem, reimplement its advance() slot to automatically fetch next point from motion. The only thing left to do then would be calling s.advance() with the required frequency.

您似乎正在尝试进行某种动画/动态更新。在Qt中有完整的框架。在最简单的形式中,您可以继承QGraphicsPathItem,重新实现其advance()槽以自动从运动中获取下一个点。剩下要做的就是用所需的频率调用s.advance()。

http://doc.trolltech.com/4.5/qgraphicsscene.html#advance

#2


Evan Teran, sorry for that comment.

Evan Teran,对此评论感到抱歉。

// Constructor:
GraphWidget::GraphWidget( QWidget *parent ) :
        QGraphicsView(parent),
        bounds(0, 0, 0, 0)
{
    setScene(&scene);
    QPen board_pen(QColor(255, 0, 0));
    QPen nature_pen(QColor(0, 0, 255));
    nature_path_item = scene.addPath( board_path, board_pen );
    board_path_item  = scene.addPath( nature_path, nature_pen );
}

// Eventually called func:
void GraphWidget::Redraw() {
    if(motion) {
        double nature[6];
        double board[6];
        // Get coords:
        motion->getNature(nature);
        motion->getBoard(board);
        if(nature_path.elementCount() == 0) {
            nature_path.moveTo( nature[0], nature[1] );
        } else {
            nature_path.lineTo( nature[0], nature[1] );
        }
        if(board_path.elementCount() == 0) {
            board_path.moveTo( board[0], board[1] );
        } else {
            board_path.lineTo( board[0], board[1] );
        }
    }
}

#1


We need to know more, what does not happen? Does the window appear at all? Are the lines not drawn? In the meantime try out this sample code if you want :) Edit: updated to show updating.

我们需要了解更多,不会发生什么?窗口是否出现?线条没有画出来吗?在此期间,如果您需要,请尝试使用此示例代码:)编辑:更新以显示更新。

#include ...

class QUpdatingPathItem : public QGraphicsPathItem {
    void advance(int phase) {
        if (phase == 0)
            return;
        int x = abs(rand()) % 100;
        int y = abs(rand()) % 100;
        QPainterPath p = path();
        p.lineTo(x, y);
        setPath(p);
    }
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QGraphicsScene s;
    QGraphicsView v(&s);

    QUpdatingPathItem item;
    item.setPen(QPen(QColor("red")));
    s.addItem(&item);
    v.show();

    QTimer *timer = new QTimer(&s);
    timer->connect(timer, SIGNAL(timeout()), &s, SLOT(advance()));
    timer->start(1000);

    return a.exec();
}

You should get something like this:

你应该得到这样的东西:

C ++和Qt  -  2D图形问题

The path in any QGraphicsPathItem can of course be updated later. You might want to keep the original painter path somewhere to avoid performance hit caused by all the path copying (I'm not sure if QPainterPath is implicitly shared...)

任何QGraphicsPathItem中的路径当然可以在以后更新。您可能希望将原始画家路径保留在某处以避免因所有路径复制而导致性能损失(我不确定是否隐式共享QPainterPath ...)

QPainterPath p = gPath.path();
p.lineTo(0, 42);
gPath.setPath(p);

Animation

It seems that you're trying to do some sort of animation/on-the-fly updating. There is entire framework for this in Qt. In the simplest form you can subclass QGraphicsPathItem, reimplement its advance() slot to automatically fetch next point from motion. The only thing left to do then would be calling s.advance() with the required frequency.

您似乎正在尝试进行某种动画/动态更新。在Qt中有完整的框架。在最简单的形式中,您可以继承QGraphicsPathItem,重新实现其advance()槽以自动从运动中获取下一个点。剩下要做的就是用所需的频率调用s.advance()。

http://doc.trolltech.com/4.5/qgraphicsscene.html#advance

#2


Evan Teran, sorry for that comment.

Evan Teran,对此评论感到抱歉。

// Constructor:
GraphWidget::GraphWidget( QWidget *parent ) :
        QGraphicsView(parent),
        bounds(0, 0, 0, 0)
{
    setScene(&scene);
    QPen board_pen(QColor(255, 0, 0));
    QPen nature_pen(QColor(0, 0, 255));
    nature_path_item = scene.addPath( board_path, board_pen );
    board_path_item  = scene.addPath( nature_path, nature_pen );
}

// Eventually called func:
void GraphWidget::Redraw() {
    if(motion) {
        double nature[6];
        double board[6];
        // Get coords:
        motion->getNature(nature);
        motion->getBoard(board);
        if(nature_path.elementCount() == 0) {
            nature_path.moveTo( nature[0], nature[1] );
        } else {
            nature_path.lineTo( nature[0], nature[1] );
        }
        if(board_path.elementCount() == 0) {
            board_path.moveTo( board[0], board[1] );
        } else {
            board_path.lineTo( board[0], board[1] );
        }
    }
}