Russian Qt Forum

Qt => 2D и 3D графика => Тема начата: Sergey от Июль 28, 2010, 11:26



Название: Рисования линии на графике
Отправлено: Sergey от Июль 28, 2010, 11:26
 Здравствуйте !

Появилась проблемка ( может она детская , но всё таки) требуется нарисовать на графике линию ....почему-то у меня получается что начало линия прорисовывается ....а потом график ....подскажите пожалуйста как исправить это ))) Линия должна быть горизонтальной ...и я должен иметь возможность перемещать её по оси Х и по оси Y.

Заранее благодарен !


Название: Re: Рисования линии на графике
Отправлено: daimon от Июль 28, 2010, 11:33
Рисуйте линию поверх графика (после отрисовки графика)- в самом пиксмепе. Если вы рисуете график на пиксмепе, а paintEvent потом рисуете этот пиксмеп, то можно и там после отрисовки графика с "потрохами" нарисовать линию


Название: Re: Рисования линии на графике
Отправлено: Sergey от Июль 28, 2010, 12:04
простите за глупый вопрос , но пиксмеп это что !? ) я не использовал пиксмеп .
 Был бы оченб благодарен за какой-то примерчик )


Название: Re: Рисования линии на графике
Отправлено: daimon от Июль 28, 2010, 16:16
простите за глупый вопрос , но пиксмеп это что !? ) я не использовал пиксмеп .
 Был бы оченб благодарен за какой-то примерчик )
QPixmap - это класс карты для рисования.
Когда Вы создаетё QPainter (this)- this- указатель на окно, где рисовать, а Вам надо указатель на QPixmap.
Код
C++ (Qt)
#include <QtGui>
#include <cmath>
 
#include "plotter.h"
 
 
Plotter::Plotter(QWidget *parent)
   : QWidget(parent)
{
 
   setAutoFillBackground(true);
 
 
rubberBand = new QRubberBand(QRubberBand::Rectangle, this);
 
rubberBand_is_shown=0;
 
 
setMinimumSize(4*Margin, 3*Margin);
 
 
connect(&opt_graph,SIGNAL(modified(bool)),this,SLOT(refreshPixmap()));
 
origin.setX(0);
origin.setY(0);
 
 
 
}
 
 
void Plotter::set_plot_settings(Settings2DGraph &opt_graph_)
{
opt_graph=opt_graph_;
 
   refreshPixmap();
 
 
}
 
 
 
QSize Plotter::minimumSizeHint() const
{
   return QSize(4 * Margin, 3 * Margin);
}
 
QSize Plotter::sizeHint() const
{
   return QSize(12 * Margin, 8 * Margin);
}
 
void Plotter::paintEvent(QPaintEvent * /* event */)
{
   QStylePainter painter(this);
 
painter.drawPixmap(0, 0,pixmap);// mg);
 
}
 
