ひとりも見捨てないことを、あきらめない

学校教育、社会教育、数学、技術家庭科、Youtube、EdTech、ICT、プログラミング、その他

実行ファイルをコンパクトにまとめる 01/11 土

 Visual StudioC# と NET 4.7 あたりをつかってしばらくプログラミングしていましたが、SQLite や PDFium などを追加していくと、どんどん DLL ファイルが増えていって、実行ファイルが埋もれていきます。

 また、実際に配布する際に、いろいろなファイルが含まれていると、解凍したときにトラブルの原因になりえます。

 そこで、「いろいろなファイルをひとつにまとめることはできないだろうかと」と検索してみたところ、Visual StudioC# と Net Core を使うと、標準で「ひとつにまとめる機能」が使えることがわかりました。

 たとえば、プロジェクトとして、WinPro4 という名前のプロジェクトがあったとします。単一ファイルを格納する場所として、single というフォルダを作っておきます。

 

f:id:takase_hiroyuki:20200112063608p:plain

さて、プログラムでは、通常のビルドでは、こんな感じでファイルが作られます。

 

f:id:takase_hiroyuki:20200112063453p:plain

 そこで、Visual Studio を用いて、次のような手順で単一ファイルを発行すると、目標の単一ファイルを作ることができます。

f:id:takase_hiroyuki:20200112065628p:plain

 

f:id:takase_hiroyuki:20200112065821p:plain

 

f:id:takase_hiroyuki:20200112070345p:plain

 

f:id:takase_hiroyuki:20200112070615p:plain

 

f:id:takase_hiroyuki:20200112070831p:plain

f:id:takase_hiroyuki:20200112071034p:plain

 

f:id:takase_hiroyuki:20200112071148p:plain

 

 いろいろな DLL ファイルを取り込んでいるので、36MB という大きさになっていますが、自分としては「まあ、こんなものかな」という感覚です。

 ただし、Visual Studio の Net Core では、フォームのデザイナーが使えません。したがって、さまざまなコントロールを、すべてプログラムで組み込んで行かなければなりません(昔は、すべてのプログラムが、そのような感じでしたけれど)。

 Visual Studio のフォーム・デザイナーは、とても使いやすいので、私の場合には、ア、まず Net 4.7 あたりで、フォームデザインする。イ、そのコードを真似して、Net Core でプログラムを作っていく。という二段階でプログラムしています。

 

SQLite データベースに、画像を保存する 01/10 金

 デスクトップで画像を処理して、それをデータベースに保存したり読み出したりというのは、基本的な事柄だと思います。しかし、現実には、検索してみても、ほとんどそういう記事が出てきません。

 自分で調べたり、他の詳しい方に質問したりして、だいたい次のような形にまとまりましたので、メモしておきます。

 

■環境

Windows10, Visual Studio 2019, C#, NET Framework 4.7, System.Data.SQLite

 

■NuGet

Visual Studio 2019 のプロジェクトから、NuGet パッケージの管理を選択し、「参照」で、「System.Data.SQLite」で検索すると、一番上に「System.Data.SQLite v1.0.112」が出てくるので、インスト―します。(2020/01/12 現在)

 

■ソース・ファイル

 次のようにプログラムします。このコードを、Form1.cs に丸ごと貼り付ければ、おそらく、動きます。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SQLite;
using System.Data.SQLite.EF6;
using System.Data.SQLite.Generic;
using System.Data.SQLite.Linq;
using System.Drawing;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Grph_SQLite
{
    public partial class Form1 : Form
    {
        Image im1, im2;

        public Form1()
        {
            InitializeComponent();

            using (var conn = new SQLiteConnection("DataSource=data.db"))
            {
                conn.Open();
                var comm = conn.CreateCommand();
                string sb = "CREATE TABLE IF NOT EXISTS mydata " +
                    " (name TEXT NOT NULL, face BLOB)";
                comm.CommandText = sb;
                comm.ExecuteNonQuery();
                conn.Close();
            }

            #region 画像を切り取って、im1, im2 に格納し、表示する。

            PictureBox pic = new PictureBox();
            pic.Location = new Point(10, 10);
            pic.Size = new Size(500, 300);
            pic.Image = Image.FromFile("data.png");
            Controls.Add(pic);

            // 元のイメージを切り取って、im1 に貼り付ける
            im1 = new Bitmap(300, 70);
            Graphics g = Graphics.FromImage(im1);
            Rectangle srcRect = new Rectangle(90, 80, 300, 70);
            Rectangle desRect = new Rectangle(0, 0, 300, 70);
            g.DrawImage(pic.Image, desRect, srcRect, GraphicsUnit.Pixel);
            g.Dispose();

            PictureBox pic1 = new PictureBox();
            pic1.Location = new Point(10, 350);
            pic1.Size = new Size(300, 70);
            pic1.Image = im1;
            Controls.Add(pic1);

            // 元のイメージを切り取って、im2 に貼り付ける
            im2 = new Bitmap(300, 70);
            g = Graphics.FromImage(im2);
            srcRect = new Rectangle(90, 180, 300, 70);
            desRect = new Rectangle(0, 0, 300, 70);
            g.DrawImage(pic.Image, desRect, srcRect, GraphicsUnit.Pixel);
            g.Dispose();

            PictureBox pic2 = new PictureBox();
            pic2.Location = new Point(10, 450);
            pic2.Size = new Size(300, 70);
            pic2.Image = im2;
            Controls.Add(pic2);

            // 以上で、im1, im2 に画像データが格納されたことが確認できた。

            #endregion

            #region 画像をデータを、データベースに登録する。

            using (var conn = new SQLiteConnection("DataSource=data.db"))
            {
                conn.Open();

                var comm = conn.CreateCommand();
                string str = "insert into mydata(name) values('visual studio1');";
                comm.CommandText = str;
                comm.ExecuteNonQuery();

                str = "insert into mydata(name) values('visual studio2');";
                comm.CommandText = str;
                comm.ExecuteNonQuery();

                // こうすればできます
                comm.CommandText = "insert into mydata(name,face) values ('visual studio3',@face);";
                ImageConverter converter = new ImageConverter();
                byte[] fdata = (byte[])converter.ConvertTo(im2, typeof(byte[]));
                var param = new SQLiteParameter("@face", System.Data.DbType.Binary);
                param.Value = fdata;
                comm.Parameters.Add(param);
                comm.ExecuteNonQuery();

                conn.Close();
            }

            #endregion
        }
    }
}

 つぎに、実際のプログラムでは、このような保存作業を、一度に 10000回程度実施する予定ですので、for 文を用いて、10000 回実施してみました。

