Qwt+VS2010+QT实现条形图和Marker线的交互。

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_37830546/article/details/82798947

前言

在学习中经常到CSND来搜索相关的知识学习,一直也有着想写自己第一篇关于自己编程的博客。今天留着上班时间偷空写了属于自己的博客。关于这段实习时间花费了不少时间学习的Qwt库调用,在VS2010下实现了这一程序。
配置为vs2010+Qt4.0+Qwt4.8.6

BarChart实现

QwtPlot中包含有很多组件,是用来绘制二维图像的widget。在它的画板上可以无限制的显示绘画组件。绘画组件可以是曲线(QwtPlotCurve)、标记(QwtPlotMarker)、网格(QwtPlotGrid)、或者其它从QwtPlotItem继承的组件。

BarChart实现在qwt库中的例子example里也有事例可以参考实现,相对只要读懂其中widget机制,在窗口绘制组件时就相对比较简单,基本就是调用库里的函数,或者稍微重载库了的函数进行调用。
完整代码可以点击这里下载或者联系本人
运行图片:
运行结果图

在这里插入图片描述

首先我们实现可以从文本读取数据在窗口的canvas上形成条形图:

using namespace std;
class DistroChartItem;
class QMouseEvent;
class QwtPlotMarker;


class Data{
public:
	string m_name;
	double m_d;
	Data(string name,double d){m_name=name;m_d=d;}
};
class BarChart: public QwtPlot
{
    Q_OBJECT
signals:
	double setMaxYValue(double m_max);
	double setMinYValue(double m_min);
public:
    BarChart(QWidget *parent = NULL);
	vector<Data>m_data;
	virtual bool eventFilter( QObject *, QEvent * );
public slots:
    void setOrientation(int value);
	void setColor(int num);
    void exportChart();
	// mouseEvent
	void mouseMoveEvent ( QMouseEvent * event );
	void mousePressEvent ( QMouseEvent * event );
	void mouseReleaseEvent ( QMouseEvent * event );
	
	void marker(QwtPlotMarker *mX,double yvalue);

	void setCanvasColor( const QColor &c );
	void setMarkerColor(const QColor &d);
	void maxChanged(double m_max);
	void minChanged(double m_min);
public:
	double setMaxMarker(){return MaxMarker->value().y();}
	double setMinMarker(){return MinMarker->value().y();}
    
private:
    DistroChartItem *d_barChartItem;
    QStringList d_distros;
	QwtPlotCanvas *canvas;

	QwtPlotMarker *MaxMarker;         //marker
	QwtPlotMarker *MinMarker;
	double yvalue;
	bool m_pressedMax;
	bool m_pressedMin;
	ColorBar *d_colorBar;
};

在barchart的构造函数中去创建画布和读取数据转变成条形图显示在画布上

BarChart::BarChart(QWidget *parent):
    QwtPlot(parent)
{
	m_pressedMax = false;
	m_pressedMin = false;
	fstream ifile;
	ifile.open("D:/2013/qwt/qwt6.1/test5/text.txt");
	 while(1){
		 string name;
		 double d;
		 ifile>>name>>d;
		 Data temp(name,d);
		 if(ifile.eof()!=0)break;
		 m_data.push_back(temp);
	 }
    setAutoFillBackground(true);
    setPalette(QColor("Linen"));

    setTitle("排行榜");

    //canvas Attributes
    canvas = new QwtPlotCanvas();
    canvas->setLineWidth(2);
    canvas->setFrameStyle(QFrame::Box | QFrame::Sunken);
    canvas->setBorderRadius(10);
    QPalette canvasPalette(QColor(255,0,0,0.1));
    canvas->setPalette(canvasPalette);
    setCanvas(canvas);
	
    d_barChartItem = new DistroChartItem();

    QVector<double>samples;
	for (int i = 0; i < m_data.size(); i++)
    {
        d_distros += QString::fromStdString(m_data[i].m_name);
        samples += m_data[i].m_d;
        d_barChartItem->addDistro(QString::fromStdString(m_data[i].m_name));
    }
    d_barChartItem->setSamples(samples);
    d_barChartItem->attach(this);
    insertLegend(new QwtLegend());
    setOrientation(0);
    setAutoReplot(false);

	MaxMarker=new QwtPlotMarker;                     //创建marker线和初始化
	MaxMarker->setLabel(QString::fromLatin1("max"));
	MaxMarker->setLinePen(QPen(Qt::black, 3, Qt::SolidLine));
	marker(MaxMarker,500);
	
	MinMarker=new QwtPlotMarker;
	MinMarker->setLabel(QString::fromLatin1("min"));
	MinMarker->setLinePen(QPen(Qt::black, 3, Qt::SolidLine));
	marker(MinMarker,300);


	QwtScaleWidget *scaleWidget = axisWidget( QwtPlot::yLeft);     //彩色条
	scaleWidget->setMargin( 10 ); 
	d_colorBar=new ColorBar(Qt::Vertical,scaleWidget);
	d_colorBar->setRange( Qt::white, Qt::darkBlue );
	d_colorBar->setFocusPolicy( Qt::TabFocus );

	scaleWidget->installEventFilter( this );        // we need the resize events, to lay out the color bar
}

