「Qtライブラリ - Qwt」の版間の差分

ナビゲーションに移動 検索に移動
437行目: 437行目:
<br><br>
<br><br>


== ラバーバンドを描画する ==
== ラバーバンドの描画 ==
プロット上に選択枠のような図形を描画する場合、QwtPlotPickerクラスを使用する。
プロット上に選択枠のような図形を描画する場合、<code>QwtPlotPicker</code>クラスを使用する。<br>
QwtPlotPickerクラスは、ズーム枠の親クラスである。
<code>QwtPlotPicker</code>クラスは、ズーム枠の親クラスである。<br>
 
<br>
以下の例では、QwtPlotクラスを継承した派生クラスを作成して、QwtPlotPickerクラスを使用して設定している。
以下の例では、<code>QwtPlot</code>クラスを継承した派生クラスを作成して、<code>QwtPlotPicker</code>クラスを使用して設定している。<br>
  <syntaxhighlight lang="c++">
  <syntaxhighlight lang="c++">
  MyPlot::MyPlot(QWidget *parent) : QwtPlot(parent)
  MyPlot::MyPlot(QWidget *parent) : QwtPlot(parent)
  {
  {
     // Picker
     // Picker
     m_pPicker = new QwtPlotPicker( canvas() );
     m_pPicker = std::make_unique<QwtPlotPicker>(canvas());
     m_pPicker->setRubberBandPen( QColor( Qt::darkRed ) );
     m_pPicker->setRubberBandPen(QColor(Qt::darkRed));
     m_pPicker->setTrackerMode( QwtPicker::ActiveOnly );
     m_pPicker->setTrackerMode(QwtPicker::ActiveOnly);
  }
  }
  </syntaxhighlight>
  </syntaxhighlight>
<br>
<br>
マウスボタンの設定は、QwtPickerMachineクラスの派生クラスで管理している。
マウスボタンの設定は、<code>QwtPickerMachine</code>クラスの派生クラスで管理している。<br>
以下の例では、ズーム枠のような矩形を描画している。
以下の例では、ズーム枠のような矩形を描画している。<br>
  <syntaxhighlight lang="c++">
  <syntaxhighlight lang="c++">
  m_pPicker->setRubberBand( QwtPicker::RectRubberBand );
  m_pPicker->setRubberBand(QwtPicker::RectRubberBand);
  m_pPicker->setStateMachine( new QwtPickerDragRectMachine );
  m_pPicker->setStateMachine(new QwtPickerDragRectMachine);
  </syntaxhighlight>
  </syntaxhighlight>
<br>
<br>
QwtPickerDragRectMachineクラスは、マウスの左ボタンを押下しながらドラッグすることにより矩形を描画して、
<code>QwtPickerDragRectMachine</code>クラスは、マウスの左ボタンを押下しながらドラッグすることにより矩形を描画して、<br>
左ボタンを離すと描画を終了する設定である。
左ボタンを離すと描画を終了する設定である。<br>
 
<br>
以下の例では、楕円を描画している。
以下の例では、楕円を描画している。<br>
  <syntaxhighlight lang="c++">
  <syntaxhighlight lang="c++">
  m_pPicker->setRubberBand( QwtPicker::EllipseRubberBand );
  m_pPicker->setRubberBand(QwtPicker::EllipseRubberBand);
  m_pPicker->setStateMachine( new QwtPickerDragRectMachine );
  m_pPicker->setStateMachine(new QwtPickerDragRectMachine);
  </syntaxhighlight>
  </syntaxhighlight>
<br>
<br>
以下の例では、ポリゴンを描画している。
以下の例では、ポリゴンを描画している。<br>
  <syntaxhighlight lang="c++">
  <syntaxhighlight lang="c++">
  m_pPicker->setRubberBand( QwtPicker::PolygonRubberBand );
  m_pPicker->setRubberBand(QwtPicker::PolygonRubberBand);
  m_pPicker->setStateMachine( new QwtPickerPolygonMachine );
  m_pPicker->setStateMachine(new QwtPickerPolygonMachine);
  </syntaxhighlight>
  </syntaxhighlight>
<br>
<br>
setStateMachineメソッドは、左ボタンで点追加、右ボタンで終了となっているが、
<code>setStateMachine</code>メソッドは、左ボタンで点を追加、右ボタンで終了する動作である。<br>
左ボタンで最初の1点、右ボタンで2点目以降を追加、左ボタンで終了となっている。
しかし、左ボタンで最初の1点、右ボタンで2点目以降を追加、左ボタンで終了となっている。(2012/4 現在)<br>
 
<br>
qwt_picker_machin.cpp(379行目~、2012年4月時点)
この動作を、左ボタンで点を追加、右ボタンで終了に変更するため、qwt_picker_machin.cppファイルを変更する。<br>
  <syntaxhighlight lang="c++">
  <syntaxhighlight lang="c++">
// qwt_picker_machin.cpp
  //! Transition
  //! Transition
  QList<QwtPickerMachine::Command> QwtPickerPolygonMachine::transition(const QwtEventPattern &eventPattern, const QEvent *event)
  QList<QwtPickerMachine::Command> QwtPickerPolygonMachine::transition(const QwtEventPattern &eventPattern, const QEvent *event)
516行目: 518行目:
  </syntaxhighlight>
  </syntaxhighlight>
<br>
<br>
ラバーバンドで描画した図形を、確定図形としてプロット上に描画する場合、
ラバーバンドで描画した図形を、確定図形としてプロット上に描画する場合、<br>
ラバーバンド描画終了時の図形データを、ラバーバンドクラスから取り出す必要がある。
ラバーバンド描画終了時の図形データを、ラバーバンドクラスから取得する必要がある。<br>
 
<br>
ここでは、ラバーバンド描画終了時のシグナルを受信して図形を取り出す手順を使用する。
ここでは、ラバーバンド描画終了時のシグナルを受信して図形を取り出す手順を使用する。<br>
上の例では、QwtPlot派生クラスにラバーバンドクラスがあるため、
<br>
プロットアイテムをプロットの親ウィンドウ側で管理する場合はシグナルをさらに親ウィンドウへ転送する必要があります。
上記の例では、QwtPlotクラスを継承した派生クラスにラバーバンドクラスがあるため、<br>
コンストラクタで以下のように設定します。
プロットアイテムを、プロットの親ウィンドウ側で管理する場合はシグナルをさらに親ウィンドウへ転送する必要がある。<br>
<br>
QMainWindowクラスのコンストラクタにおいて、以下のようにシグナル・スロットを記述する。<br>
また、QwtPlotクラスを継承した派生クラスを持つ親ウィンドウにて、転送されるシグナルを受信する。<br>
<br>
シグナルの引数は、ラバーバンドの矩形または頂点となっているため、スロットで図形を追加するとよい。<br>
楕円の場合は、矩形選択のスロットが戻るため、選択図形の楕円をスロット側で再作成する必要がある。<br>
  <syntaxhighlight lang="c++">
  <syntaxhighlight lang="c++">
  // 矩形、楕円選択の場合
  MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
