【问题标题】:how to send Qline coordinate to a QPainter Widget如何将 Qline 坐标发送到 QPainter Widget
【发布时间】:2011-05-28 05:22:19
【问题描述】:

我创建了一个 Qwidget Form_temp,它根据在父窗口小部件 MainWindow 中创建的数据数组绘制线条。我面临的问题是我通过插槽 send_data 从 MainWindow 发送到 Form_temp 的数据在 Form_temp 中的其他函数看不到。 (paintEvent)。

我无法找出循环孔。我添加了几个 Debug 点来验证数据是否到达 Form_temp。

这是带有一些解释的代码。我是用 QTCreator 做的,请帮忙,我花了几天时间,无法继续前进。

另一个问题:每次用户移动鼠标或另一个小部件正在更新其视图时都会发生paintEven(例如,我有一个显示时间的标签)。我想过滤 QPaintevens,我只想在数据更改时进行更新。有没有比我编码的更好的方法来做到这一点?

Qwidget:标题

    #ifndef FORM_TEMP_H
    #define FORM_TEMP_H
    #include <QWidget>
    #include <QDebug>

    namespace Ui { class Form_temp;   }

    class Form_temp : public QWidget        {
        Q_OBJECT
    public:
        QPainter *p;
        void paintEvent(QPaintEvent*);
        explicit Form_temp(QWidget *parent = 0);
        ~Form_temp();
        void send_data (int *parray, int asize);

        int array[48];
        int size;
        bool myupdate;

    private:
        Ui::Form_temp *ui;
    };

    #endif // FORM_TEMP_H

Qwidget:核心

#include "form_temp.h"
#include "ui_form_temp.h"
#include <cstdlib>
#include <QPainter>
#include <QDebug>

Form_temp::Form_temp(QWidget *parent) : QWidget(parent), ui(new Ui::Form_temp) {
    myupdate = false;
    ui->setupUi(this);
}
Form_temp::~Form_temp() { delete ui; }

void Form_temp::paintEvent(QPaintEvent*) {
    qDebug("Paintevent occurs");
    if (myupdate) {     // Event happen whenever I move the mouse,
                        // I only want an update when data changes.
      p = new QPainter(this);
      QPen pen(Qt::green, 3, Qt::DashDotLine, Qt::RoundCap, Qt::RoundJoin);
      p->setPen(pen);
      p->setRenderHint(QPainter::Antialiasing,true);

      qDebug()<< "this size" <<size;        
      for (int i= 0; i< size; ++i) {
         qDebug()<< "array[i" <<i <<"]="<< array[i];
      }
      [...]
      p->drawLine(x1,y1,x2,y2);
      [...]
    }
myupdate = false;  
}

void Form_temp::send_data (int *parray, int asize){
    size = asize;
     for (int i= 0; i< asize; ++i) {array[i] = parray[i];}
     myupdate = true;  // make sure the event will update the drawing
     this->update();   // create a Qpaint Event

     qDebug()<< size;  // print the data so we know we are passing data correctly
     for (int i= 0; i< asize; ++i) {
        qDebug()<< "array[i" <<i <<"]="<< array[i];
     }
}

主窗口:标题

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H

    #include <QMainWindow>
    #include <QtGui>
    #include "gpio.h"
    #include "form_temp.h"
    namespace Ui {
        class MainWindow;
    }

    class MainWindow : public QMainWindow
    {
        Q_OBJECT

    public:
        explicit MainWindow(QWidget *parent = 0);
        ~MainWindow();
        //QPropertyAnimation *m_ani ;
        //QPropertyAnimation *m_ani2 ;
        Form_temp *temp_graph;
    [...]
    #endif // MAINWINDOW_H

主窗口:核心

    MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow){

        // Start UI
        ui->setupUi(this);

        temp_graph = new Form_temp;
        startTimer(1000); // get timer event every sec.

   }

   void MainWindow::timerEvent(QTimerEvent *event)  {

      int data[]= {1,2,3};
      temp_graph->send_data(data, 3);
   }
  [...]

感谢阅读。塞巴斯蒂安。

【问题讨论】:

  • 为什么不使用 std::vector 或 QVector
  • 你已经剪掉了很多有趣的代码。 p-&gt;drawLine(x1,y1,x2,y2); 中的 x1,x2,y1,y2 是从哪里获得的?
  • 你说 send_data() 是一个槽,但没有这样声明。

标签: c++ qt class qpainter


【解决方案1】:

这里发布的代码很难评估。

看起来您使用 Qt Designer 创建了 QWidget 子类 Form_temp,这意味着它有一些它并不真正需要的额外设计时包袱。

