Kein Qwt, eigenes Verfahren

Verschiedenes zu Qt
Pixtar
Beiträge: 97
Registriert: 5. Mai 2010 15:32

Kein Qwt, eigenes Verfahren

Beitrag von Pixtar »

Hallo liebe Gemeinde,

ich möchte kein Qwt benutzen, weil mein Projekt für kommerzielle Verwendet werden soll und soweit ich die Lizenzbestimmungen überflogen habe ich Qwt nicht 4 free. Weiterhin ist es für meine Zwecke zu mächtig.

Ich habe vor einen simplen Oszillographen nachzubauen. Die Wert kommen von einem USB-Gerät, welche per DLL ins Programm geschaufelt werden.

Mein derzeitiges Problem ist das ich mir nicht sicher bin, welche Komponenten/Objekte für mich am besten geeignet sind.

Standardmäßig müsste man ein QGraphicsView erstellen, diesem eine QGraphicsScene zuweisen und dann hat man wenigstens schon einmal das Grundgerüst stehen.
Nur ist jetzt die Frage, wie es von dort aus weitergeht, sofern QGraphicsView für schnelle Zeichnungen gut geeignet ist. (USB ist nicht gerade langsam in der Übertragung ^^)
Zurzeit nutze ich eine QBitmap in die ich meine Zeichnung mache, welche ich nach jeder Aktuallisierung erneut zum View hinzufüge bevor ich den View geleert habe.

Das kann doch nicht im Sinne des Erfinders sein, das ich nach jeder Aktuallisierung alles ""neuerstellen"" muss, ebenso beim Ändern der Größe des QBitmap's. (Früher gab es dafür noch eine resize-Funktion)

Im Thread "Effiziente Darstellung vieler, vieler graphischer Elemente?" steht geschrieben, das für viele Elemente die sich bewegen OpenGL verwendet werden soll, ist das eine generelle Aussage, der man folgen sollte oder kann ich meinen Oszillographen auf die QGraphicsView-Komponente aufsetzen?

Grüße Pixtar

PS: Mich würde ebenfalls interessieren, warum bei der copy()-Funktion von QBitmap, das Bitmap geresized wird. Sprich ich kann keinen Ausschnitt kopieren und wieder einfügen, ohne das sich die Größe des Bitmaps an den kopierten Bereich anpasst:

Code: Alles auswählen

QBitmap draw(400,400);
QPen writer;
writer.setColor(QColor(0,0,0,255));
writer.setWidth(2);
QPainter painter(test);
painter.setPen(writer);
painter.drawLine(0,0,400,400);
painter.end();
draw = draw.copy(1,0,400,400);
// draw.size().width() = 399 << kann man das verhindern?
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Re: Kein Qwt, eigenes Verfahren

Beitrag von franzf »

Pixtar hat geschrieben:ich möchte kein Qwt benutzen, weil mein Projekt für kommerzielle Verwendet werden soll und soweit ich die Lizenzbestimmungen überflogen habe ich Qwt nicht 4 free. Weiterhin ist es für meine Zwecke zu mächtig.
Dann würd ich aber nochmal den Grundkurs "Lizenzen lesen" belegen :P
http://qwt.sourceforge.net/qwtlicense.html
Da steht
1) LGPL! Heißt auch kommerzielle Programme können qwt verwenden.
2)
Static linking of applications and widgets to the
Qwt library does not constitute a derivative work
and does not require the author to provide source
code for the application or widget, use the shared
Qwt libraries, or link their applications or
widgets against a user-supplied version of Qwt.
hört sich so an als darfst du sogar statisch linken, was mit LGPL normalerweise ausgeschlossen ist.

Also nicht grübeln, verwende einfach qwt ;)
Pixtar
Beiträge: 97
Registriert: 5. Mai 2010 15:32

Beitrag von Pixtar »

franzf danke für dein Feedback in Bezug auf Qwt ... aber ...

dann arbeite ich mit Qwt und mein Grundverständnis für Qt ist nicht gewachsen. Es wäre sehr nett, wenn jemand auch auf meine Fragen eingehen könnte, bezüglich des copy()-Befehls und ob OpenGL oder QGraphicsView verwendet werden sollte, wenn es um Graphendarstellung geht.
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Du wirst auch mit QWT genug Qt lernen.
Zu deinem Problem: Ein QGraphicsView einsetzen, indem man auf Pixmaps rendert und diese anzeigt ist nicht klug ;)
Ich denke du solltest dir ein eigenes QWidget schreiben (Klasse von QWidget ableiten) und da das paintEvent() entsprechend implementieren. Wird dann so ausschauen wie die Lösung, in der du auf das Pixmap gezeichnet hast.