using (var conn = new SQLiteConnection("DataSource=data.db"))
{
    conn.Open();
    SQLiteCommand cmd = conn.CreateCommand();
    ImageConverter converter = new ImageConverter();
    byte[] fdata;
    SQLiteParameter param;

    for (int i=0; i < 10000; i++)
    {
        /*
        cmd.CommandText = "insert into mydata(name) values (@ID)";
        cmd.Parameters.Add(new SQLiteParameter("@ID", "visual studio4"));
        cmd.ExecuteNonQuery();
        */

        cmd.CommandText = "insert into mydata(name,face) values ('visual studio5',@face);";
        fdata = (byte[])converter.ConvertTo(im2, typeof(byte[]));
        param = new SQLiteParameter("@face", System.Data.DbType.Binary);
        param.Value = fdata;
        cmd.Parameters.Add(param);
        cmd.ExecuteNonQuery();
    }

    conn.Close();
}

ところが、100000回、作業を行うのに5分から7分程度必要で、とても実用に堪えないことがわかりました。このことについては、あちこちのページで「トランザクション処理が原因で、非常に速度が遅くなる」と書いてありましたので、実際に作業の前後にトランザクションに関する命令を追加しました。

    var ts = conn.BeginTransaction();
<途中の処理>
ts.Commit();

この2行を追加したプログラムは、次のとおりです。

using (var conn = new SQLiteConnection("DataSource=data.db"))
{
    conn.Open();
    var ts = conn.BeginTransaction();
    SQLiteCommand cmd = conn.CreateCommand();
    ImageConverter converter = new ImageConverter();
    byte[] fdata;
    SQLiteParameter param;
    for (int i=0; i < 10000; i++)
    {
        /*
        cmd.CommandText = "insert into mydata(name) values (@ID)";
        cmd.Parameters.Add(new SQLiteParameter("@ID", "visual studio4"));
        cmd.ExecuteNonQuery();
        */

        cmd.CommandText = "insert into mydata(name,face) values ('visual studio5',@face);";
        fdata = (byte[])converter.ConvertTo(im2, typeof(byte[]));
        param = new SQLiteParameter("@face", System.Data.DbType.Binary);
        param.Value = fdata;
        cmd.Parameters.Add(param);
        cmd.ExecuteNonQuery();

    }

    ts.Commit();
    conn.Close();
}

今度は、作業は数秒で終了してしまいました。

f:id:takase_hiroyuki:20191123160855p:plain

「クラス」の考え方のひとつ 01/09 木

 今まで C++ を使っていて、最近になって C# を使うようになって、やはりひっかかったのがクラスの考え方です。

 Visual Stidio 2019 では、あらかじめ「ひな形」が用意されているので、「だいたいこんな感じのものが作りたい」と考えたときには、その原型になるようなものは、ボタンひとつで作ることができます。

 しかし、そこから先、自分の意図するものを作るためには、プログラミングが必要です。このとき、「基本的にどのように考えればよいのか」が分かっているか否かで、作業効率が大きく異なります。

 「基本的にどのように考えればよいか」は、基本的な考え方ですから、わかってしまえば、まさに基本的なので、あたりまえのことになってしまいます。しかし、わかるまでの間は、逆に、基本的すぎて、「いったい、何がなんだか、全然わからない」という状態になります。

 おそらく、検索しても、あまりこういう情報がひっかかってこないのは、「分かってしまえば当たり前なので書く必要がない」、「分かるまでは、全然わからないので、書きようがない」ということなのではないかと思います。

クラスは設計図である。そして C# にはクラスしかない

 いろいろなサイトを眺めていて、私自身が一番「なるほど、そういうことか」と感じたのが、上の文章です。

 クラスというのは、設計図である。設計図であるから、プログラムしている時点では、まだ実物は存在しない。したがって、なにか「あるもの」が最初から存在すると想定してプログラムしようとすると、行き詰まってしまう。 

