2016-11-27 15 views
0

QLineSeriesにはストリップチャートのようなものが含まれています。 QChartViewに表示することができます。HorizontalRubberBandを設定すると、その部分を拡大表示できます。デフォルトのQChartViewは、マウスの右クリックでズームアウトします。しかし、私はズームインすると、ストリップに沿って左右にスクロールできるように、水平スクロールバーをフックする方法がわかりません。QChartViewでの水平スケーリング/スクロールの有効化(Nov-2016 Qt-5.7.0)

以下のコードは、2つの正弦波を含む単純な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; 
} 

答えて

1

私はさまざまな信号を再生することができました。私はサンプルプログラムを希望どおりに動作させることができました。私はこれが承認された方法であるかどうか、あるいはそれがうまく調整されているかどうかはわかりませんが、それは私にとってはうまくいきます。

特に私にはっきりしないことの1つは、QChartViewのスクロールバーが正しいものをスクロールしないということです。彼らはQChart、軸とすべてをスクロールします。チャート内のズームしたデータをスクロールするには、別のスクロールバーを追加してから、valueChanged信号に応答してQChartscroll()関数を呼び出す必要があります。 (私はこれをテストしませんでしたが、代わりにのsetRange(<i>min</i>, <i>max</i>)と呼ぶことがあります)

ここでは、2つの正弦波サイクルを表示し、ラバーバンドズームを可能にするコードです。ズームすると、波に沿って前後にスクロールすることができます。

#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; 
} 

(ハードコードされた4.0のための謝罪[から]。正しいことを行うには、スクロールしているデータの完全な範囲を見ている。)

関連する問題