Code: Alles auswählen

draw = draw.copy(1,0,400,400); 
Dieses copy soll doch eben genau einen Bereich in ein neues Bild kopieren. Das nimmt dann natürlich auch die Größe des Ausschnitts an. Wenn du dich wunderst, dass sich auch das Original ändert -> weis den return von copy einfach einem neuen Objekt zu ;)
Pixtar
Beiträge: 97
Registriert: 5. Mai 2010 15:32

Beitrag von Pixtar »

Du wirst auch mit QWT genug Qt lernen.
Vielleicht ;)

Warum soll das nicht klug sein deiner Meinung nach franzf?
Ist die Performance bei einer abgeleiteten Klasse von QWidget schneller als die Klasse von QGraphicsView?

Hätte da gerne eine Begründung für deine Aussage.

--

Na gut, wenn copy() nur extrahiert, wie importiere ich das Extrahierte wieder um einen Pixel frei zu haben, das wieder 'bemalt' werden kann?
Sprich: aus einem 500pxl Bild 499pxl extrahieren und an den Anfang eines 500pxl Bilder einfügen, ohne das die Größe auf 499pxl zurückfällt.
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Pixtar hat geschrieben:Warum soll das nicht klug sein deiner Meinung nach franzf?
Ist die Performance bei einer abgeleiteten Klasse von QWidget schneller als die Klasse von QGraphicsView?
QGraphicsView ist ein vollkommen eigenständiger Ansatz. Das ganze ist Item-basiert. Jedes Item hat seine eigene paint()-Routine. Wenn ein View ein update() machen soll, zeichnet es nichts wirklich selber, sondern erstellt einen QPainter, der an die paint()-Methode der ganzen Items in der scene übergeben wird. Ist eigentlich ganz schön und nett.
Das was du jetzt gemacht hast ist ein ziemlicher Umweg. Du zeichnest auf ein Pixmap (das alleine ist schon um einiges inperformanter als direkt auf das Widget zu malen), und setzt das Bild dann in eine Scene. So ist das ganze nicht gedacht ;)
Wenn du mit GraphicsView arbeiten willst, solltest du ein eigenes QGraphicsItem implementieren, in dem du dann die paint() implementierst und da deine Sachen malst.

Aber hier ist das auch nicht wirklich nötig, du wirst mit einem einfachen QWidget am schnellsten vorwärts kommen.
Außerdem kannst du doch mal in den QWT-Sourcen spicken ;)
Pixtar
Beiträge: 97
Registriert: 5. Mai 2010 15:32

Beitrag von Pixtar »

Danke franzf, das klingt doch mal nach einer fundierten Aussage!
Sowas wollte ich beispielsweise in Erfahrung bringen, denn Performancegewinn ist immer ne schöne Sache.
In das QWT werde ich aufjedenfall mal reinschnuppern und stöbern - vorerst werde ich demnach auf ein Widget malen, so wie ich es bereits in der Rohfassung hatte. *g* (Mentor meinte QWidget wäre unangebracht, soviel dazu -.-)
Pixtar
Beiträge: 97
Registriert: 5. Mai 2010 15:32

Beitrag von Pixtar »

Sorry schon einmal im vorraus für den Doppelpost, fand es unangebracht zu editieren.

Hab da noch ne Frage bezüglich des paintEvents.
Kann ich das paintEvent auch noch anders erzeugen außer die Funktion zu überladen?

Sprich es geht konkret um das PaintDevice, welches QPainter benötigt, was nur im paintEvent mit 'this' aufrufbar ist:

Code: Alles auswählen

class Widget : public QWidget{
..
protected:
    void paintEvent(QPaintEvent *);
..
}
--------------
void Widget::paintEvent(QPaintEvent *event){
    QPainter paint(this);
}
Ich würde gerne selbst eine/mehrere Funktion/en schreiben die auf das Widget zeichnen, so müsste ich das mit einer switch-Prozedur oder Variablen lösen.

Angenehmer wäre mir soetwas wie:

Code: Alles auswählen

void Widget::paintLine(){
    QPainter paint(this);
}
void Widget::painPoint(){
    QPainter paint(this);
}
solarix
Beiträge: 1133
Registriert: 7. Juni 2007 19:25

