hakeの日記

Windows環境でプログラミングの勉強をしています。

C++でQTアプリ(その10) 描画処理

Ruby/Qteの勉強で行ったQPainterを用いた線の描画プログラムを書いてみた。画面下のテキストエリアの関数の定義を書き、Drawボタンを押すと関数の曲線を描きます。
関数の評価の方法がわからない(evalみたいなのはC++にもあるのだろうか)のでslcalcのソースを使わせてもらいました。
描画はQPainter *pを宣言してp->begin()からp->end()の間で描画内容を記述します。今回はX=-319〜319の範囲での定義した関数によるYの値で決まる座標に線を引いています。


drawtest.h
#ifndef DRAWTEST_H
#define DRAWTEST_H

#include <qmainwindow.h>
#include <qwidget.h>
#include <qlineedit.h>
#include <qpushbutton.h>
#include <qstring.h>
#include <qpen.h>
#include <qpainter.h>
#include "calc.h"    // slcalcのソース利用

#define MAXNN    100 // max name number
#define MAXIC    512 // max input    characters
#define MAXRC     64 // max result   characters
#define MAXFC     16 // max format   characters
#define MAXSC    128 // max standard characters
#define MAXIFC 16384 // max input file characters

class DrawTest : public QMainWindow{
	Q_OBJECT
public:
	DrawTest(QWidget *parent = 0, const char *name = 0);
//	~DrawTest();

private:
	QWidget *w;
	QLineEdit *eb;
	QPushButton *pb;

private:
	int func( int x );
	void calculate( QString t );

private slots:
	void slot_draw();
};
#endif
drawtest.cpp
#include "drawtest.h"

int  g_bFormat   = 0;     // claculated result format n:0 f:1 e:2
int  g_bAng      = 1;     // angle base rad:0 deg:1
bool g_bClear    = true;  // clear input text at next key
int  g_bBufCount = 0;     // buffer count
double g_bX      = 0;     // calculated result
bool g_bError    = false; // make error ?
bool g_bCFedited = false; // conf file edited ?

char ws[MAXIFC];
QString g_sFormatN = "%g";
QString g_sFormatF = "%f";
QString g_sFormatE = "%21.15e";
bool    g_sFlagBuffer     = true;

calc calc_;

DrawTest::DrawTest(QWidget *parent, const char *name)
		: QMainWindow(parent, name)
{
	setCaption("Draw Test");

	w = new QWidget( this );       // 描画用ウィジェット
	w->setGeometry(0, 0, 640, 370);
	eb = new QLineEdit( this );
	eb->setGeometry(0, 370, 580, 40);
	eb->clear();
	pb = new QPushButton("Draw", this);
	pb->setGeometry(580, 370, 60, 40);
	connect( pb, SIGNAL(clicked()), this, SLOT(slot_draw()) );
	
}

void DrawTest::slot_draw()
{
	calc_.clear();                 // calc_クリア
	w->erase();                    // 画面クリア
	QString t = eb->text();        // 式を取得
	calculate( t );                // 式設定
	const QPen pen( Qt::blue, 2);  // ペン色、太さ constが必須
	QPainter *p = new QPainter();
	p->begin( w );                 // 描画開始
	p->setPen( pen );
	int x = -320, y;
	y = func( x );                 // y値計算
	p->moveTo(x + 320, 185 - y);   // 初期座標
	for( x = -319; x < 320; x++){
		y = func( x );
		p->lineTo(x + 320, 185 - y);// 一つ前の座標から線を描く
	}
	p->end();                      // 描画終了
}


int DrawTest::func( int x )
{
	QString t;
	t.sprintf("S(%d)", x);
	calculate( t );
	double d = g_bX;
	if(d > 1000) d = 1000;
	if(d < -1000) d = -1000;
	return( (int)d );
}


// slcalcのソースを利用
void DrawTest::calculate( QString t )
{
	char s[MAXIC], tx[MAXRC], f[MAXFC];
	int  i, j;
	
	strcpy(f, "%g");
	if (t.length() >= MAXIC) t = t.left(MAXIC - 1);
	strcpy(s, t);
	calc_.set_ang(g_bAng);

	// calculation
	i = calc_.result(s, &g_bX, tx, f);
	if ((i==1)||(i==2)) {
		calc_.list(ws, MAXIFC);
		calc_.clear();
		for(i=j=0; ws[i]; i++)
			if (ws[i]=='\n') {
				ws[j] = 0;
				calc_.result(ws, &g_bX, tx, f);
				j=0;
			} else ws[j++] = ws[i];
		ws[j] = 0;
		calc_.result(ws, &g_bX, tx, f);
		i = calc_.result(s, &g_bX, tx, f);
	}
	g_bError = (i != 0);
	// set buffer count
	g_bBufCount = 1;
	// text clear at next input
	g_bClear = true;
}