ということだと思います。

 昨日のブログでも書いたとおり、クラスを使いたいと考えるのは、「ひとつのものに、たくさんの部品や属性があって、ゴチャゴチャしてしまうので、それらの部品や属性をひとつのものとしてまとめてしまおう」という場面だと思います。この、「ひとつのもの」というのが、プログラム全体で一種類しかなければ、そんなに問題になりません。

 ところが、「こういうゴチャゴチャ」と「ああいうゴチャゴチャ」があって、それぞれ、ひとつのものとしてまとめたいと考えます。これらのゴチャゴチャは、全体としてひとつのプログラムになっていくのですから、当然、相互に関係しています。ところが、「こっちのゴチャゴチャ」も、「あっちのゴチャゴチャ」も、それぞれが設計図ですから、まだ実物がありません。

 こっちのゴチャゴチャで、こういうことをしたい(こういうことが想定されるから、こういう作業をしたい)という場面で、「じゃあ、あっちのゴチャゴチャの、この部分も一緒に変更しよう」と考えると、「それは、まだ実物がないから、触れないですよ」と叱られます。

 仕方がないので、じゃあ、あっちのゴチャゴチャを先に処理して、その後で、こっちを処理しようとすると、「こっちは設計図だから、触れません」と言われます。

 じゃあ、どちらも設計図なんだから、それらの設計図にしたがって組み立てる前に、あらかじめ共通のものをつくっておけば、両方からアクセスできて良いんじゃないだろうか、と考えると、「 C# は、クラスしか認めていないので、あらかじめ共通のものをつくることはできません」と言われます。

いったいどうすればいいんだー

 と思うわけですが、一応、逃げ道があって、

    static public 型名 変数名;

というものを使います。「static」は「静的な」という意味で、「public」は、「他のクラスからも見ることができて、アクセス可能な」という意味です。このうち、「静的な」という部分が肝心で、「設計図を書く段階で、この静的なモノについては、あらかじめ実物を用意しておく」という意味になります。したがって、「実物がちゃんとある」、「他のクラスの設計図からもアクセスできる」ということになるので、めでたし、めでたしということになります。

 ほとんどの「モノ」は、プログラムを実行する場面までは設計図のままで、本当に実行するときに、ちょっとだけ実物をつくって、すぐに廃棄してしまう。そうすれば、余計なスペースは必要なくて、効率よく作業ができる。そして、本当にプログラム全体で共有しなければならないものだけを、「わざわざ、static public という形容詞をくっつけて」あらかじめ実物をつくっておく。というのが、C# の基本的な考え方なんだなあと、思いました。

f:id:takase_hiroyuki:20191123160855p:plain

 

プログラミングで「クラス」を使ってみる  01/08 水

 ひとつの「ことがら」について、さまざまな「属性」を考慮しなければならないので、いろいろな「変数」や「関数」がゴチャゴチャしてきました。

 こっちを、こういうふうに動かしたい、と考えたときに、あれもこれもみんな調整しなければならないので、ついうっかり調整を忘れてしまうことがあります。

 いままでのプログラミングの方法だと、うっかり忘れて、うまく動かないときに、原因を調べるのがとても大変です。

 そこで、「オブジェクト指向プログラミング」とか「クラス」とかいうものを使い始めましたが・・・。やっぱり、最初はとまどうばかりです。

f:id:takase_hiroyuki:20191123160855p:plain

 

フィットネス開始です  01/06 月

今年もフィットネスを継続します。

走行距離については、一度、リセットしました。

フィットネス 2020/01/05

現在の走行距離の合計、約13km 
キャット&ドッグ 3回x3セット
ラット・プル (25kg+27kg+29kg)x10回
ベンチ・プレス 20kgx10+30kgx7+35kgx3+45kgx30回
 
トレッドミル(25分間) 2,950m ⇒2020年の累計 2,950m
 
ハムストリングス 23kgx10回x3セット
レッグ・エクステンション 39kgx10回x3セット
アダクション 52kgx10回x3セット
アブダクション 43kgx10回x3セット
プレス・ダウン。最後にねじる 34kgx10回x4セット
アーム・カール 29kgx10回x4セット
レッグ・プレス 57kgx10回x3セット
腹筋 1秒x20回x3セット
ダンベル(内側) 10kgx25+12kgx5
ダンベル(外側) 4kgx20回x3セット
ライイング・トライセップス・エクステンション 10kgx40回+12.5kgx5回
フロント・プル 39kgx10回x3セット
 
バイク(25分間) 10,300m ⇒2020年の累計 10,300m

f:id:takase_hiroyuki:20190519162425p:plain

 

画像を切り取るのは、意外に面倒くさい  01/05 日

 あたえられた画像があって、「ある範囲の部分を切り取って、別のところに貼り付ける」という作業は、しばしば行う作業だと思います。図面でも、イラストでも、地図でも、「一部を切り取る」というのは、ごく普通のことだと思います。

 ところが、プログラムでこのことを実行しようとすると、「C#」という言語の場合には、意外に面倒な作業になってしますので、びっくりしてしまいました。

 通常は、プログラムで画像を扱う場合には、「もともとの画像を読み込んで表示して終わり」という場合が多いので、これをさらに加工しようとすると、面倒な手続きが必要になります。

 プログラミングというものを考えるときの参考になるだろうと思うので、以下に、手続きを書いておきます(あいまいな表現を、わざと使っています)。

  1. 画像を読み込むための場所を確保する
  2. その場所に画像を読み込む
    ⇒ 読み込んだものは、表示することも可能です
  3. 読み込んだ画像に対して「これから処理しますよぉ」ということを宣言しておく。
  4. 宣言するだけでなく、実際に処理するための道具も用意する。
  5. 処理した結果を格納するための場所を別途用意する
  6. 元の画像に対して、「道具」を用いて画像を処理し、結果を新しい場所に保存する。