Beitrag von solarix »

Code: Alles auswählen

void Widget::paintEvent(QPaintEvent *)
{
  QPainter p(this);
  paintLine(p);
  painPoint(p);
}

void Widget::paintLine(QPainter &paint){
    paint. ...
}
void Widget::painPoint(QPainter &paint){
     paint. ...
}
?
Pixtar
Beiträge: 97
Registriert: 5. Mai 2010 15:32

Beitrag von Pixtar »

Jo schon, aber wenn ich das handeln will, dann muss ich ja wie gesagt mit switch arbeiten. Beispiel: Dein Code würde beide Objekte malen/Funktionen aufrufen. Wenn ich das Malen der beiden Objekte getrennt steuern will muss ich mir was anders einfallen lassen:

Code: Alles auswählen

void Widget::paintEvent(QPaintEvent *)
{
  QPainter p(this);
switch(Tudies){
case 'pL':
  paintLine(p);
break;
case 'pP':
  painPoint(p);
break;
}
}

void Widget::paintLine(QPainter &paint){
    paint. ...
}
void Widget::painPoint(QPainter &paint){
     paint. ...
}
Deswegen meine Frage ob ich das PaintDevice für den QPainter selbst erstellen kann, denn so muss ich anhand einer anderen Funktion, die dem paintEvent vorraus geht, sagen was als nächstes gezeichnet werden soll:

Code: Alles auswählen

void Widget::setTudies(QString val){
   Tudies = val;
}
solarix
Beiträge: 1133
Registriert: 7. Juni 2007 19:25

Beitrag von solarix »

Wenn ich dich richtig verstehe würde ich das mit einem Strategie-Pattern lösen.. aber zur Sicherheit folgende Rückfrage: mal angenommen, du hättest die Möglichkeit

Code: Alles auswählen

void Widget::paintLine(){
    QPainter paint(this);
}
void Widget::painPoint(){
    QPainter paint(this);
}
Wie/woher würdest du dann diese beiden Methoden aufrufen wollen?
Pixtar
Beiträge: 97
Registriert: 5. Mai 2010 15:32

Beitrag von Pixtar »

Beispielsweise die Funktionen als public oder private slots deklarieren und per QPushButton aufrufen lassen.
solarix
Beiträge: 1133
Registriert: 7. Juni 2007 19:25

Beitrag von solarix »

ok... also doch ein Strategiepattern: einfach die Operation in eine eigene Klasse:

Code: Alles auswählen

void Widget::paintLine(){
    mDataPainter = new LinePainter();
}
void Widget::painPoint(){
    mDataPainter = new DotPainter();
}

void Widget::paintEvent(QPaintEvent *)
{
  QPainter p(this);
  mDataPainter->paint(p);
} 
LinePainter und DotPainter erben von einer abstrakten Baseclass mit der Operation "paint(QPainter &p)"... ich hoffe du erkennst das Prinzip.

hth..
Pixtar
Beiträge: 97
Registriert: 5. Mai 2010 15:32

Beitrag von Pixtar »

Okay, das Prinzip dahinter habe ich verstanden: http://en.wikipedia.org/wiki/Strategy_pattern#C.2B.2B

Mich würde noch interessieren, wie ich das paintEvent in einem extra Thread verschiebe. Sprich, ich könnte mein Widget nicht nur von QWidget sondern auch von QThread ableiten um dann intern das startEvent der Thread-Elternclass mit dem paintEvent der Widget-Elternclass zu verknüpfen oder halt anders herum:

Code: Alles auswählen

class Widget: public QWidget, QThread
{
..
protected:
    void paintEvent(QPaintEvent *);
    void run(QPainter *);
..
}
------------------------------------
Widget::Widget(QWidget *parent)
    : QWidget(parent), QThread(parent)
{
..
}

void Widget::run(QPainter *paint){
    paint->drawLine(0,0,300,300);
}

void Widget::paintEvent(QPaintEvent *event){
    QPainter painter(this);
    run(&painter);
}

Würde das paintEvent dann in einem eigenen Thread laufen bzw. überhaupt funktionieren, so wie ich mir das gedacht habe?
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

1) 2x von QObject ableiten (QWidget + QThread) geht nicht
2) Zeichnen in einem anderen als dem Hauptthread (überhaupt GUI-Manipulation wie setText() usw) geht nicht.
Antworten