ページ

2013年11月29日金曜日

qwtテンプレート

Qt GUI アプリケーションでプロジェクトを開く

qwtTest002.pro
#-------------------------------------------------
#
# Project created by QtCreator 2013-11-29T11:23:42
#
#-------------------------------------------------

QT       += core gui
CONFIG   += qwt

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = qwtTest002
TEMPLATE = app


SOURCES += main.cpp\
        plot.cpp

HEADERS  += plot.h

FORMS    += plot.ui


plot.h
#ifndef PLOT_H
#define PLOT_H

#include <QMainWindow>
#include <qwt_plot.h>

namespace Ui {
class Plot;
}

class Plot : public QwtPlot
{
    Q_OBJECT
    
public:
    explicit Plot(QWidget *parent = 0);
    ~Plot();
    
private:
    Ui::Plot *ui;
};

#endif // PLOT_H

main.cpp
#include "plot.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Plot w;
    w.show();
    
    return a.exec();
}


plot.cpp
#include "plot.h"
#include "ui_plot.h"

Plot::Plot(QWidget *parent) :
    QwtPlot(parent)
{
    setTitle( "Plot Demo" );//グラフのタイトル

}

Plot::~Plot()
{
    //ウインドウ終了
}


examples フォルダにある。simpleplot を参考に書いてみる。
plot.cpp
#include "plot.h"
#include "ui_plot.h"
#include <qwt_plot.h>
#include <qwt_plot_curve.h>
#include <qwt_plot_grid.h>
#include <qwt_symbol.h>
#include <qwt_legend.h>

Plot::Plot(QWidget *parent) :
    QwtPlot(parent)
{
    setTitle( "Plot Demo" );//グラフのタイトル
    setCanvasBackground( Qt::white );
    setAxisScale( QwtPlot::yLeft, 0.0, 10.0 );
    insertLegend( new QwtLegend() );
    
    QwtPlotGrid *grid = new QwtPlotGrid();
    grid->attach( this );
    
    QwtPlotCurve *curve = new QwtPlotCurve();
    curve->setTitle( "Some Points" );
    curve->setPen( Qt::blue, 4 ),
            curve->setRenderHint( QwtPlotItem::RenderAntialiased, true );
    
    QwtSymbol *symbol = new QwtSymbol( QwtSymbol::Ellipse,
    QBrush( Qt::yellow ), QPen( Qt::red, 2 ), QSize( 8, 8 ) );
    curve->setSymbol( symbol );
    
    QPolygonF points;
    points << QPointF( 0.0, 4.4 ) << QPointF( 1.0, 3.0 )
           << QPointF( 2.0, 4.5 ) << QPointF( 3.0, 6.8 )
           << QPointF( 4.0, 7.9 ) << QPointF( 5.0, 7.1 );
    curve->setSamples( points );
    
    curve->attach( this );
    
    resize( 600, 400 );
    
}

Plot::~Plot()
{
    //ウインドウ終了
}


2013年11月28日木曜日

データの追記

タイマーを使って擬似的にリアルタイムなグラフの作成に挑戦

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QTimer>

QVector<double> xval;//空のベクタ宣言
QVector<double> yval;//空のベクタ宣言
double xyData = 1;

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

    xval.append(0);
    xval.append(1);

    yval.append(0);
    yval.append(1);

    setTitle( "Plot Demo" );//グラフのタイトル
    setTitle("first_plot");
    setAxisTitle(QwtPlot::xBottom, " time [Second]");
    setAxisScale(QwtPlot::xBottom, 0,100 );
    setAxisTitle(QwtPlot::yLeft, "Value");
    setAxisScale(QwtPlot::yLeft, 0,100 );
    setAutoReplot(true);  // データの追記で必要
    
    curve = new QwtPlotCurve();
    curve->setPen(QPen(Qt::blue));
    curve->setSamples(xval.data(),yval.data(),xval.count());
    curve->attach(this);

    resize( 600, 400 );

    // タイマー
    QTimer *timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(update()));
    timer->start(1000);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::update()
{
    qDebug() << "hello" << xyData;

    xyData += 1;

    xval.append(xyData);
    yval.append(xyData);

    curve->setSamples(xval.data(), yval.data(), xyData+1 );
}