以上のような作業の流れになります。

 これらは、「画像を処理するだけ」の内容なので、処理前の画像や、処理後の画像を表示させるのは、別の作業になります。

 具体的には、「この画像を、この場所に表示させる。表示させるときの大きさはこうする」みたいなことを、ひとつひとつ教えてあげないと表示してくれません。

 一応、処理の内容について、具体的にプログラミング言語を用いて書いておきます。

// 元の画像を pic という場所に表示させる
PictureBox pic = new PictureBox();
pic.Location = new Point(10, 10);
pic.Size = new Size(500, 300);
pic.Image = Image.FromFile("data.png");
Controls.Add(pic);

// 元のイメージを切り取って、im1 に貼り付ける
im1 = new Bitmap(300, 70);
Graphics g = Graphics.FromImage(im1);
Rectangle srcRect = new Rectangle(90, 80, 300, 70);
Rectangle desRect = new Rectangle(0, 0, 300, 70);
g.DrawImage(pic.Image, desRect, srcRect, GraphicsUnit.Pixel);
g.Dispose();

// im1 を pic1 に表示させる
PictureBox pic1 = new PictureBox();
pic1.Location = new Point(10, 350);
pic1.Size = new Size(300, 70);
pic1.Image = im1;
Controls.Add(pic1);

// 元のイメージを切り取って、im2 に貼り付ける
im2 = new Bitmap(300, 70);
g = Graphics.FromImage(im2);
srcRect = new Rectangle(90, 180, 300, 70);
desRect = new Rectangle(0, 0, 300, 70);
g.DrawImage(pic.Image, desRect, srcRect, GraphicsUnit.Pixel);
g.Dispose();

// im2 を pic2 に表示させる
PictureBox pic2 = new PictureBox();
pic2.Location = new Point(10, 450);
pic2.Size = new Size(300, 70);
pic2.Image = im2;
Controls.Add(pic2);

// 以上で、im1, im2 に画像データが格納されたことが確認できた。

f:id:takase_hiroyuki:20191123160855p:plain

マウスの動きをとらえるには  01/04 土

 画面上で、マウスを動かして、なにかをクリックしたり、なにかを動かしたりということは、よくやることです。私が現在、作成中のアプリケーションでも、

  1. 全体の画面をまず、表示させる
  2. その画面上でマウスを動かし、クリックしたところに図形を表示させる
  3. さらに、表示させた図形を移動させたり、拡大・縮小したりして微調整していく

ということをやっています。このこと自体は、それほど難しいことではありません。

 プログラムで、現在のマウスの位置を取得し、クリックしたときには、こういうものを表示させる、という基本的な事柄は、すべて部品がそろっているので、それらを組み合わせるだけです。しかし、問題なのは、

 すでに部品を配置してしまうと、うまくいかない

 ということです。これは、どういうことかというと、アプリケーションでは、「現在表示されているものの(たとえばAという名前のものだとします)上でマウスが動いたり、クリックされたりしたら、別のもの(Bというものだとします)を表示させる」というふうにプログラムします。

 これは、どうやってプログラムするかというと、「 Aという部品の上での動きを設定する」というところに記入する、という約束になっています。A の上では、こういう動きをするけれども、B の上に来たら、原則としてモノが違うので、違う動きをするということになります。

 これは、当然といえば当然で、スクロールバーやボタンやチェックボックスなど、いろいろなタイプの部品がありますから、そのうえで何かの作業をするときには、それぞれ別々にプログラムする必要があるわけです。

 ところが、私が作っているアプリケーションでは、一番土台となる画像の上に、さまざまな部品を配置していきますので、複数の部品が重なることもありますし、上に部品が乗っていても同じ動きをしないと困ります。でも、上に述べたとおり、部品が違えば動きや働きが違ってくるのが当然なので、じゃあ、いったい、どうすればいいんだということになります。

 しかも、クリックするたびに新しい部品が画面に乗るので、部品の総数は、あっという間に数十になります。それらについて、ひとつひつ「動きや働き」を設定していくのは、極めて非効率的です。

 では、こういうときにはどうすればいいかと、あちこちのページを見てみるのですが、こういう細かい話は、どこにも書いてありませんので、結局、自分で考えなければなりません。

 では、どうするか

 いろいろやってみた結果、わかったことは、

  1. あらかじめ、こういう働きや動きをしてほしい、ということを、まとめて書いておく。
  2. この、まとめて書いたものについて、名前をつけておく
  3. 画面にたくさん配置するものを、あらかじめ用意する。
  4. 用意したものに、上の「名前をつけたもの」を、あらかじめ全部くっつけてしまう(これは、一括操作で可能)
  5. たくさん配置するものは、つくるだけ作っておくが、とりあえず画面に表示させず、クリックしたときに現れるようにする

という方法で可能だということがわかりました。ポイントは、「こうなってほしいということを、まとめて書いておいて、名前をつけておく」ということでした。でも、実際にこういう場面に遭遇しないと、考えるチャンスがありませんし、解決方法もなかなか思いつかないなあと感じました。

 ひとつひとつの課題は、解決しつつありますが、全体が完成するまでには、まだ時間がかかります。のんびり作っていこうと考えています。

f:id:takase_hiroyuki:20191123160855p:plain

 

こんな仕組みだったんですねえ(スクロール)01/03 金

作業するために、大きく表示させたい

 年末・年始の間も、時間をつくってプログラミングを継続しています。次第にアプリケーションの形になりつつあります(こういう時期は、だんだんに出来上がっていくので、とても楽しいです)。

 下の図は、「だいたいこんな感じのアプリケーションにしたい」という概念的なものを表しています。

f:id:takase_hiroyuki:20200104154811p:plain

 これは、どういうことかというと、メニューの代わりに「タブ」があって、主たる作業はこのタブで行いながら、別のタブで設定等を随時おこなえるようにしようというものです。

 一番上にタブがあり、上下の真ん中のところで作業を行い、一番下には、現在の状態を表すような場所があります。この状態で、真ん中の作業用の場所では、全体がおさまり切らないので、上下にスクロールできるようにしたいと考えています。そこで、あちこちのホームページを参考にして、スクロール・バーを表示させるようにしました。具体的には、

    AutoScroll = true;

というものを一行、追加するだけです。これだけで「はみだす場合には、スクロール・バーを表示させ、上下にスクロールできるようにする」ということが実現します。もちろん、はみ出さない場合には、スクロールバーは表示されません。とても便利な仕組みなので、さっそくこれを使うことにしました。具体的には、この画面全体は Form という部品でできているので、その Form に設定してみました。

 ところが、うまくいきません。

 うまくいかないというのは、「上のメニューも、下の情報を書くところも、全部、一度にスクロールしてしまう」という状態になってしまいました。「スクロールさせようとしたら、一番上のメニューが、消えてなくなってしまった」、ということでは作業が続けられません。

 じゃあ、どうすればいいのか、というと、このくらい細かい話になると、あちこちのページを見ても、どこにも書いてないのです。書いてありませんが、「真ん中の部分だけがスクロールする」というのは、ごく一般的なアプリケーションであれば、ちゃんとそういうふうになっていますから、できないワケはありません。

 そこで、あれこれ実験してみた結果、おそらく次のような方法を、皆さんは採用しているのではないかということが分かりました。

  1. まず、上にタブ(メニュー)を配置し、下に情報を表示する場所を配置する(ここまでは同じ)
  2. まんなかに、panel (パネル)というものを配置する。パネルには、スクロールバーを設置することができます。パネルにスクロールバーが表示されるのは、パネルの中に「パネルよりも大きなものが配置されたとき」です。
  3. そこで、真ん中に、実際に作業したいスペースを、パネルよりも大きなサイズで配置する。「大きなサイズで配置する」目的は、小さすぎると、細かくて見えないからです。ある程度、拡大できるようにしないと、細かいところがきちんと作業できません。

このようにして、上と下を固定した状態で、真ん中だけをスクロールするということが可能になりました。

でも、まだ細かい設定が必要です

 上のような方法で終わりなら良いのですが、実際には、細かい設定作業が残っています。というのは、全体の場面のなかに、いくつかの部品を配置していくのですが、

  1. 画面の上部のタブ(メニュー)の幅と高さ
  2. 真ん中で作業するパネルの幅と高さ
  3. 下の情報を示す場所の幅と高さ
  4. 真ん中のパネルの中に配置する作業場所の幅と高さ

というものは、すべてプログラムで自分で数値を計算して、あてはめて行かなければなりません。

 もともと、スクロールさせようという目的は、アプリケーション全体を大きく表示させたり、ある程度小さく表示させても、中の部品たちが、それなりに拡大・縮小して表示させるようにしたいからです。

 こういうのを、全部、プログラムで計算して、表示させているんだなあと、自分でアプリケーションをつくりながら、つくづく感心している次第です。みなさん、頑張って作っているんですね。

 ひとつひとつの課題は、解決しつつありますが、全体が完成するまでには、まだ時間がかかります。のんびり作っていこうと考えています。

f:id:takase_hiroyuki:20191123160855p:plain

 

GIGAスクール構想 01/02 木

寺西さんの文章を以下に引用します。引用元↓↓↓www.facebook.com

 

---ここから--

GIGAスクール構想関係

 砂岡 克也 (Katsuya Sunaoka) さんがとてもわかりやすくまとめてくださっていますのでご紹介します。

教育ICTの課題を丸裸にし議論する会
https://www.facebook.com/groups/1589822677996191/
への投稿の引用です。

 せっかくついた国庫の予算を、教育委員会から財務部局、首長、そして議会と納得して動いていただくために、関係者みんな必死です。
ありがたいことに私のウォールは教委、首長、議員さんもご覧いただいている方がいらっしゃいますので、少しでも、と思い、情報提供を続けます。 #ぜんぶGIGAのせいだ

=====

 年の瀬ですが今回は若干不明確事項含む情報を少々。

 今回の1人1台政策でネットワーク整備と端末整備の補助が分かれていることはご存じかと思いますが、そのタイミングに関する情報と、実は自治体間を大きく分断しかねない格差の危惧についてのお話です。

 まず①ネットワーク整備、これは今年度と来年度しかチャンスがありません。合わせて15か月間の内を対象とした補助金で、自治体の実負担が2割。有線LANもカテゴリ6A化推奨のため、古い有線LAN配線の張替えが推奨されます。

 基本的にはすべての自治体がこの補助金で有線/無線LAN整備をすべきで、このチャンスにやらなければ国がこんなにまるっと整備資金を拠出することは2度とないでしょうし、文科省はどうあろうとここで全部の学校が必ず整備してもらいたいと言っています。これは12月26日に文科省の財政省折衝担当の方からも直接聞いています。

 次に②端末整備ですが、自治体の大きさに関わらず全公立児童生徒数の2/3に対して税込4.5万円定額補助となっています。

 残りの1/3の分は、2018年から5年間国から拠出されている地方財政措置1805億円から自治体の整備財源に充てることになっており、この地財措置1/3+補助金2/3による整備計画をつくることが今回の2/3補助事業に参加する条件となります。

 これも若干課題がありますが、それは別途言及するとして、これは果たしてどういう時期に整備に向けた動きが起こるのか。

 まだ公に確定的なことを言えない部分もありますが(まだ決まってないので)、まず対象の小中9学年に対する端末補助は基本的に2020年から2022年の3年となります(一部メディアでは違うスパンが出ていたりしますが…)。

 そして初年度の2020年がどうなるのかですが、2020年4月までに自治体が結論を出して手を上げないと対象にはならない、などと無茶なことにはならないといえます。
