2011-09-24 4 views
3

Donc j'essaye de faire un gui pour un programme d'effets de guitare. Un but est de permettre aux autres de concevoir des «skins» svg pour personnaliser le look. J'ai fait des widgets qui ont hérité de chaque widget (c'est-à-dire qdial) et dans l'initialiseur charge le fichier svg spécifié par le skin dans un qGraphicsSvgItem. Ceci est mis dans une scène et une vue et j'ai surchargé le redimensionner et repeindre de manière appropriée. Cela marche.Custom look svg widgets GUI en QT, très mauvaise performance

Lorsque je charge plusieurs de ces widgets personnalisés svg (5 cadrans, un bouton et un led) dans un widget parent les rails du processeur et mon programme se fige. Est-ce que je vais tout à fait dans le mauvais sens? Devrais-je même utiliser QT? Cela semblait plus facile que d'essayer de tout faire avec une feuille de style (surtout je ne pouvais pas comprendre comment changer l'apparence du cadran). Cela améliorerait-il les choses à laisser les widgets sous forme de qGraphicsSvgItems et les placer tous dans la scène et la vue du widget parent? Ceci est censé être un programme de traitement du signal en temps réel, donc je ne veux pas brûler beaucoup de cpu dans l'interface graphique. J'ai essayé de faire des recherches à ce sujet mais je n'ai pas trouvé beaucoup de choses pour svg. Je ne vois pas non plus de vérificateur de performance dans qtCreator ou j'essaierais de voir quel est le goulot d'étranglement. De toute façon j'apprécierais vraiment tout conseil que vous pourriez offrir avant que je passe plus de temps essayant de faire quelque chose dans le mauvais sens.

Merci beaucoup! _ssj71

p.s. Voici le code (je l'espère assez) un widget svg:

#ifndef QSVGDIAL_H 
#define QSVGDIAL_H 

#include <QWidget> 
#include <QDial> 
#include <QtSvg/QSvgRenderer> 
#include <QtSvg/QGraphicsSvgItem> 
#include <QGraphicsView> 
#include <QGraphicsScene> 

class qSVGDial : public QDial 
{ 
    Q_OBJECT 

public: 
    explicit qSVGDial(QWidget *parent = 0); 
    explicit qSVGDial(QString knobFile = "defaultKnob.svg", QString needleFile = "defaultNeedle.svg", QWidget *parent = 0); 
    ~qSVGDial(); 

private: 
    void paintEvent(QPaintEvent *pe); 
    void resizeEvent(QResizeEvent *re); 
    float degPerPos; 
    float middle; 
    float mysize; 
    QGraphicsView view; 
    QGraphicsScene scene; 
    QGraphicsSvgItem *knob; 
    QGraphicsSvgItem *needle; 
    QSize k,n; 

}; 

#endif // QSVGDIAL_H 

cpp:

#include "qsvgdial.h" 
#include "math.h" 

qSVGDial::qSVGDial(QWidget *parent) : 
    QDial(parent) 
{ 
    knob = new QGraphicsSvgItem("defaultKnob.svg"); 
    needle = new QGraphicsSvgItem("defaultNeedle.svg"); 
    view.setStyleSheet("background: transparent; border: none"); 

    k = knob->renderer()->defaultSize(); 
    n = needle->renderer()->defaultSize(); 
    needle->setTransformOriginPoint(n.width()/2,n.height()/2); 
    knob->setTransformOriginPoint(k.width()/2,k.height()/2); 
    degPerPos = 340/(this->maximum() - this->minimum()); 
    middle = (this->maximum() - this->minimum())/2; 
    mysize = k.width(); 
    if (mysize<n.width()) mysize = n.width(); 
    if (mysize<k.height()) mysize = k.height(); 
    if (mysize<n.height()) mysize = n.height(); 
    mysize = sqrt(2)*mysize; 
    view.setDisabled(true); 
    view.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); 
    view.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); 
    scene.addItem(knob); 
    scene.addItem(needle); 
    view.setScene(&scene); 
    view.setParent(this,Qt::FramelessWindowHint); 
} 