QObject::connect(m_pPicker, SIGNAL(selected(const QRectF&)), this, SIGNAL(selected(const QRectF&)));
{
    // ...略
   
   
  // ポリゴン選択の場合
    // 矩形、楕円選択の場合
QObject::connect(m_pPicker, SIGNAL(selected(const QVector<QPointF>&)), this, SIGNAL(selected(const QVector<QPointF>&)));
    QObject::connect(m_pPicker, SIGNAL(selected(const QRectF&)), this, SIGNAL(selected(const QRectF&)));
</syntaxhighlight>
   
<br>
    // 矩形、楕円選択の場合
QwtPlot派生クラスの親ウィンドウで転送されてきたシグナルを捕まえます。
    QObject::connect(m_pPlot, SIGNAL(selected(const QRectF&)), this, SLOT(appendPoly(const QRectF&)));
<syntaxhighlight lang="c++">
// 矩形、楕円選択の場合
    // ポリゴン選択の場合
QObject::connect( m_pPlot, SIGNAL( selected( const QRectF& ) ), this, SLOT( appendPoly( const QRectF& ) ) );
    QObject::connect(m_pPicker, SIGNAL(selected(const QVector<QPointF>&)), this, SIGNAL(selected(const QVector<QPointF>&)));
 
    // ポリゴン選択の場合
    QObject::connect(m_pPlot, SIGNAL(selected(const QVector<QPointF>&)), this, SLOT(appendPoly(const QVector<QPointF>&)));
    // ...略
}
   
   
// ポリゴン選択の場合
QObject::connect( m_pPlot, SIGNAL( selected( const QVector< QPointF >& ) ), this, SLOT( appendPoly( const QVector< QPointF >& ) ) );
</syntaxhighlight>
<br>
シグナルの引数がラバーバンドの矩形または頂点になっているので、スロットで図形を追加すればいいでしょう。
問題は楕円の場合で、楕円選択の場合でも矩形選択のスロットが帰ってくるので、 選択図形の楕円をスロット側で再作成する必要があるようです。
<syntaxhighlight lang="c++">
  // 矩形の場合のスロット
  // 矩形の場合のスロット
  void ParentWnd::appendPoly(const QRectF& rc)
  void MainWindow::appendPoly(const QRectF& rc)
  {
  {
     QVector<QPointF> tempPoly;
     QVector<QPointF> tempPoly;
563行目: 571行目:
     else /* 矩形選択の場合 */
     else /* 矩形選択の場合 */
     {
     {
       tempPoly.push_back( rc.topLeft() );
       tempPoly.push_back(rc.topLeft());
       tempPoly.push_back( rc.bottomLeft() );
       tempPoly.push_back(rc.bottomLeft());
       tempPoly.push_back( rc.bottomRight() );
       tempPoly.push_back(rc.bottomRight());
       tempPoly.push_back( rc.topRight() );
       tempPoly.push_back(rc.topRight());
       tempPoly.push_back( rc.topLeft() );
       tempPoly.push_back(rc.topLeft());
     }
     }
   
   
     // QwtPlotCurveとして図形を追加
     // QwtPlotCurveクラスとして図形を追加
     QwtPlotCurve *pCurve = new QwtPlotCurve();
     std::unique_ptr<QwtPlotCurve> pCurve = std::make_unique<QwtPlotCurve>();
     pCurve->setSamples(tempPoly);
     pCurve->setSamples(tempPoly);
     pCurve->setPen(QPen(QBrush(QColor::fromRgb(255, 0, 0)), 2.0));
     pCurve->setPen(QPen(QBrush(QColor::fromRgb(255, 0, 0)), 2.0));
578行目: 586行目:
   
   
  // ポリゴンの場合のスロット
  // ポリゴンの場合のスロット
  void ParentWnd::appendPoly(const QVector<QPointF> &poly)
  void MainWindow::appendPoly(const QVector<QPointF> &poly)
  {
  {
     // 点列の末尾に始点を追加してポリゴンを閉じる
     // 点列の末尾に始点を追加してポリゴンを閉じる
584行目: 592行目:
     tempPoly.push_back(tempPoly.front());
     tempPoly.push_back(tempPoly.front());
   
   
     // QwtPlotCurveとして図形を追加
     // QwtPlotCurveクラスとして図形を追加
     QwtPlotCurve *pCurve = new QwtPlotCurve();
     std::unique_ptr<QwtPlotCurve> pCurve = std::make_unique<QwtPlotCurve>();
     pCurve->setSamples(tempPoly);
     pCurve->setSamples(tempPoly);
     pCurve->setPen(QPen(QBrush(QColor::fromRgb(255, 0, 0)), 2.0));
     pCurve->setPen(QPen(QBrush(QColor::fromRgb(255, 0, 0)), 2.0));

案内メニュー