Warum wird void Dialog::paintEvent(QPaintEvent *e) ausgeführt

Alles rund um die Programmierung mit Qt
Antworten
freakonaleash99
Beiträge: 43
Registriert: 23. Juli 2017 12:35

Warum wird void Dialog::paintEvent(QPaintEvent *e) ausgeführt

Beitrag von freakonaleash99 »

Guten Tag,
ich befasse mich seit längerem hobbymäßig mit c++ Programmierung in Qt. Habe natürlich schon viele Tutorials, Unterlagen aus Uni-Vorlesungen oder Ausschnitte aus Büchern gelesen. Allerdings fällt es mir oft schwer die Theorie in der Praxis zu verstehen und umzusetzen. Ich habe aktuell ein paar Fragen zu einem kleinen Projekt welches ich programmiere, welches ich im folgenden auf das wesentliche kürze. Wenn ich Dinge falsch formuliere bitte ich um Verbesserungen.
Ich versuche Daten (Uhrzeiten mit Informationen) aus einer Textdateien einzulesen und grafisch zu visualisieren. Das Programm funktioniert auch bereits, allerdings habe ich ein paar Verständnisprobleme, da ich ein paar Dinge aus Tutorials abgeschrieben und angepasst habe. Im wesentlichen geht es um die Funktion paintEvent(QPaintEvent *e) der Klasse Dialog (void Dialog::paintEvent(QPaintEvent *e)).

Ausschnitt aus "Dialog.cpp", Header-File spare ich mir vorerst mal.

Code: Alles auswählen

Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);
}

Dialog::~Dialog()
{
    delete ui;
}


void Dialog::paintEvent(QPaintEvent *e){
    QPainter painter(this);
        QRect rec(startposition_x,startposition_y,breite,hoehe);      //Variablen vorher natürlich angelegt und mit Werten gefüllt
        painter.drawRect(rec);
}


void Dialog::on_LoadFile_clicked()
{
    QString fileName = QFileDialog::getOpenFileName(this,
          tr("LOG-File"), "/Users/michael/Desktop", tr("LOG (*.log)"));

   // Dialog::paintEvent( ??? );

}


in der main:

Code: Alles auswählen

#include "dialog.h"
#include "readin.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Dialog w;
    w.show();
    return a.exec();
}
Nun habe ich mehrere Fragen:
1. Warum wird die Funktion paintEvent(QPaintEvent *e) überhaupt beim Starten des Programms ausgeführt? in der Main wird ja nur das Objekt w der Klasse Dialog angelegt. D.h. für mein Verständnis, dass eigentlich nur alles, was im Konstruktor steht, ausgeführt werden sollte. Und dieser ist unverändert von mir. Da steht nur das drin, was von Qt vorgegeben wurde.

2. Ich möchte später, dass ich per Button die auszuwertende Datei auswählen kann, den Pfad der Datei der Funktion paintEvent übergeben (zum auswerten und festlegen, was gezeichnet werden soll) und dass die Funktion paintEvent neu ausgeführt wird. Allerdings scheitert es gerade schon daran, dass ich "paintEvent" durch klick auf einen Button (void Dialog::on_LoadFile_clicked()), ohne Übergabe des Pfades, erneut ausführen möchte, da ich nicht weiß, was die Funktion als Argument benötigt.
Kann mir jemand sagen, wozu "QPaintEvent *e" benötigt wird und was ich dann übergeben muss? Wenn ich versuche die Funktion paintEvent ohne Parameter zu implementieren, funktioniert gar nichts mehr.


Ergänzung: Aus diesem Tutorial habe ich das Grundgerüst übernommen: https://www.youtube.com/watch?v=5JE5ek_oN_0

Bin für jede Hilfe dankbar.

Grüße und einen schönen Sonntag
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Re: Warum wird void Dialog::paintEvent(QPaintEvent *e) ausgeführt

Beitrag von Christian81 »