void Plotter::resizeEvent(QResizeEvent * /* event */)
{
 
opt_graph.width_widget = this->size().width();
opt_graph.height_widget = this->size().height();
 
rect.setRect(Margin, Margin,
opt_graph.width_widget - 2 * Margin, opt_graph.height_widget - 2*Margin);
 
   refreshPixmap();
}
 
 
void Plotter::refreshPixmap()
{
   pixmap = QPixmap(size());
 
 
   QPainter painter(&pixmap);
   painter.initFrom(this);
 
 
{drawGrid(&painter);
painter.setRenderHint(QPainter::Antialiasing,true);
 
 
drawCurves(&painter);
drawCaptions(&painter);}
 
 
 
   update();
}
void Plotter::drawCaptions(QPainter *painter)
{
if(rect.height()<50)
return;
 
 
//верхняя  нормально
if( opt_graph.caption_top!=""&&(QFontMetricsF(opt_graph.font_caption_left).width(opt_graph.caption_left) < rect.height() || QFontMetricsF(opt_graph.font_caption_top).width(opt_graph.caption_top) < rect.width() )&&
(QFontMetricsF(opt_graph.font_caption_right).width(opt_graph.caption_right) < rect.height() || QFontMetricsF(opt_graph.font_caption_top).width(opt_graph.caption_top) < rect.width()) &&
 
QFontMetricsF(opt_graph.font_caption_top).width(opt_graph.caption_top) +10 < opt_graph.width_widget)
{
 
painter->setClipping (false );
painter->setPen(opt_graph.pen_caption_top);
 
painter->setFont(opt_graph.font_caption_top);
 
painter->drawText(rect.left()+rect.width()/2-QFontMetricsF(opt_graph.font_caption_top).width(opt_graph.caption_top)/2,
rect.top()-10-QFontMetricsF(opt_graph.font_tick_labels).ascent()/2,        
QString(opt_graph.caption_top)
);
 
 
}
 
 
//нижняя надпись норма
 
if( opt_graph.caption_bottom!=""&&(QFontMetricsF(opt_graph.font_caption_left).width(opt_graph.caption_left) < rect.width() || QFontMetricsF(opt_graph.font_caption_bottom).width(opt_graph.caption_bottom) < rect.width())  &&
 
(QFontMetricsF(opt_graph.font_caption_right).width(opt_graph.caption_right) < rect.height() || QFontMetricsF(opt_graph.font_caption_top).width(opt_graph.caption_top) < rect.width()) &&
 
QFontMetricsF(opt_graph.font_caption_bottom).width(opt_graph.caption_bottom) +10 < rect.width())
{
painter->setClipping (false );
 
painter->setPen(opt_graph.pen_caption_bottom);
painter->setFont(opt_graph.font_caption_bottom);
 
painter->drawText(rect.left()+rect.width()/2-QFontMetricsF(opt_graph.font_caption_bottom).width(opt_graph.caption_bottom)/2,
rect.bottom() + 3+opt_graph.major_tick_length + QFontMetricsF(opt_graph.font_tick_labels).ascent()+3+ QFontMetricsF(opt_graph.font_caption_bottom).ascent()
,
QString(opt_graph.caption_bottom));
}
 
//левая надпись норм
 
if( opt_graph.caption_left!=""&&(QFontMetricsF(opt_graph.font_caption_top).width(opt_graph.caption_top) < rect.width() || QFontMetricsF(opt_graph.font_caption_left).width(opt_graph.caption_left) < rect.height()) &&
 
(QFontMetricsF(opt_graph.font_caption_bottom).width(opt_graph.caption_bottom) < rect.width() || QFontMetricsF(opt_graph.font_caption_left).width(opt_graph.caption_left) < rect.height()) &&
 
QFontMetricsF(opt_graph.font_caption_left).width(opt_graph.caption_left) +10 < rect.height()
 
&& rect.left()-QFontMetricsF(opt_graph.font_tick_labels).width(QString::number(opt_graph.maxY_graph_all,opt_graph.type_label,opt_graph.precision_label))-5-opt_graph.major_tick_length-10-QFontMetrics(opt_graph.font_caption_left).height() >=0)
{
 
painter->rotate(-90.0);
painter->translate(-opt_graph.height_widget,0);
 
painter->setClipping (false );
 
painter->setPen(opt_graph.pen_caption_left);
painter->setFont(opt_graph.font_caption_left);
painter->drawText(opt_graph.height_widget-rect.bottom()+rect.height()/2-QFontMetricsF(opt_graph.font_caption_left).width(opt_graph.caption_left)/2, rect.left()-QFontMetricsF(opt_graph.font_tick_labels).width(QString::number(opt_graph.maxY_graph_all,opt_graph.type_label,opt_graph.precision_label))-5-opt_graph.major_tick_length-10,        
QString(opt_graph.caption_left));
 
painter->rotate(90.0);
painter->translate(0,-opt_graph.height_widget);
}
 
//правая надпись норм
 
if(opt_graph.caption_right!=""&& (QFontMetricsF(opt_graph.font_caption_top).width(opt_graph.caption_top) < rect.width() || QFontMetricsF(opt_graph.font_caption_right).width(opt_graph.caption_right) < rect.height()) &&
 
(QFontMetricsF(opt_graph.font_caption_bottom).width(opt_graph.caption_bottom) < rect.width() || QFontMetricsF(opt_graph.font_caption_right).width(opt_graph.caption_right) < rect.height()) &&
 
QFontMetricsF(opt_graph.font_caption_right).width(opt_graph.caption_right) +10 < rect.height())
{
painter->rotate(+90.0);
painter->translate(0,-opt_graph.width_widget);
 
painter->setClipping (false );
 
painter->setPen(opt_graph.pen_caption_right);
painter->setFont(opt_graph.font_caption_right);
painter->drawText(rect.top()+rect.height()/2-QFontMetricsF(opt_graph.font_caption_right).width(opt_graph.caption_right)/2, opt_graph.width_widget-rect.right()-5-10-QFontMetricsF(opt_graph.font_caption_right).descent(),        
QString(opt_graph.caption_right));
 
painter->rotate(-90.0);
painter->translate(-opt_graph.width_widget,0);
}
 
}
void Plotter::drawGrid(QPainter *painter)
{
painter->fillRect(0,0,opt_graph.width_widget,opt_graph.height_widget,Qt::color0);
 
   if (rect.height()<50)
       return;
 
 
 
painter->setFont(opt_graph.font_tick_labels);
 
QFontMetrics fm(opt_graph.font_tick_labels);
 
bool ok_label_x=(fm.width(QString::number(opt_graph.maxX_graph_all,opt_graph.type_label,opt_graph.precision_label))<(double(rect.width())/double((opt_graph.maxX_graph_all-opt_graph.minX_graph_all)/opt_graph.stepX)));
 
bool ok_label_y=(opt_graph.font_tick_labels.pointSize()+opt_graph.font_tick_labels.pointSize()/2<(double(rect.height())/double((opt_graph.maxY_graph_all-opt_graph.minY_graph_all)/opt_graph.stepY)))&& (rect.left()- fm.width(QString::number(opt_graph.maxY_graph_all,opt_graph.type_label,opt_graph.precision_label))-opt_graph.major_tick_length - 5)>0;
 
 
 
//для оси Х грид-линии подписи
for (int i = 0; i <= ceil((opt_graph.maxX_graph_all-opt_graph.minX_graph_all)/opt_graph.stepX); ++i)
{
       int x = rect.left() + (i * (rect.width() - 1)
                                / ((opt_graph.maxX_graph_all-opt_graph.minX_graph_all)/opt_graph.stepX));
       double label = opt_graph.minX_graph_all + (i * opt_graph.stepX);
 
if(x>rect.right()||x<rect.left()) break;
 
if(opt_graph.grid_on)
{
painter->setPen(opt_graph.grid_line);
painter->drawLine(x, rect.top(), x, rect.bottom());
}
 
painter->setPen(opt_graph.pen_aces);
painter->drawLine(x, rect.bottom()-opt_graph.major_tick_length, x, rect.bottom() + opt_graph.major_tick_length);
 
if(ok_label_x)
{
 
painter->setPen(opt_graph.pen_font_tick_labels);
painter->drawText(x-fm.width(QString::number(label,opt_graph.type_label,opt_graph.precision_label))/2, rect.bottom()+opt_graph.major_tick_length+3, fm.width(QString::number(label,opt_graph.type_label,opt_graph.precision_label)), fm.height(),
                         Qt::AlignHCenter | Qt::AlignTop,
 QString::number(label,opt_graph.type_label,opt_graph.precision_label));
}
   }
 
//для оси У грид-линии подписи
for (int j = 0; j <= ceil((opt_graph.maxY_graph_all-opt_graph.minY_graph_all)/opt_graph.stepY); ++j)
{
int y = rect.bottom() - (j * (rect.height() - 1)
                                  / ((opt_graph.maxY_graph_all-opt_graph.minY_graph_all)/opt_graph.stepY));
 
       double label = opt_graph.minY_graph_all + (j * opt_graph.stepY);;
 
if(y<rect.top()) break;
 
if(opt_graph.grid_on)
{
painter->setPen(opt_graph.grid_line);
painter->drawLine(rect.left(), y, rect.right(), y);
}
 
painter->setPen(opt_graph.pen_aces);
painter->drawLine(rect.left() - opt_graph.major_tick_length, y, rect.left() + opt_graph.major_tick_length, y);
 
 
if(ok_label_y)
{
painter->setPen(opt_graph.pen_font_tick_labels);
painter->drawText(rect.left()- fm.width(QString::number(label,opt_graph.type_label,opt_graph.precision_label))-opt_graph.major_tick_length - 5, y - fm.height()/2, fm.width(QString::number(label,opt_graph.type_label,opt_graph.precision_label)), fm.height(),
 Qt::AlignRight | Qt::AlignVCenter,
 QString::number(label,opt_graph.type_label,opt_graph.precision_label));}
}
 
painter->setPen(opt_graph.pen_aces);
painter->drawLine(QPoint(rect.left(),rect.bottom()),QPoint(rect.right(),rect.bottom()));
painter->drawLine(QPoint(rect.left(),rect.bottom()),QPoint(rect.left(),rect.top()));
}
 
