在QChartView上启用水平缩放/滚动(2016年11月Qt-5.7.0)

在QChartView上启用水平缩放/滚动(2016年11月Qt-5.7.0),qt,Qt,我有一个长的QLineSeries,其中包含类似条形图的内容。我可以在QChartView中显示它,如果我设置HorizontalRubberBand,我可以放大它的一部分。默认的QChartView也会在鼠标右键单击时缩小。但是我不知道如何连接水平滚动条,这样当我放大时,我也可以沿着条带左右滚动 下面的代码创建了一个简单的QLineSeries,其中包含两个正弦周期。如果我能正确地进行缩放和滚动,我可以将这个想法扩展到我的实际项目中。有什么帮助吗 #include "mainwindow.h"

我有一个长的
QLineSeries
,其中包含类似条形图的内容。我可以在
QChartView
中显示它,如果我设置
HorizontalRubberBand
,我可以放大它的一部分。默认的
QChartView
也会在鼠标右键单击时缩小。但是我不知道如何连接水平滚动条,这样当我放大时,我也可以沿着条带左右滚动

下面的代码创建了一个简单的
QLineSeries
,其中包含两个正弦周期。如果我能正确地进行缩放和滚动,我可以将这个想法扩展到我的实际项目中。有什么帮助吗

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    QLineSeries *s = new QLineSeries;
    QChart      *c = new QChart;

    for (double theta = 0.0; theta < 4.0 * M_PI; theta += M_PI / 50.0)
        s->append( theta, sin( theta ) );

    c->addSeries( s );
    c->createDefaultAxes( );

    ui->chartview->setChart( c );
    ui->chartview->setRubberBand( QChartView::HorizontalRubberBand );
}

MainWindow::~MainWindow()
{
    delete ui;
}
#包括“mainwindow.h”
#包括“ui_main window.h”
主窗口::主窗口(QWidget*父窗口):
QMainWindow(父级),
用户界面(新用户界面::主窗口)
{
用户界面->设置用户界面(此);
QLineSeries*s=新的QLineSeries;
QChart*c=新QChart;
对于(双θ=0.0;θ<4.0*M_π;θ+=M_π/50.0)
s->append(θ,sin(θ));
c->addSeries(s);
c->createDefaultAxes();
用户界面->图表视图->设置图表(c);
ui->chartview->setRubberBand(QChartView::HorizontalRubberBand);
}
MainWindow::~MainWindow()
{
删除用户界面;
}

我开始使用各种可用的信号,并设法使我的示例程序按预期工作。我不确定这是否是被认可的方法,或者它是否能很好地扩展,但它对我来说是有效的

我不太清楚的一点是,
QChartView
上的滚动条没有滚动正确的内容。它们滚动整个
QChart
、轴和所有轴。要在图表中滚动缩放的数据,需要添加一个单独的滚动条,然后调用
QChart
scroll()
函数以响应
valueChanged
信号。(我没有对此进行测试,但是调用
QAxis
setRange(min,max)
可能会起作用。)

下面是显示两个正弦波周期并允许橡皮筋缩放的代码。缩放后,可以沿波浪前后滚动

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
  : QMainWindow(parent)
  , ui(new Ui::MainWindow)
  , scrolling( false )
{
    ui->setupUi(this);

    QLineSeries *s = new QLineSeries;
    QChart      *c = new QChart;

    for (double theta = 0.0; theta < 4.0 * M_PI; theta += M_PI / 50.0)
        s->append( theta / M_PI, sin( theta ) );

    c->addSeries( s );
    c->createDefaultAxes( );
    c->legend( )->hide( );

    ui->chartView->setChart( c );
    ui->chartView->setRubberBand( QChartView::HorizontalRubberBand );

    // PlotAreaChanged seems like it might be useful, but not for this purpose
    // rangeChanged (on the axis) is the one you need.

    connect( c->axisX( ), SIGNAL(rangeChanged(qreal, qreal)), this, SLOT(on_rangeChanged(qreal,qreal)) );
}