そもそも1人1台政策の公表もここ1.5か月のことなので、自治体の来期予算審議に間に合うわけがありませんね。
ただ、来年度内の遅くないうちに端末1/3分費用拠出方針をなんとか仕立てて議会にウンと言わせなければなりません。
 その時期がいつなのかはいずれ情報が出てきます。

 ここでまた重要なのは、①と同じくこのタイミングでやらなければ国が児童生徒の2/3の端末数を資金拠出することなど2度とないと言われていることです。ここでやらなければ取り組む自治体との情報教育格差は2度と取り戻せないほどに広がり、大変深刻な状態に陥る危険性があります。
もしそうなった場合は、その地方行政や議会は地域住民に対してその責を負わなければなりません。

 これをご覧になった方は、ご自身が住み、働き、関係している自治体やその学校がどうしようとしているのか知ったうえで、「これはまずい…」と思われるようでしたら教委、地方議員、ひいては首長部局に訴えかけるべきかもしれません。

 住民の声は自治体にとって重要ですし、地域の子どもたちの学びを現代および今後の社会に耐えるものに進歩させるのか、社会と乖離したアナログ時代のままでいくのかがこの1,2年で決まってしまいます。 

 ---ここまで---

 

なお、文部科学省のページは、次のとおりです。

www.mext.go.jp

 

f:id:takase_hiroyuki:20191231171321p:plain

 

あけましておめでとうございます。 01/01 水

2019年も、多くの方に御世話になりました。

こころから御礼申し上げます。

2020年は、いままでのペースを落とさず、ひとつひとつ確実に実行する所存です。

どうぞ、よろしくお願いいたします。

f:id:takase_hiroyuki:20200101064757p:plain

 

PDFファイルを読むことに成功しました 12/31 火

 Visual Studio 2019 の C# NET Core では、NuGet を用いて、PDFium ライブラリを使うことができます。しかし、私が拝見したブログの内容をそのまま実現することはできませんでした。

 そうなると、他の方法を考えなければなりません。NuGet のライブラリには、ダウンロードの件数が記載されています。「ダウンロードの件数が多い方が、人気があって使いやすいだろう」と考えました。残念ながら件数順に並んでいるわけではないので、ざっくり眺めてみて、次のいくつかを候補として考えました。

  • PDFium Viewer
  • CUBE PDFium
  • PDFiumLight
  • PDFium.Net.SDK

 どれが良いか分からないので、順番にやってみるしかありません。しかし、インストールがそもそもできなかったり、肝心の C# NET での使い方がわからなかったりで、なかなかうまく行きません。マニュアルが見当たらないというのも、困ったことです。ライブラリだけあっても、使い方が分からなければ、使いようがありません。

 そんなときに、(あれこれ検索しているうちに)見つけたのが、次のページです。

  そのものズバリで、「NuGet での pdfium パッケージのベスト20 」です。見てみると、最も人気があるのは、PDFium.Net.SDK でした。そこで、このパッケージについて集中的に検索してみると、次のようなマニュアルページが見つかりました。

 これが、まさに私が必要としていたページで、しかも C# のサンプルプログラムも、多数掲載されています。また、最初のページには、次のような英文が記載されていました。

Compatibility

Pdfium.Net SDK is available for .Net Framework 2.0 - 4.7 on 32- and 64-bit operating systems.

SDK has been tested with Windows XP, Vista, 7, 8, 8.1 and 10, and is fully compatible with all of them. The native PDFium.dll library included to this project is supplied in both 32-bit and 64-bit versions, so your .NET application can be "Any CPU".

 そして、私が必要としていたのは、「PDF を画像に変換する」という機能なのですが、そのことについては、次のようなサンプルが記載されていました。

    public void RenderPage()
{
    //Initialize the SDK library
    //You have to call this function before you can call any PDF processing functions.
    PdfCommon.Initialize();

    //Open and load a PDF document from a file.
    using (var doc = PdfDocument.Load(@"c:\test001.pdf"))
    {
        int i = 0;
        //Iterate all pages;
        foreach (var page in doc.Pages)
        {
            //Gets page width and height measured in points. One point is 1/72 inch (around 0.3528 mm)
            int width = (int)page.Width;
            int height = (int)page.Height;

            //Create a bitmap
            using (var bmp = new PdfBitmap(width, height, true))
            {
                //Fill background
                bmp.FillRect(0, 0, width, height, FS_COLOR.White);
                //Render contents in a page to a drawing surface specified by a coordinate pair, a width, and a height.
                page.Render(bmp, 0, 0, width, height,
                    Patagames.Pdf.Enums.PageRotate.Normal,
                    Patagames.Pdf.Enums.RenderFlags.FPDF_ANNOT);
                //Get .Net image and save it into file
                bmp.Image.Save(string.Format(@"c:\test001_pdf_page_{0}.png", i++), ImageFormat.Png);
            }
        }
    }

}