还是调用qwt其值库中的QwtPlotmarker去绘制参考线,并重载鼠标事件可以让参考线在y轴上平移,并在doublespinbox上显示。

void BarChart::marker(QwtPlotMarker *mX,double yvalue){
		
	mX->setLabelOrientation(Qt::Horizontal);
	mX->setLineStyle(QwtPlotMarker::HLine);
	mX->setYValue(yvalue);
	mX->attach(this);
	
}

void BarChart::mousePressEvent ( QMouseEvent * event )         //鼠标点击移动事件
{
    QPoint point=this->canvas->mapFromGlobal(QCursor::pos());
	double d_max=transform(QwtPlot::yLeft,MaxMarker->value().y());
	double pairMax=qAbs(point.y()-d_max);

	double d_min=transform(QwtPlot::yLeft,MinMarker->value().y());
	double pairMin=qAbs(point.y()-d_min);
	if(pairMax<pairMin&&pairMax<=5){
		m_pressedMax = true;
	}
	else if(pairMin<pairMax&&pairMin<=2){
		m_pressedMin=true;
	}
	
}

void BarChart::mouseMoveEvent ( QMouseEvent * event )
{
	QwtInterval m_scale=this->axisScaleDiv(QwtPlot::yLeft).interval();
	double ymin=m_scale.minValue();
	double ymax=m_scale.maxValue();
	double moveY;
	if(m_pressedMax==true&&(event->buttons() & Qt::LeftButton)){
		//QPoint pos=event->pos();
		QPoint point=this->canvas->mapFromGlobal(QCursor::pos());
		moveY=invTransform(QwtPlot::yLeft,point.y());
		//double moveY = invTransform(MaxMarker->yAxis(), pos.y());
		if(moveY>MinMarker->value().y()&&moveY<ymax){
			marker(MaxMarker,moveY);
			replot();
			emit setMaxYValue(moveY);
		}
		
	}
	else if(m_pressedMin==true&&(event->buttons() & Qt::LeftButton)){
		QPoint point=this->canvas->mapFromGlobal(QCursor::pos());
		moveY=invTransform(QwtPlot::yLeft,point.y());		
		if(moveY<MaxMarker->value().y()&&moveY>ymin){
			marker(MinMarker,moveY);
			replot();
			emit setMinYValue(moveY);
		}
		
	}
	
}

void BarChart::mouseReleaseEvent ( QMouseEvent * event )
{
	if (event->button() == Qt::LeftButton && (m_pressedMax||m_pressedMin)) {
        
         m_pressedMax = false;
		 m_pressedMin = false;
     }

}

画布和marker的心信号槽,可以转变窗口上的彩色条是对于着哪一个的,以便可以调节颜色。

void BarChart::setColor(int num){              //画布和marker线的信号槽连接
	if(num==0){
		disconnect(d_colorBar,0,0,0);
		connect( d_colorBar, SIGNAL( selected( const QColor & ) ),
			SLOT( setCanvasColor( const QColor & ) ) );
		
	}
	else {
		disconnect(d_colorBar,0,0,0);
		
		connect( d_colorBar, SIGNAL( selected( const QColor & ) ),
			SLOT( setMarkerColor( const QColor & ) ) );
	}

}

