簡體   English   中英

在QT中自定義看svg GUI小部件,性能非常糟糕

[英]Custom look svg GUI widgets in QT, very bad performance

所以我正在嘗試為吉他效果程序制作一個gui。 一個目標是允許其他人設計svg“皮膚”來定制外觀。 我創建了繼承每個小部件(即qdial)的小部件,並在初始化程序中將皮膚指定的svg文件加載到qGraphicsSvgItem中。 這被放入場景和視圖中,我重載了調整大小並重新適當地重新繪制。 這有效。

當我將幾個這些自定義svg小部件(5個撥號,一個按鈕和一個led)加載到父小部件中時,cpu rails和我的程序凍結。 我完全是錯誤的做法嗎? 我應該使用QT嗎? 這似乎比嘗試用樣式表做所有事情更容易(特別是我無法弄清楚如何改變表盤外觀)。 將小部件保留為qGraphicsSvgItems並將它們全部放入父窗口小部件的場景和視圖中會改進嗎?

這是一個實時信號處理程序,所以我不想在GUI中燒掉很多cpu。 我試圖對它進行一些研究但是找不到svg的很多東西。 我也沒有在qtCreator中看到任何性能檢查器,或者我試圖看看瓶頸是什么。 無論如何,在我花更多時間嘗試以錯誤的方式做事之前,我真的很感激你能提供的任何建議。

非常感謝! _ssj71

ps以下是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);
}

父標題:

#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

父母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;
}

最后測試主要

#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();
}

希望這會有所幫助。 正如您所看到的,我有一些QGraphicsViews,每個都有一個小部件。 我懷疑現在這可能是最糟糕的做法,所以我想知道是否有人在我朝着糟糕的方向前進之前有更多的經驗。 在玩了更多它之后,當我有2個qSVGDial實例時,似乎會出現問題。 如果我加載其他小部件組合,它可以正常工作。 再次感謝大家!

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

這對我來說非常可疑。 做任何可能導致從paintEvent方法重繪的事情是危險的,可能會導致無限的更新循環。

您應該將撥號盤的sliderMoved信號連接到類中的插槽並旋轉該插槽中的指針,並完全刪除paintEvent處理程序。 如果這不會觸發更新,請在該插槽中調用update() ,但我不認為這是必要的。

(要首先檢查這是否是問題,請嘗試在paintEvent處理程序內的控制台上打印一些東西。如果它像瘋了一樣打印,那就是你的問題。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM