komoto / エンジニアブログ

IT4年目の者がプログラミングやIT技術について情報発信します。

【.NET】ボタンクリックで入力フォーム部品を規則的に増やす

環境

はじめに

特定のボタンをクリックすると、入力フォームの部品を規則的に増やす方法について説明します。
ここでは下図のようなフォームで「プログラムの追加」ボタンをクリックすると、ラベル・テキストボックス・参照ボタンの一式を規則的に下に増やしたいという想定で話を進めます。

f:id:tkmt-hrkz:20200809135103p:plain

Form.cs[Design]の設定

まずはフォームのデザイン側の設定をしていきます。
デザイン側での設定は

  • 増加させる部品の親要素(コンテナやフォームウィンドウ)のスクロール設定
  • 要素(コンポーネント)の名前付け

の2点を行います。
部品を増やしていくと親要素の表示範囲を超えていくことが予想されますので、親要素にはスクロールできるように設定します。
私の場合、Panelというコンテナの中にこの一式を配置しているので、このPanelをスクロールできるようにします。
下のように親要素(コンポーネント)のプロパティの設定を変更して下さい。

コンポーネント プロパティ
増加させたい部品の親要素(コンテナまたはフォームウィンドウ) AutoScroll True

Nameは自分が分かりやすい識別子をつけてください。
ここでは下のようにNameを設定しています。

コンポーネント Name
1 「プログラムを追加」ボタン addProgButton
2 「プログラム名」ラベル prognameLabel1
3 「パス」ラベル pathLabel1
4 「プログラム名」テキストボックス prognameTextBox1
5 「パス」テキストボックス pathTextBox1
6 「参照」ボタン progRefeButton1
7 親要素のパネル allprogPanel

f:id:tkmt-hrkz:20200809142816p:plain

Form.csのコーディング

Form.csのコードは次のようになります。
上のName表と対応しているので合わせて見てください。

クリックイベントの処理の流れは以下の通りです。
クリック回数のカウント

部品一式の情報を設定(Name属性、表示するテキスト、表示位置、既存コンポーネントと新規コンポーネントの距離)

設定した情報からコンポーネントを生成する

//「プログラムを追加」ボタンのクリックイベント
private void addProgButton_Click(object sender, EventArgs e)
  {
    numberofAPBClicks++; //クリック回数のカウント、同クラスのメンバ変数

    //prognameLabel
    string PNLABEL_NAME = $"prognameLabel{numberofAPBClicks+1}";
    string PNLABEL_TEXT = $"{numberofAPBClicks+1}. プログラム名";
    //既存ラベルと新規ラベルの距離
    const int PNLABEL_OFFSET = 100; 
    int[] PNLABEL_LOCATE = {
      prognameLabel1.Location.X, //X座標
      PNLABEL_OFFSET * numberofAPBClicks + allProgPanel.AutoScrollPosition.Y //Y座標
    };

    //pathLabel
    string PATHLABEL_NAME = $"pathLabel{numberofAPBClicks+1}";
    const string PATHLABEL_TEXT = "パス";
    const int PATHLABEL_OFFSET = 100;
    int[] PATHLABEL_LOCATE = {
      pathLabel1.Location.X, //X座標
      PATHLABEL_OFFSET * numberofAPBClicks + allProgPanel.AutoScrollPosition.Y //Y座標
    };

    //prognameTextBox
    string PNBOX_NAME = $"prognameTextBox{numberofAPBClicks+1}";
    const int PNBOX_OFFSET = 100; //テキストボックス間の距離(Y)
    const int PNBOX_FIRST_OFFSET = 28; //Panelと最上部のテキストボックスとの距離(Y)
    int[] PNBOX_LOCATE = { 
      prognameTextBox1.Location.X, //X座標
      PNBOX_OFFSET * numberofAPBClicks + PNBOX_FIRST_OFFSET + allProgPanel.AutoScrollPosition.Y //Y座標
    };
    int[] PNBOX_SIZE = {
      prognameTextBox1.Size.Width, //テキストボックス幅
      prognameTextBox1.Size.Height //テキストボックス高さ
    };

    //pathTextBox
    string PATHBOX_NAME = $"pathTextBox{numberofAPBClicks+1}";
    const int PATHBOX_OFFSET = 100;
    const int PATHBOX_FIRST_OFFSET = 28; //Panelと最上部のテキストボックスとの距離(Y)
    int[] PATHBOX_LOCATE = {
      pathTextBox1.Location.X, //X座標
      PATHBOX_OFFSET * numberofAPBClicks + PATHBOX_FIRST_OFFSET + allProgPanel.AutoScrollPosition.Y //Y座標
    };
    int[] PATHBOX_SIZE = {
      pathTextBox1.Size.Width, //テキストボックス幅
      pathTextBox1.Size.Height //テキストボックス高さ
    };

    //progRefeButton
    string PRBUTTON_NAME = $"progRefeButton{numberofAPBClicks+1}";
    const string PRBUTTON_TEXT = "参照";
    int PRBUTTON_TAG = numberofAPBClicks + 1;
    const int PRBUTTON_OFFSET = 100;
    const int PRBUTTON_FIRST_OFFSET = 28; 
    int[] PRBUTTON_LOCATE ={
      progRefeButton1.Location.X,
      PRBUTTON_OFFSET * numberofAPBClicks + PRBUTTON_FIRST_OFFSET + allProgPanel.AutoScrollPosition.Y
    };
    int[] PRBUTTON_SIZE ={
    progRefeButton1.Size.Width,
    progRefeButton1.Size.Height
    };

  createLabel(PNLABEL_NAME, PNLABEL_TEXT, PNLABEL_LOCATE);
  createLabel(PATHLABEL_NAME, PATHLABEL_TEXT, PATHLABEL_LOCATE);
  createTextBox(PNBOX_NAME, PNBOX_LOCATE, PNBOX_SIZE);
  createTextBox(PATHBOX_NAME, PATHBOX_LOCATE, PATHBOX_SIZE);
  createButton(PRBUTTON_NAME, PRBUTTON_TEXT, PRBUTTON_TAG, PRBUTTON_LOCATE, PRBUTTON_SIZE);
}


//ラベルを生成するメソッド
//引数にはName属性、表示されるテキスト、ラベルの表示位置を渡す
private void createLabel(string name, string text, int[] locate)
{
  //ラベルのインスタンス生成
  Label label = new Label();
  //プロパティ設定
  label.Name = name;
  label.Location = new Point(locate[0], locate[1]);
  label.Text = text;
  //ラベルをパネルの子要素として追加
  allProgPanel.Controls.Add(label);
}

//テキストボックスを生成するメソッド
//引数にはName属性、ボックスの表示位置、ボックスの大きさを渡す
private void createTextBox(string name, int[] locate, int[] size)
{
  TextBox textBox = new TextBox();
  textBox.Name = name;
  textBox.Location = new Point(locate[0], locate[1]);
  textBox.Size = new Size(size[0], size[1]);
  allProgPanel.Controls.Add(textBox);
  return textBox;
}

//ボタンを生成するメソッド
//引数にはName属性、ボタンに表示されるテキスト、ボタンの表示位置、ボタンの大きさを渡す
private void createButton(string name, string text, int[] locate, int[] size)
{
  Button button = new Button();
  button.Name = name;
  button.Text = text;
  button.Location = new Point(locate[0], locate[1]);
  button.Size = new Size(size[0], size[1]);
  button.Click += progRefeButton_Click;
  allProgPanel.Controls.Add(button);
}

補足

要素(コンポーネント)のName属性とは

要素のName属性について説明しておきます。
f:id:tkmt-hrkz:20200809201027p:plain:w300

Name属性を指定することでコーディングをする際に、その指定したName値で要素のプロパティにアクセスしたり、各種イベント(クリックイベントなど)を検知したりできます。
なおデフォルトでは、ラベルの場合はlabel1、テキストボックスの場合はtextBox1などと設定されています。

例えば、label1.text = "Hello World!";でプログラム上でラベルのテキストを変更できますし、label1.BackColor = Blackなどとすることでラベルの背景色を変更できます。
アクセスできるプロパティや呼び出すことができるメソッド、設定できるイベントなどの詳細はこちら(Labelの場合)を確認してください

【.NET Core】ToolStripのクリックイベントでItemコンポーネントを取得する

環境

はじめに

下図のようにToolStripコンテナを配置し、その子にボタンを置きました。
そして、そのボタンのクリックイベントを実装しようとしましたが、ToolStripの子であるボタンにはイベントが設定できません。
代わりに、ToolStripのItemClickイベントというものが有効化されますが、引数のsenderにはToolStripが入ってしまいます。
本当はボタンが入っていることを期待していたのに・・・。

f:id:tkmt-hrkz:20200801235347p:plain:w200

そこで、クリックしたボタンを同じItemClickイベントで取得する方法を説明します。
結論から言うと、ToolStrip内のItemを取得することは非常に簡単でした。

e.ClickedItemで取得できる

ボタンなどのクリックされたItemは、イベントハンドラーメソッドの第2引数であるToolStripItemClickedEventArgs eClickedItemプロパティに格納されています。
なので、e.ClickedItemでクリックされたItemを取得できます。

ToolStriptItemClickedEventArgsクラスはその名の通り、コンストラクタにクリックされたItemを受け取りインスタンス生成します。
そして、そのクリックされたItemはClickedItemプロパティに設定されます。
ToolStriptItemClickedEventArgsクラスについて、詳しくは公式ドキュメントをご覧ください。

例えば上の画像のようにToolStrip内に複数ボタンを配置してそれぞれで異なる処理をしたい場合だと

private void toolStrip1_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
{
    Console.WriteLine(e.ClickedItem.GetType()); //クリックされたItemの型を表示   
    var itemType = e.ClickedItem.GetType();   
    var item = e.ClickedItem as itemType; //クリックされたItemの取得   
    switch (item.Tag) //Itemに設定したTagによって分岐、nameなどでも可   
    {   
        case ○○:   //Itemごとに分岐させ処理する
            break;

        case ○○:   
            break;
    }
}

という風に書けばOKです。

【VSCode】便利なショートカット

はじめに

普段使っているVSCodeのショートカットをまとめました。
目的ごとにグループ分けしているので、非効率だと感じる作業に合わせて読んでいただければ幸いです。
環境はWindowsです。 Macの方は、Ctrl → Command, Alt → Optionに読み替えてください。

目次

  1. ファイル操作
    1. 新規作成
    2. ファイルを開く
    3. 名前を付けて保存
    4. 上書き保存
    5. すべてのファイルを上書き保存
  2. 表示ウィンドウとレイアウトの変更
    1. ターミナル(シェル)起動
    2. コマンドパレット起動
    3. 左サイドバー最小化
    4. 設定メニュー表示
  3. コード編集
    1. 次行に改行を入れる
    2. 前行に改行を入れる
    3. 矢印キーの方向へコードを移動
    4. 矢印キーの方向へコードをコピー
    5. コメント化
    6. 次行を一括選択
    7. 行ごとカット
    8. 行ごとコピー
    9. 同一単語の選択
    10. カーソルを追加
    11. 矢印キー方向にカーソルを追加
  4. 検索と置換
    1. 任意の単語を検索
    2. 任意の単語を置換

1. ファイル操作

動作 キー
新規作成 Ctrl+N
ファイルを開く Ctrl+O
名前を付けて保存 Ctrl+Shift+S
上書き保存 Ctrl+S
すべてのファイルを保存 Ctrl+Alt+S

VSCodeに限らずどのソフトでもよく使うショートカットです。
たくさんのファイルを編集したときには、Ctrl+Alt+S保存のし忘れをなくせます。

2. 表示ウィンドウとレイアウトの変更

動作 キー
ターミナル(シェル)起動 Ctrl+@
コマンドパレット起動 Ctrl+Shift+P
左サイドバー最小化 Ctrl+B
設定メニュー表示 Ctrl+,

ターミナルを起動することでコマンドを打てるようになるので、Web開発などでよく使用します。
ターミナルからフレームワークのコマンドを打ち、インストールしたりサーバを起動させることなどができます。 サーバサイドのエンジニアであればよく使うのではないでしょうか。

コマンドパレットVSCodeのあらゆる機能から実行したいコマンドなどを検索し実行するときに使用します。
例えば、上記で上げたショートカット動作も検索できますし、コードのコンパイルやデバック・実行、VSCodeのテーマの変更など、実に様々なことができます。

3. コード編集

動作 キー
次行に改行を入れる Ctrl+Enter
前行に改行を入れる Ctrl+Shift+Enter
矢印キーの方向へ行を移動 Alt+矢印キー
矢印キーの方向へ行をコピー Alt+Shift+矢印キー
コメント化 Ctrl+/
次行を一括選択 Ctrl+L
行ごとカット Ctrl+X
行ごとコピー Ctrl+C
同一単語の選択 Ctrl+D
カーソル追加 Alt+左クリック
矢印キー方向にカーソル追加 Ctrl+Alt+矢印キー

Ctrl+X, Ctrl+Cについてはカーソルを任意の行に置いた状態でCtrl+X, Ctrl+Cを入力することで行ごとにカット・コピーができます。

4. ワード検索と置換

動作 キー
任意の単語を検索・置換 Ctrl+F

置換方法を次の通りです。 f:id:tkmt-hrkz:20200731161024p:plain f:id:tkmt-hrkz:20200731161028p:plain

【Github】Visual StudioとGithubを連携する

はじめに

Visual Studioを使ってデスクトップアプリを開発しようと思ったので、Visual StudioGithubの連携方法を残しておきます。
思った以上に簡単ですぐに連携することができました。

目次

  1. 環境
  2. Github Extention for Visual Studioのインストール
  3. リポジトリと作業ディレクトリの作成
  4. プロジェクトフォルダの作成
  5. 補足(エラー対応など)

0. 環境

Visual Studio 2017でもGithubとの連携はできましたので、2017をお使いの方も大丈夫です。
少しメニュー等が異なるかもしれませんが同じ手順でできます。

1. Github Extention for Visual Studioのインストール

Visual Studio上でGithubを使えるようにします。
拡張機能拡張機能の管理」GitHub Extension for Visual Studio

f:id:tkmt-hrkz:20200726101619j:plain

f:id:tkmt-hrkz:20200726101659p:plain

最初に出ない場合は、右枠の検索ボックスで検索してみましょう。

2. リポジトリと作業ディレクトリの作成

Github上にリポジトリを、ローカルに作業ディレクトを作成します。
「チームエクスプローラー」「作成」
「複製」ではGithubリポジトリにあるフォルダを、丸ごとローカルにコピーすることができます。

以下は「作成」をクリックした場合です。

f:id:tkmt-hrkz:20200726101719p:plain

「名前」→リポジトリ
「説明」→リポジトリの説明
「ローカルパス」→作業ディレクト
「Git無視」→バージョン管理しないもの
「ライセンス」→プログラムのライセンス

「Git無視」は、何もなければデフォルトのままで構いません。
「ライセンス」の概要についてはこちらから。

3. プロジェクトフォルダの作成

いつものようにプロジェクトフォルダソリューションファイルを作成します。

f:id:tkmt-hrkz:20200726103948p:plain

「新規作成」をクリックしたら、いつものように開発するものに合わせてプロジェクトを選択しましょう。
これで開発の準備ができました。
それでは開発を始めましょう!

補足

Git管理でエラーが出る時の対処法

Git for Windowsをインストールしましょう。

Git管理から除外したいディレクトリやファイルを設定する

ローカルパスで指定したディレクトリにある.gitignoreファイルを開き、最下部(.ionide/の下)に除外したいディレクトリまたはファイルを指定しましょう。

f:id:tkmt-hrkz:20200726105724p:plain

【Windows10+Ubuntu20.04+VSCode】WSL2上のUbuntu20.04をWindows上のVSCodeで動かす

はじめに

パソコンを買い替えたり、作業パソコンが変わるたびにWindows上にUbuntuをのせる方法を調べるのが手間なので記録に残しておきます。
おまけには、個人的によく使うGCCコンパイラのインストールPythonの仮想環境構築の方法などをのせています。
Ubuntu20.04と書いていますが、利用するUbuntuはどのバージョンでも大丈夫です。

目次

  1. WSL2を有効化する
  2. Ubuntuをインストール
  3. Windows10上のVSCodeUbuntuを操作する
  4. おまけ

1. WSL2を有効化する

1.1 スタートメニュー上で右クリックし、アプリと機能をクリック
f:id:tkmt-hrkz:20200716230002p:plain:h300

1.2 プログラムと機能をクリックし、Windowsの機能の有効化または無効化をクリック
f:id:tkmt-hrkz:20200716230737p:plain:h300

1.3 Windows Subsystem for Linuxにチェックを入れる
f:id:tkmt-hrkz:20200716231055p:plain:h300

1.4 スタートメニューから設定⚙をクリックし、更新とセキュリティの開発者向けをクリックし、開発者モードを選択する

2. Ubuntuをインストールする

2.1 スタートメニュー横の検索バーにMicrosoft Storeと入力し、Microsoft Storeを開く
f:id:tkmt-hrkz:20200717170548p:plain:h300

2.2 Microsoft Storeの検索バーにUbuntuと入力し、Ubuntuをインストール f:id:tkmt-hrkz:20200717171601p:plain:h300

バージョンはお好みで良いですが、LTSと付いているものをお勧めします。
LTSが付いているUbuntuはサポート期間が2~3年と長いため、頻繁に環境を移行せずに済みます。
対して付いていないものは数か月と短いので、特に理由がないのであればLTSをインストールしましょう。

2.3 インストール完了後スタートメニュー横の検索バーでUbuntuと入力し、Ubuntuを起動 f:id:tkmt-hrkz:20200717172214p:plain:h300

2.4 Ubuntu起動後、ユーザ名パスワードを入力

3. Windows10上のVSCodeUbuntuを操作する

VS Codeのインストールは省略します。

3.1 VS Codeを起動

3.2 extensions(Ctrl+Shift+X)をクリック
その後、検索バーにRemote-WSLと入力し、Remote-WSLをインストール
f:id:tkmt-hrkz:20200717173221p:plain:h300

3.3 VS Code再起動
その後、左下の緑色のボタン(><)をクリックし、Remote-WSL:New Windowをクリック
f:id:tkmt-hrkz:20200717173756p:plain:h300

新しくウィンドウが表示されるので、その新ウィンドウで左下の緑色のボタン(><)の横にWSL- Ubuntu○○と表示されていれば成功です。

これでVS Codeのターミナルを開くとUbuntuのシェルと繋ぐことができました。

VS Codeのターミナルを開くショートカットキーはCtrl+@です。

おまけ

初期設定(リポジトリの変更とパッケージのアップデート)

リポジトリの変更

データを取りに行くサーバを変更する(日本にあるサーバに変更)
sudo sed -i -e 's%http://.*.ubuntu.com%http://ftp.jaist.ac.jp/pub/Linux%g' /etc/apt/sources.list