void BarChart::maxChanged(double m_max){
	if(m_max>MinMarker->value().y()){
		marker(MaxMarker,m_max);
		replot();
	}	
}

void BarChart::minChanged(double m_min){
	if(m_min<MaxMarker->value().y()){
		marker(MinMarker,m_min);
		replot();
	}

}

main文件就在mainwindow是中设置一些组件菜单

#include "test5.h"
#include <QtGui/QApplication>
#include<qmainwindow.h>
#include<qtoolbar.h>
#include<qcombobox.h>
#include<qtoolbutton.h>
#include<qtextcodec.h>
#include<qwt_plot_curve.h>
#include<qwt_symbol.h>
#include<qsplitter.h>
#include<QSpinBox>
class MainWindow: public QMainWindow
{
public:
    MainWindow(QWidget *parent = NULL);

private:
    BarChart *d_chart;

};

MainWindow::MainWindow(QWidget *parent):
    QMainWindow(parent)
{
    d_chart = new BarChart(this);
    setCentralWidget(d_chart);
    QToolBar *toolBar = new QToolBar(this);

    QComboBox *orientationBox = new QComboBox(toolBar);      //窗体的菜单栏的小组件
    orientationBox->addItem("Vertical");
    orientationBox->addItem("Horizontal");
    orientationBox->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);

	QComboBox *m_color=new QComboBox(toolBar);
	m_color->addItem("canvas_color");
	m_color->addItem("marker_color");
	m_color->setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed);

    QToolButton *btnExport = new QToolButton(toolBar);        //文件一键输出
    btnExport->setText("Export");
    btnExport->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
    connect(btnExport, SIGNAL(clicked()), d_chart, SLOT(exportChart()));

    toolBar->addWidget(orientationBox);
	toolBar->addWidget(m_color);
    toolBar->addWidget(btnExport);
	
    addToolBar(toolBar);

    d_chart->setOrientation(orientationBox->currentIndex());
    connect(orientationBox, SIGNAL(currentIndexChanged(int)), d_chart, SLOT(setOrientation(int)));

	d_chart->setColor(m_color->currentIndex());
	connect(m_color,SIGNAL(currentIndexChanged(int)),d_chart,SLOT(setColor(int)));
	
	QDoubleSpinBox *MaxSpinbox=new QDoubleSpinBox;
	QwtInterval m_scale=d_chart->axisScaleDiv(QwtPlot::yLeft).interval();
	MaxSpinbox->setRange(m_scale.minValue(),m_scale.maxValue());
	MaxSpinbox->setValue(d_chart->setMaxMarker());
	MaxSpinbox->setPrefix("max:");
	toolBar->addWidget(MaxSpinbox);
	connect(d_chart,SIGNAL(setMaxYValue(double)),MaxSpinbox,SLOT(setValue(double)));
	connect(MaxSpinbox,SIGNAL(valueChanged(double)),d_chart,SLOT(maxChanged(double)));

	QDoubleSpinBox *MinSpinbox=new QDoubleSpinBox;
	MinSpinbox->setRange(m_scale.minValue(),m_scale.maxValue());
	MinSpinbox->setValue(d_chart->setMinMarker());
	MinSpinbox->setPrefix("min:");
	toolBar->addWidget(MinSpinbox);
	connect(d_chart,SIGNAL(setMinYValue(double)),MinSpinbox,SLOT(setValue(double)));
	connect(MinSpinbox,SIGNAL(valueChanged(double)),d_chart,SLOT(minChanged(double)));
}

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
	QTextCodec::setCodecForCStrings(QTextCodec::codecForLocale());
	QTextCodec::setCodecForTr(QTextCodec::codecForName("utf-8"));

    MainWindow mainWindow;
    mainWindow.resize(600, 500);
    mainWindow.show();

    return a.exec();
} 

渣渣的程序员,真是一如IT深似海,从此秃顶便可期。来京实习的一个月,果真当个程序员也是不容易,写的第一篇博客,也是想记录记录自己的一些小收获吧,希望自己能够经常更新写下去,忘记一些东西时也可以回来看看。有什么不足也希望大家可以多多指出,写得比较粗糙。

看了一下一去二三里博客

展开阅读全文

没有更多推荐了,返回首页