サインカーブでやってみる。
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QTimer>

QVector<double> xval;//空のベクタ宣言
QVector<double> yval;//空のベクタ宣言

int kArraySize = 1000;
//double x[kArraySize] = {}; // x
//double y[kArraySize] = {}; // y
double xData = 0;

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

    setTitle( "Plot Demo" );//グラフのタイトル
    setTitle("first_plot");
    setAxisTitle(QwtPlot::xBottom, " time [Second]");
    setAxisScale(QwtPlot::xBottom, 0,1 );
    setAxisTitle(QwtPlot::yLeft, "Value");
    setAxisScale(QwtPlot::yLeft, -1,1 );
    setAutoReplot(true);  // データの追記で必要

    curve = new QwtPlotCurve();
    curve->setPen(QPen(Qt::blue));
    //curve->setSamples(xval.data(),yval.data(),xval.count());
    curve->attach(this);

    resize( 600, 400 );

    // タイマー
    timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(update()));
    timer->start(5);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::update()
{
    qDebug() << "hello" << xData;

    if( xData < 1000 ){
        double x = xData/(1000-1.0);
        xval.append( x );
        yval.append( sin(2.0*M_PI*x) );

        curve->setSamples(xval.data(), yval.data(), xData);
        xData += 1;
    }else{
        timer->stop();
    }

}


x軸の移動を考えてみる
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QTimer>
#include <qwt_plot_magnifier.h>

QVector<double> xval;//空のベクタ宣言
QVector<double> yval;//空のベクタ宣言

double xData = 0;

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

    setTitle( "Plot Demo" );//グラフのタイトル
    setTitle("first_plot");
    setAxisTitle(QwtPlot::xBottom, " time [Second]");
    setAxisScale(QwtPlot::xBottom, 0,1 );   // x軸
    setAxisTitle(QwtPlot::yLeft, "Value");
    setAxisScale(QwtPlot::yLeft, -1,1 );
    setAutoReplot(true);  // データの追記で必要

    curve = new QwtPlotCurve();
    curve->setPen(QPen(Qt::blue));
    curve->attach(this);

    QwtPlotMagnifier* magnifier = new QwtPlotMagnifier( canvas());// 拡大縮小
    magnifier->setMouseButton(Qt::LeftButton);

    resize( 600, 400 );

    // タイマー
    timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(update()));
    timer->start(30);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::update()
{
        double x = xData/(100-1.0);
        xval.append( x );
        yval.append( sin(2.0*M_PI*x) );

        curve->setSamples(xval.data(), yval.data(), xval.count());

        // x軸を移動
        if( xval.last() > 1){
            setAxisScale(QwtPlot::xBottom,  xval.last()-1 ,xval.last() );
        }

        xData += 1;
}


もっと便利な方法があるかもしれません。


配列のデータでグラフを描く


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

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

    double xval[5]={10,20,30,40,50};
    double yval[5]={1,2.2,3,4,5};

    setTitle( "Plot Demo" );//グラフのタイトル
    setTitle("first_plot");
    setAxisTitle(QwtPlot::xBottom, " System time [h:m:s]");
    setAxisScale(QwtPlot::xBottom, 0,60 );
    setAxisTitle(QwtPlot::yLeft, "Degree");
    setAxisScale(QwtPlot::yLeft, -60,60 );

    curve = new QwtPlotCurve();
    curve->setPen(QPen(Qt::blue));
    curve->setSamples(xval,yval,5);
    curve->attach(this);

    resize( 600, 400 );
}

MainWindow::~MainWindow()
{
    delete ui;
}



グラフの拡大・縮小

#include <qapplication.h>
#include <qwt_plot.h>
#include <qwt_plot_curve.h>
#include <qwt_plot_grid.h>
#include <qwt_symbol.h>
#include <qwt_legend.h>
#include <qwt_plot_magnifier.h>