というわけで、実際に、やってみようと考え、C# NET Framework 4.7 でプロジェクトを作成し、NuGet で PDFium.Net.SDK をインストールしました。

 一番不安だったのは、名前空間の指定でした。実際のところ、上のプログラムをコピペしてビルドしてみると、「これこれが、見当たらない」というエラー・メッセージがたくさん出ます。しかし、オブジェクト・ブラウザーで検索すると、その見当たらないものがどの名前空間に所属しているのがわかりました。だとすれば、using にその名前空間を追加すればよいわけです。このようにして、実際には次の4つの名前空間を追加しました。

using Patagames;
using Patagames.Pdf;
using Patagames.Pdf.Net;
using System.Drawing.Imaging;

 

このようにして、作成したプログラムが以下のとおりです。

    using Patagames;
using Patagames.Pdf;
using Patagames.Pdf.Net;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace test03_SDK
{
    public partial class Form1 : Form
    {
        public Form1() { InitializeComponent(); }
        private void Form1_Click(object sender, EventArgs e) { RenderPage(); }

        public void RenderPage() {
            PdfCommon.Initialize(); // これは必ず必要
            using (var doc = PdfDocument.Load(@"c:\tmp\03.pdf")) // ファィルを開く
            {
                int i = 0;
                foreach (var page in doc.Pages) {
                    int width = (int)page.Width;   // 幅
                    int height = (int)page.Height; // 高さ

                    int nw = 1000;
                    int nh = height * 1000 / width;

                    var bmp = new PdfBitmap(nw, nh, true); // bitmap をつくる
                    bmp.FillRect(0, 0, nw, nh, FS_COLOR.White); // 背景は白

                    page.Render(bmp, 0, 0, nw, nh,
                        Patagames.Pdf.Enums.PageRotate.Normal,
                        Patagames.Pdf.Enums.RenderFlags.FPDF_ANNOT);

                    bmp.Image.Save(
                        string.Format(@"c:\tmp\test_{0}.png", i++),
                        ImageFormat.Png); // pngファイルに保存
                }
            }
        }


    }
}

これによって、PDFファイルを画像ファイルに変換することができました。大きな難関を、ひとつ超えることができました。この次は、データベースの取り扱いについてです。

f:id:takase_hiroyuki:20191123160855p:plain

 

 

フィットネス ・・・ 12/30 月

#フィットネス 2019/12/29
現在の走行距離の合計、約566km 

 本年度の、ほぼ最後の運動です。明日もフィットネス・ジムは開いているので、少し運動するかも知れません。一年間で、ランニングと自転車で合計570km ほど走りました。特に、ランニングだけでは150km弱になりました。また、ベンチプレスは、どうやら 45kg が安定してできるようになりました。3月頃に故障した左ヒザも、少しずつ良くなっています。今後も、無理をせず、少しずつ、少しずつ、頑張ろうと思います。

キャット&ドッグ 3回x3セット
ラット・プル (25kg+27kg+29kg)x10回
ベンチ・プレス 20kgx10+30kgx7+35kgx3+45kgx30回
 
トレッドミル(25分間) 3,140m ⇒2019年の累計 147,780m
 
ハムストリングス 23kgx10回x3セット
レッグ・エクステンション 39kgx10回x3セット
アダクション 52kgx10回x3セット
アブダクション 43kgx10回x3セット
プレス・ダウン。最後にねじる 34kgx10回x4セット
アーム・カール 29kgx10回x4セット
レッグ・プレス 57kgx10回x3セット
腹筋 1秒x20回x3セット
ダンベル(内側) 10kgx25+12kgx5
ダンベル(外側) 4kgx20回x3セット
ライイング・トライセップス・エクステンション 10kgx40回+12.5kgx5回
フロント・プル 39kgx10回x3セット
 
バイク(25分間) 10,300m ⇒2019年の累計 419,110m

f:id:takase_hiroyuki:20190519162425p:plain

 

どれを選ぶか PDFium C# Nuget・・・12/29 日

 開発言語を C++ から C# に変更したのは、PDF を読んだり書いたりするライブラリが比較的容易に入手できるからです。具体的には、NuGet というライブラリ集があって、必要なライブラリをここで見つけてインストールのボタンを押せば、それでインストール完了です。

 しかし、インストールしただけでは、何もできません。インストールしたライブラリを使用するためには、ちゃんと作法にしたがってプログラムを書かないとダメです。

 ところが、これが難しいのです。なにしろ、こういうことができる人というのは、コンピュータが得意な人ですから、「これって、アタリマエだよね」という感じで、サクサク仕事をします。逆に初心者(つまり私)は、いったいどこから手をつければよいのかが分かりません。入口付近でウロウロ迷いつづけるということになります。

 しかも、さらに困ったことに、ライブラリにはたくさんの種類があります。検索するとこんな風になります。

 書かれているのは英文ばかりですから、読むだけでも大変です。 

 実際には、私は次の記事を参考にしようと考えていました。

 

 ところが、このとおりにやっても、なかなかうまく行かない。そもそも最初の「名前空間」(って変な命名だよなあ)で、つまづいてしまう。あれこれ調べてみると、「名前空間」に関する情報を得るためには、オブジェクト・ブラウザーというものを使えばいいらしい、ということがわかりました。

 

 そこで、オブジェクト・ブラウザーを使って調べてみるのですが、なんだか、ブログ記事にかかれていることと違う結果が出てきます。「適当に書けば、なんとかなるだろう」と考えてプログラムしてみますが、なんとかなるワケがないですよね。エラー。エラー。エラー。エラー。エラー。エラー。エラー。エラー。エラー。エラー。エラー。エラー。エラー。エラー。エラー。エラー。エラー。エラー。エラー。エラー。の連続です・・・。

 