Wann die paintEvent() - Funktion aufgerufen wird steht gut in der Doku: http://doc.qt.io/qt-5/qwidget.html#paintEvent
Sobald app.exec() aufgerufen wird, startet die Qt-Eventloop und das Fenster wird dargestellt. Sobald dies passiert wird natürlich auch das paintEvent() aufgerufen um die Elemente des Dialogs zu zeichnen.
Was Du allerdings nicht machen solltest ist, das paintEvent deines Dialogs zu überschreiben. Was Du willst ist wohl eher ein QWidget innerhalb deines Dialogs und dort das paintEvent() überschreiben so dass Du was eigenes zeichnen kannst. Aber auch das würde ich als Anfänger nicht machen sondern die Daten z.B. in einem QTextEdit oder QTableWidget/View ausgeben.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
freakonaleash99
Beiträge: 43
Registriert: 23. Juli 2017 12:35

Re: Warum wird void Dialog::paintEvent(QPaintEvent *e) ausgeführt

Beitrag von freakonaleash99 »

Ok zunächst danke für deine Antwort.
Wenn ich das richtig sehe, ist QTextEdit oder QTableWidget/View wirklich nur reine Textausgabe. So etwas habe ich auch schon geschafft.
Die grafische Ausgabe über Dialog::paintEvent funktioniert ja eigentlich auch schon, inkl. Verarbeitung der Textdatei. Also die Logik und der Ablauf selbst klappt ja und die grafische Ausgabe ist wie gewünscht. Nur der Zeitpunkt ist/war unklar und eben, wie ich die Funktion per Button wieder aufrufen kann.
QWidget könnte ne Möglichkeit sein. Werde ich mir mal anschauen.


Edit:
Ok da paintEvent von Widget verhält sich eigentlich genau gleich.
Auch da stellt sich die Frage, wie ich neu zeichnen kann per Buttonklick. Und die Frage, warum ein Pointer in der Klammer stehen muss.
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Re: Warum wird void Dialog::paintEvent(QPaintEvent *e) ausgeführt

Beitrag von Christian81 »

Wenn Du direkt in den QDialog zeichnest kann Qt in diesem QDialog nichts weiter darstellen, also auch keine Buttons oder ähnliches was Du dort mittels ui-Datei angelegt hast.
Ein Neuzeichnen per Buttonclick geht nur indirekt wie in der Doku beschrieben mittels update():
A paint event is a request to repaint all or part of a widget. It can happen for one of the following reasons:
repaint() or update() was invoked,
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
freakonaleash99
Beiträge: 43
Registriert: 23. Juli 2017 12:35

Re: Warum wird void Dialog::paintEvent(QPaintEvent *e) ausgeführt

Beitrag von freakonaleash99 »

Vielen Dank, bin zwischenzeitlich auch auf die update() Funktion gestossen mit der das ganze funktionieren sollte.

Jetzt fehlt mir nur noch eine Sache:
ich hab das ganze jetzt über QWidget realisiert: Eigene Klasse erstellt mit paintEvent - Funktion.
In der paintEvent Funktion habe ich allerdings nun noch die komplette Auswertung der Textdatei drin, da diese ja die Koordinaten enthält für die jeweilen Zeichnungen.
Ich möchte nun per Button die Datei auswählen und den Pfad verwenden.

Code: Alles auswählen

void MainWindow::on_pushButton_clicked()		
{
    QString fileName = QFileDialog::getOpenFileName(this,
          tr("LOG-File"), "/Users/michael/Desktop", tr("LOG (*.log)"));

}
Ausschnitt aus meiner Klasse "paintsomething":

Code: Alles auswählen

 
 void paintsomething::paintEvent(QPaintEvent *){
 .
 .
 .
 
  QFile file("/Users/michael/Desktop/Programmierung/test.log");		//hier soll der variable Pfad "fileName" rein.
     if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
         return;

     QTextStream in(&file);
     while (!in.atEnd()) {


         QString line = in.readLine(); 
         .
         .
         .
         .
     }
  }
         