int main(int argc, char *argv[])
{
    QApplication a( argc, argv );

       QwtPlot plot;
       plot.setTitle( "Plot Demo" );
       plot.setCanvasBackground( Qt::white );
       plot.setAxisScale( QwtPlot::yLeft, 0.0, 10.0 );
       plot.insertLegend( new QwtLegend() );

       QwtPlotGrid *grid = new QwtPlotGrid();
       grid->attach( &plot );

       QwtPlotCurve *curve = new QwtPlotCurve();
       curve->setTitle( "Some Points" );
       curve->setPen( Qt::blue, 4 ),
       curve->setRenderHint( QwtPlotItem::RenderAntialiased, true );

       QwtSymbol *symbol = new QwtSymbol( QwtSymbol::Ellipse,
           QBrush( Qt::yellow ), QPen( Qt::red, 2 ), QSize( 8, 8 ) );
       curve->setSymbol( symbol );

       QPolygonF points;
       points << QPointF( 0.0, 4.4 ) << QPointF( 1.0, 3.0 )
           << QPointF( 2.0, 4.5 ) << QPointF( 3.0, 6.8 )
           << QPointF( 4.0, 7.9 ) << QPointF( 5.0, 7.1 );
       curve->setSamples( points );
       curve->attach( &plot );

       QwtPlotMagnifier* magnifier = new QwtPlotMagnifier( plot.canvas());
       magnifier->setMouseButton(Qt::LeftButton);

       plot.resize( 600, 400 );
       plot.show();

       return a.exec();
}

サンプル画像一覧








タイマーを使てみる

mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <iostream>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT
    
public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    
private:
    Ui::MainWindow *ui;

 public slots:
    void update();


};

#endif // MAINWINDOW_H



mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QtCore/QDebug>
#include <QTimer>

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

    qDebug() << "hello";
    QTimer *timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(update()));
    timer->start(3000);

    qDebug() << "hello2";
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::update()
{
    qDebug() << "update";
}

出力結果
hello
hello2
update
update
update
update

2013年11月27日水曜日

サインカーブ


.pro ファイルに
CONFIG += qwt
を追記

ヘッダー
plot.h
#ifndef PLOT_H
#define PLOT_H

#include <QMainWindow>
#include <qwt_plot.h>
#include <qwt_legend.h>
#include <qwt_plot_grid.h>
#include <qwt_plot_curve.h>

namespace Ui {
class Plot;
}

class Plot : public QwtPlot
{
    Q_OBJECT
    
public:
    explicit Plot(QWidget *parent = 0);
    ~Plot();
    
private:
    Ui::Plot *ui;
    class QwtPlotCurve *curve;
    void plotCurve();
};

#endif // PLOT_H

main.cpp
#include "plot.h"
#include 

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    qDebug("%s", "main.cpp");

    Plot w;
    w.show();
    
    return a.exec();
}


#include "plot.h"
#include "ui_plot.h"


Plot::Plot(QWidget *parent) :
    QwtPlot(parent),
    ui(new Ui::Plot)
{
    //ui->setupUi(this);

    setTitle( "Plot Demo" );//グラフのタイトル
    insertLegend( new QwtLegend() );// 凡例を表示

    // y軸
    setAxisTitle(QwtPlot::yLeft, "y abc");//タイトル
    //setAxisScale( QwtPlot::yLeft, 0.0, 10.0 );//目盛

    // x軸
    setAxisTitle(QwtPlot::xBottom, "x abc");

    // グリッドの設定
    QwtPlotGrid *grid = new QwtPlotGrid();
    grid->enableXMin(true);
    grid->attach( this );


    curve = new QwtPlotCurve();
    curve->setTitle("sine wave");
    curve->setRenderHint(QwtPlotItem::RenderAntialiased);
    curve->setPen(QPen(Qt::red));
    curve->attach(this);

    // 曲線の描画
    plotCurve();

    curve->attach( this );

    resize( 600, 400 );

    //setAxisScale( QwtPlot::xBottom, 0.5, 2.0 );//目盛
}

Plot::~Plot()
{
    delete ui;
}

void Plot::plotCurve()
{
    const int kArraySize = 1000;

    double x[kArraySize] = {}; // x
    double y[kArraySize] = {}; // y

    for (int i = 0; i < kArraySize; ++i) {
        x[i] = i/(kArraySize-1.0);
        y[i] = sin(2.0*M_PI*x[i]);
    }

    curve->setSamples(x, y, kArraySize);
}








2013年11月23日土曜日

Qwtのインストール・メモ

Qt のグラフライブラリ インストールに苦労したのでメモ

