Update -> CPU-Auslastung zu hoch

Alles rund um die Programmierung mit Qt
Antworten
ossi
Beiträge: 9
Registriert: 4. Mai 2010 09:03

Update -> CPU-Auslastung zu hoch

Beitrag von ossi »

Hallo miteinander!

Ich bin noch ziehmlicher Neuling was Qt betriftt, darf aber ein Projekt damit machen. Hauptsächlich arbeite ich derzeit mit dem QT-Creator und der Version 4.6, und pfusche da im Code rum. Hier mein Problem:


Ich zeichne einen Zeiger auf ein Bild (ähnlich wie ein Tacho) und bewege diesen mit einer einfachen Routine. Per Timer wird alle 16 Milisekunden ein Update aufgerufen. Der Zeiger bewegt sich auch einwandfrei und flüssig.
Nur: die CPU-Auslastung liegt bei rund 70-80% und das bei einem ordentlichen PC. Später sollen 5 oder mehr dieser Zeiger dargestellt werden, doch schon bei 2 kommt es ordentlich zum ruckeln und die CPU ist voll ausgelastet. Gibt es vl. eine Ressourcenschonendere Variante das Programm zu realisieren?



Hier mal ein Codeschnippsel (das Zeiger-Bwegen hab ich mal weggelassen, da ich dies als Ressourcenfresser schon ausgeschlossen habe):

tacho::tacho(QWidget *parent)
: QMainWindow(parent), ui(new Ui::tacho)
{
ui->setupUi(this);
QPalette p = palette();
ui->centralWidget->setPalette(p);
ui->centralWidget->setStyleSheet("background-color: black");

QImageReader reader;
reader.setFileName("Bild.png");
ZeichenSicherung = reader.read();
Zeichenflaeche = ZeichenSicherung.copy(0,0,750,750);

QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(update()));
timer->start(16);


}

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


void tacho::paintEvent (QPaintEvent *event){

//Kopieren des leeren Bildes
Zeichenflaeche = ZeichenSicherung.copy(0,0,750,750);

QPainter painter (&Zeichenflaeche);

QPen pen(Qt::red, 1, Qt::SolidLine);
painter.setRenderHint(QPainter::Antialiasing);
painter.setPen(QPen(QBrush("#575555"), 1));


//Zeiger zeichnen
painter.setPen(pen);
QPolygon polygon;
painter.translate(374,374);
painter.setBrush(QBrush(Qt::red, Qt::SolidPattern));
painter.drawEllipse(QPoint(0,0), 25, 25);
polygon << QPoint(0,-310) << QPoint(18,0) << QPoint(0,0) << QPoint(-18,0);

painter.rotate(winkel);
painter.drawPolygon(polygon, Qt::OddEvenFill);

painter.end();
//Fertiges Bild auf den Bildschirm kopieren - ich glaube das ist der Ressourcenfressenste Befehl
ui->Bild->setPixmap(QPixmap::fromImage(Zeichenflaeche));
}

Wird die Updatefrequenz auf das 3fache erhöht, also 50ms, sinkt die CPU-Auslastung auf rund rund 45%!

Über einen Denkanstoß wäre ich sehr dankbar.

MfG,

ossi
AuE
Beiträge: 918
Registriert: 5. August 2008 10:58

Re: Update -> CPU-Auslastung zu hoch

Beitrag von AuE »

ossi hat geschrieben: Per Timer wird alle 16 Milisekunden ein Update aufgerufen. ossi
Dir ist schon klar du du ne höhere Wiederholrate hast als zB bei normalen TV????Die Updaterate von 50ms entspricht ungefähr den FPS bei TV



Daher kommt auch deine CPU Last. GUI Sachen sind immer sehr Zeit intensiv - mit sowas kannst du nen PC zum Heizkörper umfunktionieren! :D
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Abgesehen davon - warum wird es nicht direkt auf dem Bildschirm gemalt sondern erst in ein QImage ???
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Es gibt immer Optimierungsmöglichkeiten ;)

*) Das menschliche Auge kann 20 - 30 Hz wahrnehmen. Das heißt mit 50ms-Timer hast du eine relativ flüssige Darstellung, 16 ist etwas viel ^^

*) Dein QPaintEvent enthält einen hint "rect" der aktualisiert werden soll. Stell deine Aktualisierungsroutinen um, sodass du diesen hint nutzen kannst.
- Berechne aus dem Winkel, in dem der Pfeil steht, ein QRect, und ruf selber update(const QRect& rect) auf (mit dem zuerst berechneten rect) und zeichne dann auch nur diesen Ausschnitt neu.

*) Zeichenflaeche = ZeichenSicherung.copy(0,0,750,750); ?
Das rufst du in jedem (!) paintEvent auf.

BTW: Ein paintEvent() zeichnet normalerweise direkt auf das widget. Du kannst in deinem Fall das paintEvent komplett umgehen. Mal doch direkt auf das Widget!
Für was hast du denn eigentlich zusätzlich das ui? Nur wegen dem Label?

Ich kann mir mittlerweile gut vorstellen, dass das Zeichnen in das Pixmap die eigentlich Performancebremse ist. QPainter auf ein natives Widget kann Hardware-Beschleunigung nutzen, wird aber auch ohne deutlich schneller sein.
Zusätzlich zu dem Zeichnen auf das QImage hast du noch eine weitere Zeichenroutine, die das Image auf deinem Label malt.

Deshalb mein Tip:
Leite eine eigene Klasse von QWidget ab, implementiere da dein paintEvent() in dem du ganz normal auf "this" zeichnest.
ossi
Beiträge: 9
Registriert: 4. Mai 2010 09:03

Re: Update -> CPU-Auslastung zu hoch

Beitrag von ossi »

AuE hat geschrieben:
ossi hat geschrieben: Per Timer wird alle 16 Milisekunden ein Update aufgerufen. ossi
Dir ist schon klar du du ne höhere Wiederholrate hast als zB bei normalen TV????Die Updaterate von 50ms entspricht ungefähr den FPS bei TV



Daher kommt auch deine CPU Last. GUI Sachen sind immer sehr Zeit intensiv - mit sowas kannst du nen PC zum Heizkörper umfunktionieren! :D
Ist mir bewusst, ist aber eigentlich eine Vorgabe von der zukünfitgen dahinterliegenden Software. Mal sehn ob ich die noch etwas umgehen kann! :wink:



Ich habe gerade das Bild kleiner gemacht, schon hab ich 30% bei 16ms bzw. bei 50ms rausgeholt. (das ganze Bild war größer als es später sein soll)

Wie gesagt, ich bin noch Anfänger in der ganzen Sache. Das mit dem Label wurde mir Beispielsweise so erklärt, ich werd das aber ändern.

Das mit dem neuzeichnen des Bereichs kam mir schon als Idee, ich wusste nur nicht wie ich das realisieren kann! Aber ich werd jetzt mal in die Richtung weitersuchen.

Schonmal Danke für die Hilfe! :wink:
Antworten