Hi!
How to do scaling of my graphics by Qt means?
Thanks for helps!
Printable View
Hi!
How to do scaling of my graphics by Qt means?
Thanks for helps!
What graphics? Be more specific, please!
Assuming that you are showing an image, use QImage::scaled, if your graphics are in the form of a QPixmap, use QPixmap::scaled...
If that is not what you would like to know:
give us more information! Your question is not really precise and I am wondering what you are trying to do. Hard to give advice that way.
If you would give us a few lines of your code and say what is not working the way you want it to, you would save us time and get more helpful answers.
HTH
I want to draw grid. I have minimal, maximal means, step. Should I specify QMatrix? How to do it? What should I do it?
My previous code was:
Code:
{ if(!rect.isValid()) return; QRect boundString; /// Отрисовка осей вдоль оси X for(int i=0; i<=settings.numXTicks; ++i) { int x = rect.left() + (i * (rect.width() - 1) / settings.numXTicks); double label = (settings.minX >= 0) ? settings.minX + (i * settings.spanX() / settings.numXTicks) : settings.maxX - (i * settings.spanX() / settings.numXTicks); painter -> setPen(Qt::black); painter -> drawLine(x, rect.top(), x, rect.bottom()); if(i != settings.numXTicks) { int flags = Qt::AlignHCenter | Qt::AlignTop; boundString = painter -> boundingRect(boundString, flags, s_label); painter -> drawText(x - (boundString.width() + 5), rect.bottom() - (boundString.height() + 5), boundString.width(), boundString.height(), flags, s_label); } } if(mode != NULL) { int flags = Qt::AlignCenter; boundString = painter -> boundingRect(boundString, flags, mode -> x_param.param_name); painter -> drawText(rect.right() - boundString.width(), rect.bottom() - 2 * boundString.height(), mode -> x_param.param_name); } /// Отрисовка осей вдоль оси Y for(int j=0; j<=settings.numYTicks; ++j) { int y = rect.bottom() - (j * (rect.height() - 1) / settings.numYTicks); double label = settings.minY + (j * settings.spanY() / settings.numYTicks); painter -> setPen(Qt::black); painter -> drawLine(rect.left(), y, rect.right(), y); if(j != settings.numYTicks) { int flags = Qt::AlignRight | Qt::AlignTop; boundString = painter -> boundingRect(boundString, flags, s_label); painter -> drawText(rect.left() + 7, y - boundString.height(), boundString.width(), boundString.height(), flags, s_label); } } if(mode != NULL) { int flags = Qt::AlignCenter; boundString = painter -> boundingRect(boundString, flags, mode -> y_param.param_name); painter -> drawText(rect.left() + 7, rect.top() + boundString.height(), mode -> y_param.param_name); } painter -> drawRect(rect.adjusted(0, 0, -1, -1)); }
Help me, please! I don't know how to draw the grid that is scale with graphic! Don't ignore my posts, please!
Well...
first:
* obviously I can't compile that example (not self contained)
* I figure from your comment that this is working code, probable Qt3 based, right?
* (I don't understand russian comments in kyrillian fonts, btw ;-)
You should tell us what you want to do, what is your problem.
From looking at your code, I would say that the same is possible in Qt4.
(Why) do you want to change it?
Is something not working/compiling?
You only have to specify a matrix if you want to apply an affine transformation on the draw stuff. Scaling would be an example.
So: if your problem is (only) that the grid is drawn in the wrong size, then yes: apply a scaling matrix to the painter.
(Perhaps it would be in order to save() it first, and restore() it later.)
HTH
Well.....
My problem is seen so: I don't know how it is possible in Qt4! What do I can with means of step, min and max values? What element in Qt account for it? I want to draw grid and graphic by Qt and not manually!
My previous code worked but it didn't scale right! I solved write this code by management Qt!
Sorry with my english! I say with difficulties and lexicographer! So my native language is russian!
As far as I know, there is no built-in stuff for drawing grids.
You have to do it manually, i.e. code it yourself.
But then, your code seems to be for drawing a grid...
isn't it working?
But.... Why I haven't Qt means?
In my manual code I don't know how to do right scaling!
My graphic stretched but it didn't near/move away! I don't know right algorithm scaling!
P.S. May I turn to Qt built-in stuff?
Code:
//If your grid is at the wrong position, do painter->save(); QPoint offset=...; painter->translate(offset), // if the grid is the wrong size: painter->scale(zoomX, zoomY); // draw here painter->restore();
Details, see QPainter::save, QPainter::scale, QPainter::translate, QPainter::restore.
Well! Thank you!
Possible, it is more concrete if I give my code, isn't it? This code with small correct.
Header
Code:
{ Q_OBJECT private: PlotSettings settings; QVector<QPointF> curve_vec; QPoint origin; bool rubberBandIsShown; MODEGRAPHICS* mode; QPainter painter; private: // MORE code =) protected: public: ~QModeGraphics(); void setPlotSettings(const PlotSettings& sts) { settings = sts; update(); } void initCurve(); void zoomIn(int delta); void zoomOut(int delta); };
Source
Code:
/// Draw all { painter.begin(this); painter.setWindow(modesDisplay -> rect()); painter.setPen(Qt::black); initCurve(); drawGrid(&painter); drawCurves(&painter); drawModeBorder(&painter); painter.end(); } { int numDegrees = events -> delta() / 8; int numTicks = numDegrees / 15; if(numTicks > 0) zoomIn(numTicks); else zoomOut(numTicks); update(); } { QRect r; switch(events -> button()) { case Qt::LeftButton: ///< если нажата левая кнопка мыши origin = events -> pos(); rubberBandIsShown = true; setCursor(Qt::CrossCursor); rubber -> setGeometry(r); rubber -> show(); break; case Qt::RightButton: ///< если нажата правая кнопка мыши break; default: break; } } { if(rubberBandIsShown) { rubber -> setWindowOpacity(0.0); } update(); } /// Возвращение прежнего вида курсору и изменение масштаба { if(events -> button() == Qt::LeftButton && rubberBandIsShown) { rubberBandIsShown = false; unsetCursor(); if(rect.width() < 10 || rect.height() < 10) return; PlotSettings prevSettings = settings; PlotSettings settings_temp; double sp_x = prevSettings.spanX(); double sp_y = prevSettings.spanY(); double dx = prevSettings.spanX() / (width() - 2 * MARGIN); double dy = prevSettings.spanY() / (height() - 2 * MARGIN); settings_temp.minX = prevSettings.minX + dx * rect.left(); settings_temp.maxX = prevSettings.minX + dx * rect.right(); settings_temp.minY = prevSettings.maxY - dy * rect.bottom(); settings_temp.maxY = prevSettings.maxY - dy * rect.top(); settings_temp.adjust(); settings = settings_temp; rubber -> hide(); update(); } } /// Grid drawing { if(!rect.isValid()) return; QRect boundString; /// Отрисовка осей вдоль оси X for(int i=0; i<=settings.numXTicks; ++i) { int x = rect.left() + (i * (rect.width() - 1) / settings.numXTicks); double label = (settings.minX >= 0) ? settings.minX + (i * settings.spanX() / settings.numXTicks) : settings.maxX - (i * settings.spanX() / settings.numXTicks); painter -> setPen(Qt::black); painter -> drawLine(x, rect.top(), x, rect.bottom()); if(i != settings.numXTicks) { int flags = Qt::AlignHCenter | Qt::AlignTop; boundString = painter -> boundingRect(boundString, flags, s_label); painter -> drawText(x - (boundString.width() + 5), rect.bottom() - (boundString.height() + 5), boundString.width(), boundString.height(), flags, s_label); } } if(mode != NULL) { int flags = Qt::AlignCenter; boundString = painter -> boundingRect(boundString, flags, mode -> x_param.param_name); painter -> drawText(rect.right() - boundString.width(), rect.bottom() - 2 * boundString.height(), mode -> x_param.param_name); } /// Отрисовка осей вдоль оси Y for(int j=0; j<=settings.numYTicks; ++j) { int y = rect.bottom() - (j * (rect.height() - 1) / settings.numYTicks); double label = settings.minY + (j * settings.spanY() / settings.numYTicks); painter -> setPen(Qt::black); painter -> drawLine(rect.left(), y, rect.right(), y); if(j != settings.numYTicks) { int flags = Qt::AlignRight | Qt::AlignTop; boundString = painter -> boundingRect(boundString, flags, s_label); painter -> drawText(rect.left() + 7, y - boundString.height(), boundString.width(), boundString.height(), flags, s_label); } } if(mode != NULL) { int flags = Qt::AlignCenter; boundString = painter -> boundingRect(boundString, flags, mode -> y_param.param_name); painter -> drawText(rect.left() + 7, rect.top() + boundString.height(), mode -> y_param.param_name); } painter -> drawRect(rect.adjusted(0, 0, -1, -1)); } /// Mode border drawing { if(!rect.isValid()) return; if(mode == NULL) return; for(mode_border_iter iter=mode -> mode_border.begin(); iter!=mode -> mode_border.end(); ++iter) { brush.setColor(color); int j = 0; for(pntIter jter=iter -> border_pnt.begin(); jter!=iter -> border_pnt.end(); ++jter, ++j) { double dx = (settings.minX < 0) ? jter -> x() - settings.minX : jter -> x() - settings.maxX; double dy = jter -> y() - settings.minY; double x = (settings.minX < 0) ? rect.right() - (dx * (rect.width() - 1) / settings.spanX()) : rect.right() + (dx * (rect.width() - 1) / settings.spanX()); double y = rect.bottom() - (dy * (rect.height() - 1) / settings.spanY()); } painter -> setPen(pen); painter -> setBrush(brush); painter -> drawPolygon(polyline); } } /// Инициализация кривых нужными значениями void QModeGraphics::initCurve() { if(mode == NULL) return; for(QVector<PARAMVALUE>::iterator iter=mode -> x_param.log_param.begin(); iter!=mode -> x_param.log_param.end(); ++iter) { double dx = (settings.minX < 0) ? iter -> value - settings.minX : iter -> value - settings.maxX; double x = (settings.minX < 0) ? rect.right() - (dx * (rect.width() - 1) / settings.spanX()) : rect.right() + (dx * (rect.width() - 1) / settings.spanX()); curve_vec.push_back(pnt); } for(int i=0; i<mode -> y_param.log_param.size(); ++i) { QVector<PARAMVALUE>::iterator iter = &mode -> y_param.log_param[i]; double dy = iter -> value - settings.minY; double y = rect.bottom() - (dy * (rect.height() - 1) / settings.spanY()); curve_vec[i].setY(y); } } /// Draw curve { if(mode == NULL) return; if(mode -> x_param.param_record == NULL || mode -> y_param.param_record == NULL) return; painter -> setPen(Qt::blue); for(int i=0; i<curve_vec.size(); ++i) polyline[i] = curve_vec[i]; painter -> drawPolyline(polyline); } /// scaling + void QModeGraphics::zoomIn(int delta) { if(delta > 0) settings.scroll(-1 * delta, -1 * delta, delta, delta); else settings.scroll(delta, delta, -1 * delta, -1 * delta); update(); } /// scaling - void QModeGraphics::zoomOut(int delta) { if(delta > 0) settings.scroll(delta, delta, -1 * delta, -1 * delta); else settings.scroll(-1 * delta, -1 * delta, delta, delta); update(); }
Where and when I should be to use your help code? What I should be to do that the graphic not stretch?
This code describing class PlotSettings!
Code:
class PlotSettings { public: double minX; double maxX; int numXTicks; double minY; double maxY; int numYTicks; protected: static void adjustAxis(double& min, double& max, int& numTicks); public: PlotSettings(); void scroll(int dx, int dy); void scroll(double mn_dx, double mn_dy, double mx_dx, double mx_dy); void adjust(); double spanX() const { return fabs(fabs(maxX) - fabs(minX)); } double spanY() const { return fabs(fabs(maxY) - fabs(minY)); } }
Code:
PlotSettings::PlotSettings(): minX(-999.0), minY(-999.0), maxX(-999.0), maxY(-999.0) { numXTicks = 8; numYTicks = 8; } void PlotSettings::scroll(int dx, int dy) { double stepX = spanX() / numXTicks; minX += dx * stepX; maxX += dx * stepX; double stepY = spanY() / numYTicks; minY += dy * stepY; maxY += dy * stepY; } void PlotSettings::scroll(double mn_dx, double mn_dy, double mx_dx, double mx_dy) { double stepX = spanX() / numXTicks; minX += mn_dx * stepX; maxX += mx_dx * stepX; double stepY = spanY() / numYTicks; minY += mn_dy * stepY; maxY += mx_dy * stepY; } void PlotSettings::adjust() { adjustAxis(minX, maxX, numXTicks); adjustAxis(minY, maxY, numYTicks); } void PlotSettings::adjustAxis(double& min, double& max, int& numTicks) { const int MinTicks = 5; double grossStep = (max - min) / MinTicks; double step = pow(10.0, floor(log10(grossStep))); if(5 * step < grossStep) step *= 5; else if(2 * step < grossStep) step *= 2; numTicks = int(ceil(max / step) - floor(min / step)); if(numTicks < MinTicks) numTicks = MinTicks; min = floor(min / step) * step; max = ceil(max / step) * step; }
Help, please!
Patience, please. I got other things to do, too...
Well, where to put it depends on what is wrong.
Basically, you can wrap the drawing of your stuff with the code.
(If only the grid is too small, wrap the drawGrid stuff, if all is too small, put it into paintEvent().
so, try
Code:
{ painter.begin(this); painter.setWindow(modesDisplay -> rect()); painter.setPen(Qt::black); initCurve(); painter.save(); QPoint offset=...; painter.translate(offset), drawGrid(&painter); drawCurves(&painter); drawModeBorder(&painter); painter.end(); painter.restore(); }
If your code is working, and you are just not happy about the graphics you produce, how about giving us a screenshot and describing what looks you would like to achieve.
PS: The code is helpful; I'd just like to point out that we still can not try it out. We lack the .ui-file
PPS: The use of fonts like "Tahoma" is dangerous. Your target platform might not have it. So the looks of the program might be diffrent.
This problem is resolved! :))))) URAAAAA
Code:
class PlotSettings { public: double minX; double maxX; int numXTicks; double minY; double maxY; int numYTicks; protected: static void adjustAxis(double& min, double& max, int& numTicks); public: PlotSettings(); void scroll(int dx, int dy); void scale(double delta_x, double delta_y); void adjust(); double spanX() const { return fabs(maxX - minX); } double spanY() const { return fabs(maxY - minY); } }; /// Увеличение/уменьшение значения minX, maxX, minY, maxY на интервал между 2-мя отметками void PlotSettings::scale(double delta_x, double delta_y) { if((minX == maxX || minY == maxY) && delta_x < 0 && delta_y < 0) return; double stepX = spanX() / numXTicks; minX -= delta_x * stepX; maxX += delta_x * stepX; double stepY = spanY() / numYTicks; minY -= delta_y * stepY; maxY += delta_y * stepY; } /// Класс для отображения параметров по времени или по расстоянию { Q_OBJECT private: QMap<int, QVector<QPointF>> curveMap; ///< список всех изображаемых кривых ParamPlotSettings settings; ///< настройка для определения масштаба QPoint origin; ///< начальные координаты выделяемой области bool rubberBandIsShown; ///< флажок попадания курсора в "резиновую ленту" QPen myPen; ///< карандаш для рисования линий определенной жирности и цвета enum { MARGIN = 10 }; QPainter painter; ///< рисовальщик QVector<QPointF> data; ///< вектор загружаемой кривой private: protected: public: ~GraphicDisplay(); void zoom(double delta) { settings.scale(delta, delta); settings.adjust(); update(); } void setPlotSettings(const ParamPlotSettings& sts) { settings = sts; settings.adjust(); update(); } /// Изменение масштаба при движении колесика { int numDegrees = events -> delta() / 8; double numTicks = numDegrees / 15.0; zoom(numTicks); update(); } /// Нажатие на кнопки клавиатуры { switch(events -> key()) { case Qt::Key_Plus: zoom(1.0); break; case Qt::Key_Minus: zoom(-1.0); break; case Qt::Key_Left: settings.scroll(-1, 0); update(); break; case Qt::Key_Right: settings.scroll(1, 0); update(); break; case Qt::Key_Up: settings.scroll(0, 1); update(); break; case Qt::Key_Down: settings.scroll(0, -1); update(); break; default: } } /// Отрисовка сетки { if(!rect.isValid()) return; QRect boundString; int _max = max(settings.numXTicks, settings.numYTicks); for(int i=0, j=0, k=0; i<=_max; ++i, ++j, ++k) { if(j <= settings.numXTicks) ///< отрисовка по оси X { int x = rect.left() + (j * (rect.width() - 1) / settings.numXTicks); double label = settings.minX + (j * settings.spanX() / settings.numXTicks); painter -> setPen(Qt::black); painter -> drawLine(x, rect.top(), x, rect.bottom()); if(j != settings.numXTicks) { int flags = Qt::AlignHCenter | Qt::AlignTop; boundString = painter -> boundingRect(boundString, flags, s_label); painter -> drawText(x - (boundString.width() + 5), rect.bottom() - (boundString.height() + 5), boundString.width(), boundString.height(), flags, s_label); } } if(k <= settings.numYTicks) ///< отрисовка по оси Y { int y = rect.bottom() - (k * (rect.height() - 1) / settings.numYTicks); double label = settings.minY + (k * settings.spanY() / settings.numYTicks); painter -> setPen(Qt::black); painter -> drawLine(rect.left(), y, rect.right(), y); if(k != settings.numYTicks) { int flags = Qt::AlignRight | Qt::AlignTop; boundString = painter -> boundingRect(boundString, flags, s_label); painter -> drawText(rect.left() + 5, y - boundString.height(), boundString.width(), boundString.height(), flags, s_label); } } } painter -> drawRect(rect.adjusted(0, 0, -1, -1)); } /// Отрисовка легенды { myPen.setWidth(1); painter -> setPen(Qt::black); int flags = Qt::AlignCenter; boundString = painter -> boundingRect(boundString, flags, dimension); rect.bottom() - 2 * boundString.height()), dimension); ++k; } /// Инициализация координат { double dx, dy; dx = sx - settings.minX; dy = sy - settings.minY; double x = rect.left() + (dx * (rect.width() - 1) / settings.spanX());; double y = rect.bottom() - (dy * (rect.height() - 1) / settings.spanY()); } /// Отрисовка графика { if(!rect.isValid()) return; painter -> setClipRect(rect.adjusted(1, 1, -1, -1)); QMapIterator<int, QVector<QPointF>> iter(curveMap); int k = 1; while(iter.hasNext()) { iter.next(); int id = iter.key(); TP_PARAM ty = fact_prm[id].type; if(settings.win_type != ty) continue; const QVector<QPointF> &data = iter.value(); for(int j=0; j<data.count(); ++j) { double x = data[j].x(); double y = data[j].y(); polyline[j] = initXY(x, y); } myPen.setColor(fact_prm[id].param_color); painter -> setPen(myPen); painter -> drawPolyline(polyline); int width = myPen.width(); drawLegend(painter, rect, k, id); painter -> setPen(oldPen); } }
This is describing the code which have resolved problem! :)