void Plotter::drawCurves(QPainter *painter)
{
if (rect.height()<50)
       return;
 
painter->setClipRect(rect);
 
for(int j=0;j<  opt_graph.curves.size();j++)
{
if(opt_graph.curves[j].show_graph_one)
for(int i=0; i<opt_graph.curves[j].table.size();i++)
{
 
opt_graph.curves[j].table[i].x_widget = x_widget(opt_graph.curves[j].table[i].x_tabl);
           opt_graph.curves[j].table[i].y_widget = y_widget(opt_graph.curves[j].table[i].y_tabl);
 
if(i>0)
{
painter->setPen(opt_graph.curves[j].graph_line);
painter->drawLine(opt_graph.curves[j].table[i-1].x_widget ,opt_graph.curves[j].table[i-1].y_widget,
opt_graph.curves[j].table[i].x_widget,opt_graph.curves[j].table[i].y_widget);
}
painter->setPen(opt_graph.curves[j].graph_point);
painter->drawPoint(opt_graph.curves[j].table[i].x_widget,opt_graph.curves[j].table[i].y_widget);
}
 
   }
}
double Plotter::y_widget(double y_tabl_)
{
 
 
double dy = y_tabl_ - opt_graph.minY_graph_all;
 
return rect.bottom() - (dy * (rect.height() - 1)
                                          / (opt_graph.maxY_graph_all - opt_graph.minY_graph_all));
}
 