使用したもの
windows 8 64bit
Qt 5.1.1 for Windows 32-bit (MinGW 4.8, OpenGL, 666 MB)
qwt-6.1.0.zip

1.Qt をインストールしてシステム環境変数を登録
C:\Qt\Qt5.1.1\5.1.1\mingw48_32\bin
C:\Qt\Qt5.1.1\Tools\mingw48_32\bin

2.qwt-6.1.0.zipを解凍する
コマンドプロンプトを開く。
qwt-6.1.0.zipを解凍したフォルダ(C:\temp\qwt-6.1.0)で次のコマンドを打つ。
qmake qwt.pro
mingw32-make
mingw32-make install

成功すると
C:\Qwt-6.1.0 が出来上がる。

3.システム環境変数を登録
C:\Qwt-6.1.0\lib

ユーザー環境変数を登録する。
変数:QT_PLUGIN_PATH  値:C:\Qwt-6.1.0\plugins;
変数:QMAKEFEATURES  値:C:\Qwt-6.1.0\features;


環境変数を反映させるために再起動させる。
これで完了。

参考にしたサイト:HowTo: Installation of Qt 5.0.1 and Qwt 6.1.0 rc3 (Win7 64bit)


以下苦労した点 
mingw32-make の時エラーが出た。

collect2.exe: error: ld returned 1 exit status
Makefile.Release:320: recipe for target '../lib/qwt.dll' fa
mingw32-make[2]: *** [../lib/qwt.dll] Error 1
mingw32-make[2]: Leaving directory 'D:/qwt-6.1.0/src'
Makefile:38: recipe for target 'release-all' failed
mingw32-make[1]: *** [release-all] Error 2
mingw32-make[1]: Leaving directory 'D:/qwt-6.1.0/src'
makefile:41: recipe for target 'sub-src-make_first-ordered'
mingw32-make: *** [sub-src-make_first-ordered] Error 2

たぶん以前に利用していたMinGW を使っていたからだと思う

備考:
>qmake -set QMAKEFEATURES C:\Qwt-6.0.1\features と解説している所もあった。

> qmake -unset QMAKEFEATURES
> set QMAKEFEATURES=C:\Qwt-6.1.0\features
> qmake  
>



>mingw32-make install の時に
mingw32-make: *** No rule to make target 'inatall'.  Stop. のエラーが出た時は再起動

qwt widget は使えない。プラグインが読み込めていないみたいです。

QCustomPlot というライブラリもあるようです。

2013年11月14日木曜日

サーバープログラム:QTcpSocket

Qt GUI アプリケーション でプロジェクトを作成する。

とりあえず接続の確認とボタンを押してクライアント側に文字を送ってみる。

プロジェクト名:tcpServer

tcpServer.pro
#-------------------------------------------------
#
# Project created by QtCreator 2013-11-11T20:59:55
#
#-------------------------------------------------

QT       += core gui network

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = tcpServer
TEMPLATE = app


SOURCES += main.cpp\
        mainwindow.cpp

HEADERS  += mainwindow.h

FORMS    += mainwindow.ui

mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QTcpServer>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

protected slots:
    void connection();
    void deleteLater();
    void read();

private slots:
    void on_pushButton_clicked();

private:
    Ui::MainWindow *ui;
    QTcpServer *tcpServer;
    QTcpSocket *socket;
};

#endif // MAINWINDOW_H
main.cpp
#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}
mainwoidow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <QTcpSocket>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    qDebug("%s", "処理スタート");
    
    ui->setupUi(this);
    
    //QTcpServer *tcpServer;
    int port = 1024;
    
    tcpServer = new QTcpServer(this);
    tcpServer->listen(QHostAddress::Any, port);
    
    // クライアントと接続した時の処理、SLOT関数を作成する。
    connect(tcpServer, SIGNAL(newConnection()), this, SLOT(connection()));
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::connection()
{
    qDebug("%s", "接続完了");
    
    // まず最初に、接続してきたクライアントのソケットを取得する。
    socket = tcpServer->nextPendingConnection();
    
    // 切断したときの処理としてSLOT関数を設定する。
    connect(socket, SIGNAL(disconnected()), this, SLOT(deleteLater()));
    // クライアントからの送信を受信する
    connect(socket, SIGNAL(readyRead()), this, SLOT(read()));
    
    // 一応、クライアントのアドレスを取得する。
    QString ippaddr = socket->localAddress().toString();
    int ippaddr2 = socket->localPort();
    
    qDebug("%s", qPrintable( ippaddr ));    //ip アドレス表示
    qDebug("%d", ippaddr2 );                //ポート番号表示
    
    //クライアントに文字を送信するためのストリームを定義
    QDataStream out(socket);
    out.setVersion(QDataStream::Qt_4_1);
    
    // データを送信。
    QString string = "Send";
    out << quint16(string.size()) <<  string << quint16(0xFFFF);
    
}