パッケージのアップデート

アップデートは自動更新されないので、次の2つのコマンドを実行して日々更新し続ける。
sudo apt update
sudo apt upgrade

Windows側でUbuntuのファイルを管理する

Windows側でエクスプローラーを開き、ディレクタが表示される所に\wsl$を入力して決定 f:id:tkmt-hrkz:20200717175351p:plain:h300

あとは、Ubuntuのフォルダへのショートカットを作成してデスクトップとかに置いておけば、楽にアクセスできます。

C/C++言語をコンパイル可能にする(GCCのインストール)

以下のコマンドをUbuntu上で実行すれば、インストールできます。
Windowsコマンドプロンプトではできません)
sudo apt-get install build-essential curl file gi

コンパイル
C → gcc your_programname.c
C++g++ your_programname.cpp
でできます。

pipとvenvをインストールして、Pythonの仮想環境を構築する

以下のコマンドをUbuntu上で順に実行。
UbuntuにはデフォルトでPythonが入っているので、インストールは不要です。

  1. sudo apt install python3-pip
  2. sudo apt install python3-venv
  3. python3 -m venv your_virtualname
  4. source your_virtualname/bin/activate

これでPythonの仮想環境を構築し、4つ目のコマンドで作成した環境に入ることができます。
出るときは、deactivateで出られます。

仮想環境の方にはpipはすでに入っているみたいなので、インストールは不要です。
あとは仮想環境上でpython3 -m pip install package_nameを実行すれば、必要なパッケージをインストールできます。
これで開発するアプリごとに開発環境を整備できます。

【Generics】任意の型を受け取り処理をする

最近、テンプレートやジェネリクスを知る機会がありました。これまではある関数やクラスに特定の型を指定して処理をしていました。
しかしこれでは、その特定の型以外が渡された時に同じように処理できません。
キャストをすれば処理を行うことができますが、毎回キャストとかをするのは面倒ですし、あまり良くありません。

そんな時に利用できるのが、ジェネリクス(テンプレート)です。

対象読者

  • テンプレート、ジェネリックスという単語を初めて聞いた人
  • 引数の型の違いを吸収して、同じような処理を書きたいと考えている人
  • テンプレートを用いた書き方を知りたい人(C++, Kotlin)

ジェネリクス(=テンプレート)とは

ジェネリクス(テンプレート)は次のように定義されています。

Genericsとは、クラス、インターフェース、メソッドなどの「型」を「パラメータとして定義する」ことを可能にしたものです。
クラスの定義内で用いられる型を変数化し、インスタンス化しオブジェクトを生成するときまで扱う型を抽象的に表現しておき、生成時に「<」と「>」の間に具体的な型名を指定することで汎用的なクラスやメソッドを特定の型に対応づけることができる機能です。
引用サイト: Javaのジェネリクス (Generics) の使い方を現役エンジニアが解説【初心者向け】 | TechAcademyマガジン

つまりジェネリクス(テンプレート)は、特定の型に依存したコードを他の任意の型でも動作できるようにするなど、型を抽象化しコードを汎用化するために使用します。
受け取る型を制限したり、受け取った任意の型のうち型によって処理を変えたり、型によっては例外処理を行ったりすることもできます。

受け取る型を予想するのは難しいですし、その型の違いによってコードを書くのは大変ですよね。

ちなみに、ジェネリクスという言葉は言語によって異なるみたいです。

C++ → テンプレート
JavaC#、Kotlin → ジェネリクス

と呼び、意味合いも少し変わってくるようです。

テンプレートとジェネリクスの違いについてはこちら

ufcpp.net

この辺りはまだ勉強不足なので割愛させてください...

具体例

それでは簡単な具体例を挙げて考えていきます。

需要はおそらくないと思いますが、今回は引数で受け取った任意のものを3回表示するというメソッドを考えます。