qSVGDial::qSVGDial(QString knobFile, QString needleFile, QWidget *parent) : 
    QDial(parent) 
{ 
    knob = new QGraphicsSvgItem(knobFile); 
    needle = new QGraphicsSvgItem(needleFile); 
    view.setStyleSheet("background: transparent; border: none"); 
    k = knob->renderer()->defaultSize(); 
    n = needle->renderer()->defaultSize(); 
    needle->setTransformOriginPoint(n.width()/2,n.height()/2); 
    knob->setTransformOriginPoint(k.width()/2,k.height()/2); 
    if (k!=n) 
     needle->setPos((k.width()-n.width())/2,(k.height()-n.height())/2); 

    degPerPos = 340/(this->maximum() - this->minimum()); 
    middle = (this->maximum() - this->minimum())/2; 
    mysize = k.width(); 
    if (mysize<n.width()) mysize = n.width(); 
    if (mysize<k.height()) mysize = k.height(); 
    if (mysize<n.height()) mysize = n.height(); 
    mysize = sqrt(2)*mysize; 
    view.setDisabled(true); 
    view.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); 
    view.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); 

    scene.addItem(knob); 
    scene.addItem(needle); 
    view.setScene(&scene); 
    view.setParent(this,Qt::FramelessWindowHint); 
} 

qSVGDial::~qSVGDial() 
{ 
    //delete ui; 

} 

void qSVGDial::paintEvent(QPaintEvent *pe) 
{ 
    needle->setRotation((this->sliderPosition() - middle)*degPerPos); 
} 

void qSVGDial::resizeEvent(QResizeEvent *re) 
{ 
    if (this->width()>this->height()) 
    { 
     view.setFixedSize(this->height(),this->height()); 
     view.move((this->width()-this->height())/2,0); 
     knob->setScale(this->height()/mysize); 
     needle->setScale(this->height()/mysize); 
     view.centerOn(knob); 
    } 
    else 
    { 
     view.setFixedSize(this->width(),this->width()); 
     view.move(0,(this->height()-this->width())/2); 
     knob->setScale(this->width()/mysize); 
     needle->setScale(this->width()/mysize); 
     view.centerOn(knob); 
    } 
    QDial::resizeEvent(re); 
} 

L'en-tête parent:

#ifndef PEDAL_H 
#define PEDAL_H 

#include <QtGui/QWidget> 
#include <QString> 
#include <QtSvg/QSvgRenderer> 
#include <QtSvg/QGraphicsSvgItem> 
#include <QGraphicsView> 
#include <QGraphicsScene> 
#include <skin.h> 
#include <qsvgdial.h> 
#include <qsvgbutton.h> 
#include <qsvgled.h> 
#include <qsvgslider.h> 

class Pedal : public QWidget 
{ 
    Q_OBJECT 

public: 
    explicit Pedal(QWidget *parent = 0); 
    explicit Pedal(QString boxFile, QWidget *parent = 0); 
    ~Pedal(); 
    int LoadSkin(skin skinfiles); 
    QWidget* AddControl(QString type, QString param, int x, int y, int w, int h, QString file1, QString file2, QString file3, QString file4); 

private: 
    void resizeEvent(QResizeEvent *re); 
    QRect PedalPosition(); 
    float myheight; 
    float mywidth; 
    float scale; 
    int effectNumber; 
    QGraphicsView view; 
    QGraphicsScene scene; 
    QGraphicsSvgItem *box; 
    QSize p; 
    QWidget* controls[20]; 
    QRect ctrlPos[20]; 
    int numControls; 
}; 

#endif // PEDAL_H 

parent cpp

#include "pedal.h" 
#include "math.h" 

Pedal::Pedal(QWidget *parent) 
    : QWidget(parent) 
{ 
    numControls = 0; 
    box = new QGraphicsSvgItem("stompbox.svg"); 
    view.setStyleSheet("background: transparent; border: none"); 
    p = box->renderer()->defaultSize(); 
    box->setTransformOriginPoint(p.width()/2,p.height()/2); 

    myheight = p.height(); 
    mywidth = p.width(); 
    view.setDisabled(true); 
    view.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); 
    view.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); 

    scene.addItem(box); 
    view.setScene(&scene); 
    view.setParent(this,Qt::FramelessWindowHint); 
} 