/*
 *概要:クライアントが切断時したの処理
*/
void MainWindow::deleteLater()
{
    qDebug("%s", "deleteLater");
}
/*
 *概要:クライアントからの送信を受信
 */
void MainWindow::read()
{
    qDebug("%s", "on_readyRead");
    
    char buffer[128];
    
    socket->read(buffer, socket->bytesAvailable());
    std::string sString(buffer);
    QString qString(sString.c_str());
    
    ui->textEdit->setText(qString);
    qDebug("%s", qPrintable(qString));
    
    qDebug("%s", "on_readyRead end");
}
/*
 *概要:ボタンがクリックされた時にクライアントに送信する
*/
void MainWindow::on_pushButton_clicked()
{
    qDebug("%s", "ボタンがクリックされた");
    
    QDataStream out2(socket);
    out2.setVersion(QDataStream::Qt_4_1);
    
    QString string = "Buton Send";
    out2 << quint16(string.size()) <<  string << quint16(0xFFFF);
}

UI のデザイン
ボタンにはスロットのclicked()を設定している。

動作確認
クライアントソフトはベクターから『TCPテスター』をダウンロードしてインストールする。
参考:クライアントソフトはいろいろありますが『TCPテスター』がいい感じです。

1.作成したサーバプログラムを実行させる。

2.『TCPテスター』で、動作モードでクライアントを選択して、接続ボタンを押す。
ipアドレスはそれぞれ設定して下さい。ポート番号はプログラムで指定した番号。
接続したときに、サーバから文字sendを送っているのが確認できる。

3.クライアントからサーバに文字を送る
『TCPテスター』のASCII文字列に文字を入力して、送信ボタンを押す。

一応、クライアントから送られた文字を受信できているのが確認できる。

3.サーバのプッシュボタンを押すと、『TCPテスター』で、 Buton Send と送られるのが確認できる。

サーバ側のプログラムで、送信の時の文字の先頭や、受信時の文字の最後に変な空白か何かが在るが、とりあえずは、送受信が確認できた。

備考:
このプログラムを書いたのが、Qtを使って1週間くらいなので、まだわからないことが多い。







2013年11月10日日曜日

『アプリケーション出力』画面に文字を表示する。

#include <QDebug>

qDebug("qDebug, printf style, %i\n", 1);
qDebug() << "qDebug cout style, " << 1;


BloggerでSyntaxHighlighterを使う。

ガジェットからSyntaxHighlighterを使う。

<script type='text/javascript'>
function loadCss(url) {
 var headElem  = document.getElementsByTagName('head')[0]
 var linkElem =document.createElement("link")
 linkElem.rel = "Stylesheet"
 linkElem.type = "text/css"
 linkElem.href = url
 headElem.appendChild(linkElem)
}
loadCss("http://alexgorbatchev.com/pub/sh/current/styles/shCore.css");
loadCss("http://alexgorbatchev.com/pub/sh/current/styles/shThemeDefault.css");
</script>

<script src="http://alexgorbatchev.com/pub/sh/current/scripts/shCore.js" type='text/javascript' ></script>

<script type="text/javascript" src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushXml.js"  ></script>
<script type="text/javascript" src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJScript.js" ></script>
<script type="text/javascript" src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJava.js" ></script>
<script type="text/javascript" src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushScala.js" ></script>
<script type="text/javascript" src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushPlain.js" ></script>

<script language='javascript' type="text/javascript">
<!--
SyntaxHighlighter.config.bloggerMode = true;
SyntaxHighlighter.defaults['toolbar'] = false;
SyntaxHighlighter.all();
// -->
</script>