void
MainWindow::on_chartScroll_valueChanged( int v )
{
    if (!scrolling) {
        scrolling = true;
//      cerr << "scroll " << v << endl;
        ui->chartView->chart( )->scroll( v - sv, 0 );
        sv = v;
        scrolling = false;
    }
}

void
MainWindow::on_rangeChanged( qreal min, qreal max )
{
    if (scrolling) return;  // Scrolling causes range changes, but we don't have to do anything.

    QChart          *c = ui->chartView->chart( );
    QAbstractAxis   *x = c->axisX( );
    qreal            avg = (min + max) / 2.0;
    bool             range_fixed = false;

    /*
     * Make sure the new range is sane; fix if not.
     */
    if ((max - min) < 0.1) {    // Avoid overzooming
        min = avg - 0.05;
        max = avg + 0.05;
        range_fixed = true;
    }

    if (min < 0.0) { min = 0.0; range_fixed = true; }

    if (max > 4.0) { max = 4.0; range_fixed = true; }

    if (range_fixed) {
        x->setRange( min, max );    // will re-signal with the fixed range
        return;
    }

    qreal    vis_width = c->plotArea( ).width( );
    qreal    all_width = vis_width * (4.0 - 0.0) / (max - min);

//    cerr << "range " << min << " ... " << max << " in " << vis_width << " pixels" << endl;
//    cerr << "full width requires " << all_width << " pixels" << endl;;

    if (max - min < 4.0) {
//        cerr << "set scroll parameters" << endl;
        scrolling = true;
        ui->chartScroll->setMaximum( all_width - vis_width );
        sv = min / (4.0 - 0.0) * all_width;
        ui->chartScroll->setValue( sv );
        scrolling = false;
    } else {
//        cerr << "disable scroll bar" << endl;
        scrolling = true;
        ui->chartScroll->setMaximum( 0 );
        ui->chartScroll->setValue( sv );
        scrolling = false;
    }
}

MainWindow::~MainWindow()
{
    delete ui;
}
#包括“mainwindow.h”
#包括“ui_main window.h”
主窗口::主窗口(QWidget*父窗口)
:QMainWindow(父级)
,ui(新ui::Main窗口)
,滚动(错误)
{
用户界面->设置用户界面(此);
QLineSeries*s=新的QLineSeries;
QChart*c=新QChart;
对于(双θ=0.0;θ<4.0*M_π;θ+=M_π/50.0)
s->append(θ/mupi,sin(θ));
c->addSeries(s);
c->createDefaultAxes();
c->legend()->hide();
用户界面->图表视图->设置图表(c);
ui->chartView->setRubberBand(QChartView::HorizontalRubberBand);
//PlotAreaChanged看起来可能有用,但不是用于此目的
//rangeChanged(在轴上)是您需要的。
连接(c->axisX(),信号(rangeChanged(qreal,qreal)),这个,插槽(on_rangeChanged(qreal,qreal));
}
无效的
主窗口::在图表上滚动\u值已更改(int v)
{
如果(!滚动){
滚动=真;
//cerr涡旋(v-sv,0);
sv=v;
滚动=假;
}
}
无效的
主窗口::on_范围已更改(qreal最小值、qreal最大值)
{
if(scrolling)return;//滚动导致范围改变,但我们不必做任何事情。
QChart*c=ui->chartView->chart();
QAbstractAxis*x=c->axix();
qreal平均值=(最小值+最大值)/2.0;
bool range_fixed=false;
/*
*确保新范围正常;如果不正常,请修复。
*/
如果((最大-最小)<0.1){//避免过度缩放
最小值=平均值-0.05;
最大值=平均值+0.05;
范围固定=真;
}
如果(min<0.0){min=0.0;范围_fixed=true;}
如果(max>4.0){max=4.0;range_fixed=true;}
如果(范围固定){
x->setRange(最小,最大);//将使用固定范围重新发送信号
返回;
}
qreal vis_width=c->plotArea().width();
qreal all_width=vis_width*(4.0-0.0)/(max-min);
//瑟尔