double Plotter::x_widget(double x_tabl_)
{
 
 
double dx = x_tabl_ - opt_graph.minX_graph_all;
   return  rect.left() + (dx * (rect.width() - 1)
/ (opt_graph.maxX_graph_all - opt_graph.minX_graph_all));
 
}
 
double Plotter::x_tabl(int x_widget_)
{
return ((((x_widget_ - rect.left() )* (opt_graph.maxX_graph_all - opt_graph.minX_graph_all)) )/ (rect.width() - 1)) + opt_graph.minX_graph_all;
}
 
double Plotter::y_tabl(int y_widget_)
{
return ((((rect.bottom()-y_widget_ )* (opt_graph.maxY_graph_all - opt_graph.minY_graph_all)) )/ (rect.height() - 1)) + opt_graph.minY_graph_all;
}
 
void Plotter::mousePressEvent(QMouseEvent *event)
{
 
if(event->button()==Qt::LeftButton)
{
if (rect.contains(event->pos()))
{
origin = event->pos();
rubberBand->setGeometry(QRect(origin, QSize()));
rubberBand_is_shown=1;
}
}
else if(event->button()==Qt::RightButton)
{
opt_graph.rescale(1);
}
}
void Plotter::mouseMoveEvent(QMouseEvent *event)
{
if(rubberBand_is_shown==1)
{
rubberBand->setGeometry(QRect(origin, event->pos()).normalized());
rubberBand->show();
}
}
 