Jede Zeile der Textdatei "test.log" wird ausgewertet und für jede Zeile ein entsprechendes Rechteck gezeichnet.
Wenn ich den Pfad direkt eingebe, funktioniert alles wunderbar. Allerdings weiß ich nicht wie ich die Verknüpfung zu dem variablen "fileName", welche durch Klick auf den Button gesetzt wird, zu der paintEvent Funktion herstellen kann....

Hättest du dafür noch einen Tip?
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Re: Warum wird void Dialog::paintEvent(QPaintEvent *e) ausgeführt

Beitrag von Christian81 »

Irgendwo musst du ja eine Instanz von paintSomething instanziieren. Und wenn Du paintSomething noch eine Methode spendierst mit der Du den Dateinamen übergeben kannst sollte es funktionieren. -> C++ Grundlagen (Pointer, Funktionen)
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
freakonaleash99
Beiträge: 43
Registriert: 23. Juli 2017 12:35

Re: Warum wird void Dialog::paintEvent(QPaintEvent *e) ausgeführt

Beitrag von freakonaleash99 »

Stimmt - irgendwie hab die diese Klassendenkweise noch nicht so drin.

Hab es jetzt so gemacht, dass ich eine eine public Variable angelegt habe, in die ich den Pfad reinschreibe. Allerdings ist hier das Problem, dass bei "update()" der neue Wert nicht übernommen wird (immer noch leer > File nicht gefunden) und die Funktion selbst kann ich nicht neu aufrufen (Fehler, s. unten).

.cpp:

Code: Alles auswählen

void paintsomething::setFileName()
{

    QString fileName = QFileDialog::getOpenFileName(this,
          tr("LOG-File"), "/Users/micheal/Desktop/", tr("LOG (*.log)"));
    paintsomething::fileName = fileName;

}

header:

Code: Alles auswählen

class paintsomething : public QWidget
{
    Q_OBJECT


public:
    QString fileName;
    explicit paintsomething(QWidget *parent = 0);
    void paintEvent(QPaintEvent *);
    void setFileName();

signals:

public slots:
};

#endif // PAINTSOMETHING_H
in der mainwindow:

Code: Alles auswählen

void MainWindow::on_pushButton_clicked()
{
    paintsomething painter;
    painter.setFileName();
   
   //  update();				//zeichnet nicht > Datei nicht gefunden; vermutlich weil die Funktion nicht komplett neu durchlaufen wird?
    //repaint(); > gleiches Ergebnis
    
    
   // painter.paintEvent(QPaintEvent *);			//bring Fehler QPaintEvent does not refer to a value
}

Den Dateipfad in paintEvent habe ich durch "paintsomething::fileName" ersetzt.
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Re: Warum wird void Dialog::paintEvent(QPaintEvent *e) ausgeführt

Beitrag von Christian81 »

Tut mir leid aber jetzt benötigst Du dringend erstmal ein C++ Grundlagen Buch ... hier fehlen elementare Programmierkenntnisse.
in on_pushButton_clicked() sollte man den QFileDialog öffnen, den zurückgegebenen Dateinamen an die paintsomething - Klasse über die setFileName - Funktion übergeben und dort kann man dann auch das Neuzeichnen triggern.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
freakonaleash99
Beiträge: 43
Registriert: 23. Juli 2017 12:35

Re: Warum wird void Dialog::paintEvent(QPaintEvent *e) ausgeführt

Beitrag von freakonaleash99 »

Ok. Dachte nicht dass es soo schlimm es :/....
Na dann noch mal von vorne.
Danke für deine Unterstützung
freakonaleash99
Beiträge: 43
Registriert: 23. Juli 2017 12:35

Re: Warum wird void Dialog::paintEvent(QPaintEvent *e) ausgeführt

Beitrag von freakonaleash99 »

Ok Thema ist erledigt. Nach ner Woche Intensivkurs muss ich selbst den kopf schütteln wenn ich meinen geposteten Code durchgehe.

Habe die programmstruktur jetzt auch umgeworfen und verwende die Paintevent Funktion gar nicht mehr sondern zeichne mit einem qpainter auf eine QPixMap und binde das in ein label ein. Genau das was ich brauche .
Antworten