как отправить координату Qline в виджет QPainter - PullRequest
1 голос
/ 28 мая 2011

Я создал Qwidget, Form_temp, который рисует линии на основе массива данных, созданных в родительском виджете MainWindow. Проблема, с которой я сталкиваюсь, заключается в том, что данные, которые я отправляю из MainWindow в Form_temp через слот send_data, не видны другим функциям в Form_temp. (PaintEvent).

Я не могу понять, что такое петля. Я добавил несколько точек отладки, чтобы проверить, что данные поступают в Form_temp.

Вот код с некоторыми пояснениями. Я сделал это с QTCreator Пожалуйста, помогите, я потратил несколько дней на это и не могу двигаться вперед.

Другой вопрос: рисование происходит каждый раз, когда пользователь перемещает мышь, или другой виджет обновляет его вид (например, у меня есть метка, показывающая время). Я хотел бы отфильтровать QPaintevens, я просто хочу обновления, когда данные изменяются. Есть ли лучший способ сделать это, чем то, что я кодировал?

Qwidget: header

    #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: core

#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];
     }
}

MainWindow: заголовок

    #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::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);
   }
  [...]

Спасибо за чтение. Себастьен.

1 Ответ

0 голосов
/ 28 мая 2011

Очень сложно оценить код, так как он размещен здесь.

Похоже, вы создали подкласс QWidget, Form_temp, используя Qt Designer, что означает, что у него есть некоторый дополнительный багаж времени разработки, который ему на самом деле не нужен.

Когда вы создаете свой экземпляр Form_temp, вы не устанавливаете MainWindow в качестве родительского элемента в конструкторе, поэтому я не совсем уверен, как ваш собственный виджет будет рисовать сам себя, поскольку он никогда не получает вызов show() сама. Это также никогда не разрушается.

Необходимая проводка для использования слота и реализации также отсутствует, поэтому невозможно определить, является ли это проблемной областью в этой ситуации.

Тем не менее, у вас должна быть возможность достичь своей цели :) Я настоятельно рекомендую вам ознакомиться с примером Qt Analog Clock , поскольку он довольно хорошо демонстрирует, как реализовать свой собственный виджет.

Вы упоминаете, что хотите, чтобы ваш виджет обновлялся только при изменении данных, но вы неправильно понимаете, как работает платформа Qt. Вы хотите, чтобы ваш виджет рисовал сам, когда вы изменяете данные, но это не единственный раз, когда виджет должен рисовать сам, поэтому вы не должны пытаться ограничивать операцию рисования таким образом.

Поместите код в paintEvent(), который закрасит весь виджет так, как вы хотите, чтобы он отображался на основе текущих данных. Фреймворк будет выполнять paintEvent() при первом появлении виджета, когда он открывается после того, как ранее был скрыт другим окном, и во многих других ситуациях, над которыми вы не можете управлять.

Добавьте обычные методы (не требующие слотов), которые позволяют вам изменять базовые данные извне класса и обеспечивать, чтобы эти методы включали вызов update() в конце их, чтобы они сигнализировали каркасу, что виджет следует перекрасить.

Если ваш виджет сложный и медленный для рисования, вы можете посмотреть на область, указанную в событии, переданном в paintEvent(), чтобы ограничить ваш код рисования только той областью, которую нужно обновить.

UPDATE:

Ваш код близок. Я обрезал его до самого необходимого, чтобы продемонстрировать основы. Вы должны быть в состоянии уточнить это для ваших нужд.

main.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 */

main.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);
}
...