void Plotter::mouseReleaseEvent(QMouseEvent *event)
{
   rubberBand->hide();
 
bool changed=false;
 
if (rubberBand->geometry().width() < 4 || rubberBand->geometry().height() < 4)
           return;
 
if(rubberBand_is_shown==1)
{
double minX_graph_all_widget=std::min(rubberBand->geometry().left(),rubberBand->geometry().right());
if(minX_graph_all_widget<rect.left())
minX_graph_all_widget = rect.left();
double minX_graph_all_old=x_tabl(minX_graph_all_widget);
 
double maxX_graph_all_widget=std::max(rubberBand->geometry().left(),rubberBand->geometry().right());
if(maxX_graph_all_widget > rect.right())
maxX_graph_all_widget = rect.right();
double maxX_graph_all_old=x_tabl(maxX_graph_all_widget);
 
double stepX=0;
opt_graph.calculate_norm_Min_Max_Step(minX_graph_all_old,maxX_graph_all_old,stepX);
 
if( QString::number(fabs(maxX_graph_all_old-minX_graph_all_old),'f',4).toDouble()>0.001)
{
opt_graph.minX_graph_all=minX_graph_all_old;
opt_graph.maxX_graph_all=maxX_graph_all_old;
opt_graph.calculate_norm_Min_Max_Step(opt_graph.minX_graph_all,opt_graph.maxX_graph_all,opt_graph.stepX);
changed=1;
}
else changed=0;
 
 
  double minY_graph_all_widget=std::max(rubberBand->geometry().top(),rubberBand->geometry().bottom());
  if(minY_graph_all_widget > rect.bottom())
minY_graph_all_widget = rect.bottom();
double minY_graph_all_old=y_tabl(minY_graph_all_widget);
 
double maxY_graph_all_widget=std::min(rubberBand->geometry().top(),rubberBand->geometry().bottom());
if(maxY_graph_all_widget<rect.top())
maxY_graph_all_widget = rect.top();
double maxY_graph_all_old=y_tabl(maxY_graph_all_widget);
 
double stepY=0;
opt_graph.calculate_norm_Min_Max_Step(minY_graph_all_old,maxY_graph_all_old,stepY);
 
 
if( QString::number(fabs(maxY_graph_all_old-minY_graph_all_old),'f',4).toDouble()>0.001)
  {
 
opt_graph.minY_graph_all=minY_graph_all_old;
opt_graph.maxY_graph_all=maxY_graph_all_old;
 
opt_graph.stepY=stepY;
 
changed=1;
}
else changed=0;
 
if(changed) refreshPixmap();
}
 rubberBand_is_shown=0;
 
}
 
void Plotter::keyPressEvent(QKeyEvent *event)
{
switch (event->key()) {
 
 
   case Qt::Key_Left:
opt_graph.move_left_right_coordinates_x(1,1);
       break;
   case Qt::Key_Right:
opt_graph.move_left_right_coordinates_x(0,1);
       break;
   case Qt::Key_Down:
        opt_graph.move_top_bottom_coordinates_y(0,1);
       break;
   case Qt::Key_Up:
       opt_graph.move_top_bottom_coordinates_y(1,1);
       break;
 
case Qt::Key_Minus:
if(event->modifiers()&Qt::ShiftModifier)
opt_graph.zoom_x(0,1);
else if(event->modifiers()&Qt::ControlModifier)
opt_graph.zoom_y(0,1);
else opt_graph.zoom_x_y(0,1);
       break;
 
case Qt::Key_Plus:
if(event->modifiers()&Qt::ShiftModifier)
opt_graph.zoom_x(1,1);
else if(event->modifiers()&Qt::ControlModifier)
opt_graph.zoom_y(1,1);
else opt_graph.zoom_x_y(1,1);
       break;
 
 
   default:
       QWidget::keyPressEvent(event);
   }
}
 
 


Название: Re: Рисования линии на графике
Отправлено: Sergey от Июль 28, 2010, 17:29
спасибо большое )
уже разобрался ....сделал немного по-другому .... взял просто кривую и сделал из нею прямую линию ....впринципе так вроде бы легче ....но ваш код понял спасибо ещё раз )

Появилась ещё одна проблемка даже две ! Первая заключается , в том что как в сетку добавить вертикальных линий , то есть сделать шаг сетки другой )

Заранее благодарен )