crossframe » Qt http://crossframe.iiv.jp Windows Dev. Site Tue, 07 Nov 2023 06:31:52 +0000 ja hourly 1 https://wordpress.org/?v=3.8.41 jQueryPlot from Excel ../../../20131207651/ ../../../20131207651/#comments Sat, 07 Dec 2013 14:35:10 +0000 http://xfra.me/?p=651 データビジュアライゼーション。最近とてもブームでもあり私自身も大変興味深い領域です。Excelデータをビジュアライゼーションするとき、どんな形が面白そうかと考えてみたところ、WebでJavaScriptライブラリという結論になりました。Webで表示させるためには、VSTOを使ってWindowsForm上のWebViewにhtmlファイルを読み込ませる方法にしました。もともと今大人気のD3.jsを使いたかったのですが、WebViewがIE7相当のため(Webサーバログで確認)動作しませんでした。対応しないメソッドがあったり、SVGを使うということが原因と思われます。(ちなみにQtのQWebViewでは表示できました。)しかしながら個人的にこのD3.jsを初めて知ったときは、jQueryが登場したときと同じくらい衝撃を受けました。ちょっとはまっています。
そこでD3.jsのかわりにIE7にも対応しているjQueryPlot(http://www.jqplot.com/)を使うことにしました。

前置きが長くなりましたが、ExcelシートにあるデータをWindowFormのボタンを押すとWebViewのグラフが更新されるデモをつくってみました。

jqplot1

jqplotdata1

データを変更(赤字部分)してボタン押下

jqplot2

jqplotdata2

環境 : VisualStudio 2010, Excel 2010 / Windows 7
ThisWorkbook.cs

using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml.Linq;
using Microsoft.Office.Tools.Excel;
using Microsoft.VisualStudio.Tools.Applications.Runtime;
using Excel = Microsoft.Office.Interop.Excel;
using Office = Microsoft.Office.Core;

namespace ExcelWorkbook_Web
{
    public partial class ThisWorkbook
    {
        private void ThisWorkbook_Startup(object sender, System.EventArgs e)
        {
            Form1 fm = new Form1();
            fm.Show();
        }
        public String getData()
        {
            String str = "[";

            for (int i = 1; i <= 7; i++)
            {
                str += "[";

                var o1 = Globals.Sheet1.Cells[i, 2].Value;
                var o2 = Globals.Sheet1.Cells[i, 3].Value;
                var o3 = Globals.Sheet1.Cells[i, 4].Value;

                str += o1.ToString() + "," + o2.ToString() + "," + o3.ToString();
                var o4 = Globals.Sheet1.Cells[i, 1].Value;
                str += ",'" + o4.ToString() + "'";
                str += "]";
                if (i != 7)
                {
                    str += ",";
                }
            }
            str += "]";
            return str;
        }

        private void ThisWorkbook_Shutdown(object sender, System.EventArgs e)
        {
        }

        #region VSTO デザイナーで生成されたコード
        private void InternalStartup()
        {
            this.Startup += new System.EventHandler(ThisWorkbook_Startup);
            this.Shutdown += new System.EventHandler(ThisWorkbook_Shutdown);
        }
        #endregion
    }
}

Form1.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace ExcelWorkbook_Web
{
    [System.Runtime.InteropServices.ComVisibleAttribute(true)]
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            webBrowser1.ObjectForScripting = this;
            webBrowser1.Navigate(new Uri("file:///C:/work/test.html"));

        }

        private void button1_Click(object sender, EventArgs e)
        {
            String str = Globals.ThisWorkbook.getData();
            object[] args = {str};
            webBrowser1.Document.InvokeScript("plot", args);
        }
    }
}

test.html

<html>
<head>
<!--[if lt IE 9]><script language="javascript" type="text/javascript" src="excanvas.js"></script><![endif]-->
<script type="text/javascript" src="jquery.min.js"></script>
<script type="text/javascript" src="jquery.jqplot.min.js"></script>
<script type="text/javascript" src="jqplot.bubbleRenderer.min.js"></script>
<link rel="stylesheet" type="text/css" href="jquery.jqplot.min.css" />
<script>
function plot(arg)
{
    var arr = eval(arg);

    plot1 = $.jqplot('chart1',[arr],{
        title: 'Transparent Bubbles',
        seriesDefaults:{
            renderer: $.jqplot.BubbleRenderer,
            rendererOptions: {
                bubbleAlpha: 0.6,
                highlightAlpha: 0.8
            },
            shadow: true,
            shadowAlpha: 0.05
        }
    });
}
</script>
</head>
<body>
<div id="chart1" style="height:300px;width:300px; "></div>
</body>
</html>

Excelシートのデータを変更してボタンを押すと、BubbleChart(というらしい)が変化する模様は、なかなかわかりやすいくて使いやすいと思いました。
いろいろと応用がききそうです。

]]>
../../../20131207651/feed/ 0
QtとHaskell/VisualStudio ../../../20131124638/ ../../../20131124638/#comments Sat, 23 Nov 2013 15:04:32 +0000 http://xfra.me/?p=638 QtとHaskellは、どちらもソースコンパチブルでクロスプラットフォームの対応ができることから、実行環境について類似点があると思っています。またQtはC++、HaskellはFFI(Foreign Function Interface)によりC言語との親和性がとても高く、長年Cに慣れてきた自分にとって、この二つはとても肌に合う技術です。