当您创建Form_temp 的实例时,您并没有在构造函数中将MainWindow 设置为父级,所以我不太确定您的自定义小部件将如何绘制自己,因为它从未收到对show() 本身。它也永远不会被破坏。

也不存在使用插槽和实现所需的接线,因此无法确定在这种情况下这是否是问题区域。

您应该可以实现您的目标:) 我强烈建议您查看Qt Analog Clock Example,因为它很好地展示了如何实现您自己的小部件。

您提到您只希望小部件在更改数据时自行更新,但您误解了 Qt 框架的运行方式。您希望小部件在更改数据时自行绘制,但这不是小部件需要绘制自身的唯一时间,因此您不应尝试以这种方式限制绘制操作。

将代码放入paintEvent(),它将根据当前数据绘制整个小部件,使其显示为您希望的样子。框架将在小部件首次出现时执行paintEvent(),当它在先前被另一个窗口遮蔽后显示时以及您无法控制的许多其他情况。

添加允许您从类外部更改底层数据的普通方法(不需要插槽),并确保这些方法在它们的末尾包含对 update() 的调用,以便它们向框架发出小部件的信号应该重新粉刷。

如果您的小部件复杂且绘制速度慢,您可以查看传递给paintEvent() 的事件中指定的区域,以将您的绘制代码限制在需要更新的区域。

更新:

您的代码很接近。我已将其精简为基本要素以展示基础知识。您应该能够根据您的需要对其进行详细说明。

ma​​in.cpp

#include <QApplication>
#include "MainWindow.h"

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    MainWindow mainWindow;
    mainWindow.show();
    return app.exec();
}

MainWindow.h

#ifndef _MAINWINDOW_H
#define _MAINWINDOW_H

#include "Form_temp.h"

#include <QWidget>
#include <QTimer>

class MainWindow : public QWidget
{
    Q_OBJECT
public:
    MainWindow();
    virtual ~MainWindow();

private:
    Form_temp *temp_graph;   
    QTimer m_timer;

private slots:
    void slot_timeout();

};

#endif  /* _MAINWINDOW_H */

ma​​in.cpp

#include "MainWindow.h"

MainWindow::MainWindow():
    temp_graph(0),
    m_timer(this)
{
    temp_graph = new Form_temp(this);
    connect(&m_timer, SIGNAL(timeout()), this, SLOT(slot_timeout()));
    m_timer.start(1000);
}

MainWindow::~MainWindow()
{
}

void MainWindow::slot_timeout()
{
    int y = temp_graph->getY();

    y++;
    if(y > 10)
    {
        y = 0;
    }

    temp_graph->setY(y);
}

Form_temp.h

#ifndef _FORM_TEMP_H
#define _FORM_TEMP_H

#include <QWidget>

class Form_temp : public QWidget
{
    Q_OBJECT
public:
    Form_temp(QWidget *parent = 0);
    virtual ~Form_temp();

    void setY(const int newY);
    int  getY();

protected:
    void paintEvent(QPaintEvent *event);

private:
    int m_y;
};

#endif  /* _FORM_TEMP_H */

Form_temp.cpp

#include "Form_temp.h"
#include <iostream>
#include <QPaintEvent>
#include <QPainter>
#include <QPen>

using namespace std;

Form_temp::Form_temp(QWidget *parent) :
    QWidget(parent),
    m_y(1)
{
    cout << "Form_temp created." << endl;
}

void Form_temp::setY(const int newY)
{
    m_y = newY;
    update();
}

int Form_temp::getY()
{
    return m_y;
}

Form_temp::~Form_temp()
{
    cout << "Form_temp destroyed." << endl;
}

void Form_temp::paintEvent(QPaintEvent *event)
{
    cout << "Form_temp paintEvent." << endl;

    QPainter p(this);

    QPen pen(Qt::green, 3, Qt::DashDotLine, Qt::RoundCap, Qt::RoundJoin);
    p.setPen(pen);
    p.setRenderHint(QPainter::Antialiasing, true);

    p.drawLine(0, m_y, width(), m_y);
}

【讨论】:

  • 感谢您的反馈。我写了插槽,但实际上我只使用函数 send_data 将数据从 MainWindow 传输到该类;我只是看了一下上面提到的例子。我想我得到了 10000 英尺的视图,但可能还没有所有的细节。您能否详细说明“您没有在构造函数中将 MainWindow 设置为父级”,您能否给我看一个代码示例?
  • 我已经通过修改您的代码来更新我的答案以显示关键点。它使用 MainWindow 中的计时器来增加线条绘制小部件的 Y 分量。这将在小部件的顶部画一条线,并且每一秒,这条线都会变低,直到达到 10,然后重置回顶部。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-12-01
  • 2019-03-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多