Так что я пытаюсь сделать графический интерфейс для программы эффектов гитары. Одна из целей - позволить другим разрабатывать svg "скины" для настройки внешнего вида. Я создал виджеты, которые унаследовали каждый виджет (т.е. qdial), и в инициализаторе загрузил файл svg, указанный скином, в qGraphicsSvgItem. Это помещено в сцену и вид, и я перегрузил размеры и перекрасил соответственно. Это работает.
Когда я загружаю несколько из этих пользовательских виджетов svg (5 циферблатов, кнопку и светодиод) в родительский виджет, рельсы процессора и моя программа зависают. Я иду по этому пути совершенно неправильно? Должен ли я даже использовать QT? Это казалось проще, чем пытаться делать все с помощью таблицы стилей (особенно я не мог понять, как изменить внешний вид циферблата). Будет ли это лучше, если оставить виджеты как qGraphicsSvgItems и поместить их все в сцену и вид родительского виджета?
Это программа обработки сигналов в реальном времени, поэтому я не хочу перегружать процессор в графическом интерфейсе. Я пытался сделать некоторые исследования, но не смог найти много для SVG. Я также не вижу никакой проверки производительности в qtCreator, или я бы попытался увидеть, что является узким местом. В любом случае, я очень ценю любой совет, который вы могли бы дать, прежде чем уделять больше времени попыткам сделать что-то неправильно.
Большое спасибо!
_ssj71
p.s.
Вот часть кода (надеюсь, достаточно)
виджет 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
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;
}
наконец-то основной тест
#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();
}
надеюсь, это поможет. Как вы можете видеть, у меня есть слои QGraphicsView, каждый из которых имеет один виджет. Я подозреваю, что сейчас это может быть худший способ сделать это, поэтому мне интересно, есть ли у кого-то больше опыта, прежде чем я буду двигаться в плохом направлении. Кроме того, после того, как я поигрался с ним еще раз, проблема возникает, когда у меня есть 2 экземпляра qSVGDial. Если я загружаю другие комбинации виджетов, все работает нормально. Еще раз спасибо всем!