Pedal::Pedal(QString boxFile, QWidget *parent) : 
    QWidget(parent) 
{ 
    numControls = 0; 
    box = new QGraphicsSvgItem(boxFile); 
    view.setStyleSheet("background: transparent; border: none"); 
    p = box->renderer()->defaultSize(); 
    box->setTransformOriginPoint(p.width()/2,p.height()/2); 

    myheight = p.height(); 
    mywidth = p.width(); 
    view.setDisabled(true); 
    view.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); 
    view.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); 

    scene.addItem(box); 
    view.setScene(&scene); 
    view.setParent(this,Qt::FramelessWindowHint); 
} 


Pedal::~Pedal() 
{ 

} 

void Pedal::resizeEvent(QResizeEvent *re) 
{ 
    view.setFixedSize(this->width(),this->height()); 
    //view.move((this->width()-this->height())/2,(this->width()-this->height())/2); 
    if (this->width()/mywidth>this->height()/myheight) 
    { 
     scale = this->height()/myheight; 
    } 
    else 
    { 
     scale = this->width()/mywidth; 
    } 
    box->setScale(scale); 
    view.centerOn(box); 
    //QWidget::resizeEvent(re); 
    QRect v = PedalPosition(); 
    QRect cpos; 
    for(int i = 0; i<numControls; i++) 
    { 
     cpos = ctrlPos[i]; 
     controls[i]->setGeometry(v.x()+cpos.x()*scale,v.y()+cpos.y()*scale,cpos.width()*scale,cpos.height()*scale); 
    } 
} 

QWidget* Pedal::AddControl(QString type, QString param, int x, int y, int w, int h, QString file1, QString file2, QString file3, QString file4) 
{ 
    QWidget* control; 
    if (type.toLower() == "dial") 
    { 
     if (!file2.isEmpty()) 
      control = new qSVGDial(file1,file2,this); 
     else 
      control = new qSVGDial(this); 
    } 
    else if (type.toLower() == "button") 
    { 
     if (!file2.isEmpty()) 
      control = new qSVGButton(file1,file2,this); 
     else if (!file1.isEmpty()) 
      control = new qSVGButton(file1,this); 
     else 
      control = new qSVGButton(this); 
    } 
    else if (type.toLower() == "slider") 
    { 
     if (!file2.isEmpty()) 
      control = new qSVGSlider(file1,file2,this); 
     else if (!file1.isEmpty()) 
      control = new qSVGSlider(file1,this); 
     else 
      control = new qSVGSlider(this); 
    } 
    else if (type.toLower() == "led") 
    { 
     if (!file2.isEmpty()) 
      control = new qSVGLED(file1,file2,this); 
     else 
      control = new qSVGLED(this); 
    } 
    control->setToolTip(param); 
    ctrlPos[numControls] = QRect(x,360-y-h,w,h); 
    controls[numControls] = control; 
    numControls++; 
    return control; 
} 

QRect Pedal::PedalPosition() 
{ 
    QRect mypos; 
    mypos.setWidth(mywidth*scale); 
    mypos.setHeight(myheight*scale); 
    mypos.setX((this->width()-mypos.width())/2); 
    mypos.setY((this->height()-mypos.height())/2); 
    return mypos; 
} 

enfin la principale de test

#include <QtGui/QApplication> 
#include "pedal.h" 