JavaVMや.NET(Mono)の中間言語、Python等の軽量言語でクロスプラットフォーム開発をする方法もいいですが、Cでも古くない(やれることが新しい言語に負けていない)という点が魅力に感じます。
QtはUI、Haskellはロジックという使い方で、いろいろやってみたいことがあり、まず最初に、Hakellの関数の戻り値をQWebViewに表示してみることにしました。(WebViewに、ということは、JavaScriptとの連携ができることを意図しています。) QWebviewは以前「QtWebKit.QWebView を使ったPython、JavaScript連携」でテストしましたが、今度はQtがメインでVisualStudioでビルドしました。

環境

Glasgow Haskell Compiler, Version 7.6.3 stage 2 booted by GHC version 7.4.

Qt 5.1.1 for Windows 32-bit
qt-windows-opensource-5.1.1-msvc2010-x86-offline.exe

Visual Studio Add-in 1.2.2 for Qt5
qt-vs-addin-1.2.2-opensource.exe

mainwindow.cpp

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

#ifdef __cplusplus
extern "C"
{
#endif
__declspec(dllexport) void __stdcall HsBegin(void);
__declspec(dllexport) void __stdcall HsEnd(void);
__declspec(dllexport) long __stdcall adder(long x, long y);
#ifdef __cplusplus
}
#endif

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
	ui->webView->load(QUrl("file:///c:/test.html"));
}

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

void MainWindow::on_pushButton_1_clicked()
{
  char buf[20];

    HsBegin();
    sprintf_s(buf, "adder : %d", adder(1,2));
    HsEnd();

    ui->webView->page()->mainFrame()->findFirstElement("body").appendInside(buf);
}

Haskellコードは「Haskell from Excel」を参考にしてください。

プログラムを起動するとtest.htmlが読み込まれ、ボタンを押すとエリアに演算結果が追加されます。
実はこのプログラムは、いきなりVisualStudioで作成したのではなく、QtCreator 2.8.1(Baseed on Qt 5.1.1 MSVC 2010.32bit)で作成したものを、Qt5Add-Inを組み込んだVisualStudioで読み込みました。
Qt Creator
QtCreator

Visual Studio Add-in 1.2.2 for Qt5 (Open Qt Project File(.pro))
Qt4AddIn

もちろんQt Creatorだけでも開発可能ですが、Add-InのテストをするためVSを使用しました。
Haskellをメインに、Qtを使うこともできるようですが、私の環境では、ghcで使われているmingwと、Qtで使われるmingwのバージョンが違うせいか、実行時にエラーとなりました。
なかなか思い通りになってくれないものですね。

]]>
../../../20131124638/feed/ 0
QtWebKit.QWebView を使ったPython、JavaScript連携 ../../../20130420194/ ../../../20130420194/#comments Sat, 20 Apr 2013 14:07:57 +0000 http://xfra.me/?p=194 前々回、WebViewでのC#、JavaSCript間の連携の話題、そして前回IronPythonを使ったWebページの話題という流れて、どうしてもテストしておきたかったのが、Qtを使ったWebViewのPython、JavaScript間相互呼び出しです。
Qtは、LinuxZaurusの開発で経験がありますが(組み込みLinux用なのでQtopiaと呼ばれていましたが)、C++でクロスプラットフォームのGUIアプリケーションを開発できます。歴史は古いのですが、まだまだ現役のようです。最近また触れる機会があり、いろいろと調べてみたところ、WebKitを使ったプログラムが面白そうだということで、ちょっとはまっています。PySideというライブリを使って、Pythonからダイレクトに操作できる点も魅力です。
次の例は、起動するとPythonのプログラムからJavaScript関数を呼び出し、表示されたボタンをクリックすると、Python関数を呼び出すというものです。これはコンソールにメッセージを出力します。

環境: Python 2.7.3 + PySide 1.1.2 / Windows7


import sys
from PySide import QtWebKit,QtGui,QtCore

html = """
<html>
<script>
function pyMsg(str){
	pyObj.console(str);
}
function jsFunc(str){
	alert(str);
}
</script>
<body>
<input type="button" value="btn" onClick="pyMsg('js String')">
</body>
</html>
"""
 
class jsTest(QtCore.QObject):
	def __init__(self, parent=None):
		super(jsTest, self).__init__(parent)
	@QtCore.Slot(str)
	def console(self, msg):
		print msg

app = QtGui.QApplication(sys.argv)
view = QtWebKit.QWebView()
frame = view.page().mainFrame()
js = jsTest()
view.setHtml(html)
frame.addToJavaScriptWindowObject('pyObj', js)
frame.evaluateJavaScript("jsFunc('from py Function');")
view.show()
sys.exit(app.exec_())

他にも、クリックイベント等をフックできるので、デバッグやその他いろいろと楽しいことができます。
自分ブラウザみたいなものを作ってみたくなりますね。

]]>
../../../20130420194/feed/ 0