f:id:takase_hiroyuki:20191123160855p:plain

 

C# は「とっかかり」は面倒。わかってみれば簡単 ・・・ 12/28 土

 C# を使い始めました。「ひな形」は用意されているので、真っ白な画面をひとつだけ出すのであれば、すぐにできます。問題はその後で、「じゃあ、こういうことをやろうと思うんだけど、それって、どこに書けばいいの?」という状態になります。

 どうやら、C++C# では、モノの考え方が違っているようです。どちらも、基本的には「人間が何かをしたら、コンピュータがそれに対応して何かをする」という形になっています。たとえば、人間がメニューをクリックしたら何かを表示する、とか、画面上でマウスを動かしたら、それに対応して図形が動く、とかです。このこと自体は、C++C# も変わりありません(こういうのを、イベント・ドリブンと言うのだそうです)。

 問題は、それをどのように実現するかです。C++ の場合には、外から見た動きは、イベント・ドリブンですが、中身はそれよりも昔の考えをまだ引きずっていて、「これをやったら、次にこれをやる。その次にこれをやる。ここまで来たら、ここで待機する」みたいな手続きの順番がなんとなく見えています。

 ところが、C# になると、イベント・ドリブンの考え方がさらに進んで、「こういうことを人間がやったら、こうする」という断片的なことを、バラバラっと書いておしまいです。「あとは、コンピュータが適当に動くから、なんとかなるよ」みたいな感じです。

 「なんとかなるよ」と言われても、本当にちゃんと動くのかすごく心配です。したがって、できれば最初から順番に確認していきたいのですが、それができません。一応、順番に確認する手順も残っているのですが、プログラムの最初から順番に確かめていくと、比較的短い手続きのあとで、「ここから先は、おまかせ~」という状態になってしまいます。

 「いやいや、おまかせでは困る。これとこれと準備しておきたいんだけどなあ」と考えて、仕方がないので、それなりのところに準備のプログラムを書いてみると、その準備をすっ飛ばしてしまうという状態で、ほとほと困ってしまいました。なにしろ、一番簡単と思われるプログラムが書けないのです。

 結局2日ぐらいインターネットの資料をあちこち見て、試しては失敗し、試しては失敗しを繰り返した後、もうこれは自分ではどうにもならないと考えて、他の方に質問してみました。 

 質問してみたら、「これは、作法が違いますよ」という御指摘をいただき、「すいません。分かってませんでした」とお詫び申し上げ、すったもんだして、ようやくプログラムを作成することができました。記念すべき(?)最初のプログラムですので、ソースコードを書いておきます。

//
// 次のようなことを実現した。
//
// Form を表示させる。
// ラベルに現在の Form の左上の座標を表示させる。
// Form を移動させると、ラベルの座標の値も変化する。
// Form 内にボタンを表示させる。
// ボタンを押すと、ボタンの名前と、Form 全体の名前を変更し、Form を 左上に移動させる。


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

namespace test01
{
	public partial class Form1 : Form
	{
		public Form1()
		{
			InitializeComponent();

			this.label1 = new System.Windows.Forms.Label();
			this.label1.AutoSize = true;
			this.label1.Text = "★★ TEXT ★★";
			this.label1.Location = new System.Drawing.Point(50, 50);
			this.label1.TabIndex = 0;

			this.Controls.Add(this.label1);
			this.LocationChanged += Form1_LocationChanged; // 常に今の値が欲しい場合

			this.button1 = new System.Windows.Forms.Button();
			this.Controls.Add(this.button1);
			this.button1.Location = new System.Drawing.Point(50, 100);
			this.button1.Text = "my button 1";
			this.button1.AutoSize = true;
			this.button1.Click += new EventHandler(button1_Click);
			this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.Form1_MouseMove);
		}

		private void Form1_MouseMove(object sender, EventArgs e)
		{
			System.Drawing.Point sp = System.Windows.Forms.Cursor.Position;
			System.Drawing.Point cp = this.PointToClient(sp);
			int mx = cp.X;
			int my = cp.Y;

			this.Text = "Moved to (" + mx.ToString("0") + "," + my.ToString("0") + ")";
		}

		private void button1_Click(object sender,EventArgs e)
		{
			this.Text = "Button1 Clicked";
			this.button1.Text = "OK";
			this.Left = 10;
			this.Top = 10;
		}


		private void Form1_LocationChanged(object sender, EventArgs e)
		{
			int xxx = this.Location.X;
			int yyy = this.Location.Y;
			string x1 = xxx.ToString("0");
			string y1 = yyy.ToString("0");
			this.label1.Text = x1 + "," + y1;
		}

		private System.Windows.Forms.Label label1;
		private System.Windows.Forms.Button button1;
	}
}
    

 一番のポイントは、「this.Controls.Add(this.label1)」という部分です。これが抜けていたのが最大の原因でした。また、ここには「this」が2回出てきますが、この「this」の意味が分かってくると、「なるほどなあ」と納得できるようになりました。

 わかってみれば、いろいろなことがどんどんできるようになるのは、プログラミングも数学も一緒です。さっそく、次の課題に取り掛かろうと思います。

f:id:takase_hiroyuki:20191123160855p:plain