#include <string.h> 
int main(int argc, char *argv[]) 
{ 
    QApplication a(argc, argv); 
    Pedal w("skins/default/stompbox.svg",0); 
    w.AddControl("Dial" , "Level", 133, 295, 47, 47, "skins/default/blackKnob.svg", "skins/default/whiteNeedle.svg","",""); 
    w.AddControl("Button", "On", 20, 21, 182, 111, "skins/default/blackButton.svg","","",""); 
    w.AddControl("LED", "On", 106, 328, 11, 11, "skins/default/redLEDOff.svg", "skins/default/redLEDOn.svg","",""); 
    w.AddControl("Dial", "Gain", 44, 295, 47, 47, "skins/default/blackKnob.svg", "skins/default/whiteNeedle.svg","",""); 
    w.AddControl("Dial", "Low", 36, 244, 31, 31, "skins/default/blackKnob.svg", "skins/default/whiteNeedle.svg","",""); 
    w.AddControl("Dial", "Mid", 98, 244, 31, 31, "skins/default/blackKnob.svg", "skins/default/whiteNeedle.svg","",""); 
    w.AddControl("Dial", "High", 160, 244, 31, 31, "skins/default/blackKnob.svg", "skins/default/whiteNeedle.svg","",""); 
    w.show(); 

    return a.exec(); 
} 

espérons que cela aide. Comme vous pouvez le voir, j'ai des couches de QGraphicsViews avec un widget. Je soupçonne maintenant que cela pourrait être la pire façon de le faire, alors je me demande si quelqu'un a plus d'expérience avant d'aller de l'avant dans une mauvaise direction. Aussi après avoir joué un peu plus avec, le problème semble se produire quand j'ai 2 instances du qSVGDial. Si je charge d'autres combinaisons de widgets cela fonctionne bien. Merci encore tout le monde!

+0

Sans voir votre code, nous pouvons » t dire si vous faites quelque chose de mal ou non.Le format SVG est plus coûteux que les formats de type bitmap, donc il y a un coût avec eux quelle que soit la boîte à outils que vous utilisez. Etes-vous sûr que vous avez besoin de SVG pour tous? (Je trouve surprenant que vous voyiez un tel ralentissement.) Quant à "est Qt meilleur", s'il vous plaît ne posez pas ce type de question subjective – Mat

+0

Désolé, je ne voulais pas poser ce genre de question. Je me demandais juste s'il y a une bibliothèque que je ne connais pas conçue pour cela. Et je suppose que je n'ai pas besoin de svgs mais j'aime travailler dans inkscape et l'évolutivité. – user962342

+0

'QDial :: paintEvent' n'est pas appelé depuis le remplacement, n'est-ce pas? – Troubadour

Répondre

6
void qSVGDial::paintEvent(QPaintEvent *pe) 
{ 
    needle->setRotation((this->sliderPosition() - middle)*degPerPos); 
} 

Cela me semble très suspect. Faire quoi que ce soit qui pourrait entraîner un redessin de la méthode paintEvent est dangereux, pourrait conduire à des boucles de mise à jour infinies.

Vous devez connecter le signal sliderMoved du comparateur à un emplacement de votre classe et faire pivoter l'aiguille dans ce logement, puis retirer le gestionnaire paintEvent. Si cela ne déclenche pas une mise à jour, appelez également le update() dans cet emplacement, mais je ne pense pas que cela soit nécessaire.

(Pour vérifier si tel est le problème en premier lieu, essayez d'imprimer quelque chose à la console dans le gestionnaire paintEvent. Si elle imprime comme un fou, c'est votre problème.)

+0

Merci. Vos suggestions ont été très efficaces. C'était en effet une boucle infinie. J'ai laissé la fonction paintEvent là mais sans code à l'intérieur juste pour que le cadran ne soit pas peint derrière mon objet svg. Mais l'idée du signal et de la fente était le ticket. C'est beaucoup plus léger maintenant. Merci encore! – user962342

+0

err .. même sans code, il a semblé faire une boucle alors je viens de sortir la redéfinition paintEvent. – user962342

+0

Il y a probablement quelque chose d'autre qui ne va pas. Inspectez soigneusement vos gestionnaires resizeEvent, faire des choses qui peuvent déclencher un redimensionnement à partir de là peut également avoir de mauvais effets. Je suis un peu inquiet à propos de 'view.setFixedSize' et déplace les appels spécifiquement. Sont-ils vraiment nécessaires? (Mais je n'ai jamais utilisé ces vues, donc je ne peux pas aider beaucoup plus.) – Mat