言語はC++Kotlinで書いてきたいと思います。

まずはジェネリクスを使わない場合の書き方から見ていきます。

class MyClass {
public:
    void getThreeInt(int x) {
        for(int i = 0; i < 3; i++) cout << x << endl;
    }

    void getThreeStr(string str) {
        for (int i = 0; i < 3; i++) cout << str << endl;
    }
      ・
      ・
      ・
};

int main(void) {
    auto i = MyClass();
    i.getThreeInt(5); // 5 5 5

    auto str = MyClass();
    str.getThreeStr("Hello"); // Hello Hello Hello

    return 0;
}
class MyClass {
    fun getThreeInt(x: Int) {
        println(x)
        println(x)
        println(x)
    }
    fun getThreeStr(x: String){
        println(x)
        println(x)
        println(x)
    }
   ・
   ・
   ・
}

fun main(args: Array<String>) {
    val i = MyClass()
    i.getThreeInt(5) // 5 5 5

    val str = MyClass()
    str.getThreeStr("Hello") // Hello Hello Hello
}

テンプレートを使わない場合だと、受け取る引数の型ごとにメソッドを定義しておく必要が出てきます。

main関数の方で文字列をInt型に変換して渡せば、メソッドは1つで済みますがスマートでなくあまりメリットはありません。

これをテンプレートを使うと、型の違いを吸収できてとてもスッキリします。

class MyClass {
public:
    template<typename T>
    void getThree(T x) {
        for (int i = 0; i < 3; i++) cout << x << endl;
    }
};

int main(void){
    auto x = MyClass();
    x.getThree(5); // 5 5 5
    x.getThree("Hello"); // Hello Hello Hello

    return 0;
}
class MyClass<T> {
  fun getThree(x: T) {
    println(x)
    println(x)
    println(x)
  }
}

fun main(args: Array<String>) {
    val i = MyClass<Int>()
    i.getThree(5) // 5 5 5

    val str = MyClass<String>()
    str.getThree("Hello") // Hello Hello Hello
}

C++の場合はメソッドの上部にtemplate<typename T>を、Kotlinの場合はクラス宣言時にクラス名の横に<T>をつけることで、型を抽象化できクラスやメソッドを汎用化できます。

上の場合はクラスのメソッドにジェネリクスを適用していますが、クラスのメンバ変数にもジェネリクスを適用したいなら次のようにすることもできます。

template<typename T>
class MyClass {
public:
    void getThree(T x) {
        for (int i = 0; i < 3; i++) cout << x << endl;
    }

    MyClass(T member) {
        this->member = member;
    }

    T getmember() {
        return member;
    }

private:
    T member;
};

int main(void){
        auto x = MyClass<int>(2020);
        cout << x.getmember() << endl; // 2020
        auto y = MyClass<string>("Hello");
        cout << y.getmember() << endl; // Hello
    
        return 0;
}

【Markdown】はてなブログのMarkdown記法で画像サイズを変更する

デフォルトでは画像サイズが大きすぎて逆に見にくいため、Markdown記法で画像サイズを変更する方法について調べました。

画像サイズを変更するには

画像を貼り付けたらその箇所に[○○:plain]と記述されると思います。

これを[○○:plain:w300]とすれば、幅を300pxに変更できます。

高さを変更するには[○○:plain:h300]にすれば変更できます。

デフォルト[○○:plain]↓

f:id:tkmt-hrkz:20200524220312p:plain

幅300px[○○:plain:w300]↓

f:id:tkmt-hrkz:20200524220312p:plain:w300

幅600px[○○:plain:w600]↓

f:id:tkmt-hrkz:20200524220312p:plain:w600

高さ300px[○○:plain:h300]↓

f:id:tkmt-hrkz:20200524220312p:plain:h300

小さい画像を大きくすることはぼやけるのでできませんが、大きすぎる画像を小さく表示したいときは以上の方法で調整できます。