Java : WindowBuilder Java WindowBuilder から超簡易掲示板(CSVタイプ)投稿 WindowBuilder のテーブルコントロールにインターネットから JSON データを読み込んで処理するテンプレート WindowBuilder テンプレートのテーブルコントロールに MySQL のデータを表示する Eclipse 4.4 Pleiades + WindowBuilder テンプレート / アプリケーションウインドウとダイアログ / インポート手順 HttpGet クラス(ソースコード) HttpPost クラス(ソースコード) 1からのプロジェクト作成方法 Java : Android Studio tools.jar の callHttpGet のテストと include による画面再利用と HttpPost クラスで掲示板書き込み / Android Studio Android の Spinner に関するいろいろな実装と知識 / Android Studio AsyncTask を継承して、Drawable を取得する専用クラスを作成する : Android Studio Android Studio でボタンの処理を追加する4つの方法 : Android Studio 2.0 新しい Activity を追加して MainActivity より呼び出し、MainActivity に戻る処理 tools.jar を使用して MessageBox 処理 tools.jar を使用して基本的なアクションを簡単に実装する tools.jar ソースコード ( Tools.java, Tools2.java, TestArrayAdapter.java, AndroidTools.java ) Android Studio : jar の作成と実行テスト Android Studio の設定 Android Studio 予習開始!(良く使う機能・ショートカット・メニュー) Java : コンソール Java のコンソールで NAVER の RSS を取得して、title 部分を正規表現で加工して表示するサンプル java をコマンドプロンプトからビルドして実行するサンプル。( メール送信が初心者には楽しいはず ) PHP PHP で 自家製 API を作成して jQuery の簡単なコードで更新処理を行うサンプル 超簡易掲示板 : 保存タイプは CSV 超簡易掲示板 ( JSON ) : PHP PHP で HTML数値エンティティを、目的のキャラクタセットの文字列に変換する PHP で漢字スペースと通常スペースのトリム jQuery Google Chrome で音声認識の結果をブログの投稿テキストエリアに転送するブックマークレット ブックマークレット IFRAME ユニット作成ツール イラストAC用、一括タグ転送ブックマークレット Google Chrome での音声認識処理 ほぼ、Google Chrome 限定ですが Web Speech API の現時点での実装と問題点回避方法 EASELJS を使用した画像の分割と分割されたエリア毎のアニメーション / createjs.Ticker の reset と init はうまく動きませんでした EASELJS を使用した画像の縮小とトリミングと角丸マスク / 画像は new Image でイベント処理して画像サイズを取得します jQuery Columns を使って、Picasa API より アルバム一覧を表示する jquery.ajax-combobox(オートコンプリートとドロップダウンリストを組み合わせたコンボボックス) を使用して、入力可能なコンボックス( しかもリストはページャ付き ) jquery.ajax-combobox で JSON をデータに使う場合、複数項目を検索対象にする為の簡単な改造 Kintone kintone で画像を表示する / PC と スマホで少し違います。PC ではスペース項目、スマホでは、スマホ用ヘッダスペースを使用します kintone JavaScript API で ルックアップ先が更新された場合の参照元を全て更新する kintone API のトークンを使った PHP コードの注意点 kintone の開発者ライセンスを取得しました。一年有効で、見たところ4年ぐらい使えそうです その他 A 要素と CSS だけでボタンを表現する 『BUTTONS』 BUTTON 要素と CSS だけでアイコンボタンを表現する 『BUTTONS』 utf8 文字ツール の 文字参照リンクの作成方法 レンタルサーバで PHP のバージョンを 5.4 から 5.6 に変更する時の注意事項 IFRAME 内に外部の javascript を読み込んで画面を作成する / document.write での構築
2016年05月31日
Java、PHP、jQuery : 最近の記事と関連する記事のまとめ / インデックス
Java のコンソールで NAVER の RSS を取得して、title 部分を正規表現で加工して表示するサンプル
java.util.regex.Matcher java.util.regex.Pattern groupCount で取得されるのは、部分一致した数なので、() を使用しなければ、戻り値は 0 となります。また、その場合は group() で取得できますし。group(0) でも取得できます。 なので、常に pattern に一致する文字列は group(0) です。group(n) で n が 1 以上は部分一致となります。 よって、部分一致のみのループは、for( int i = 1; i <= m.groupCount(); i++ ) となります。
import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; import java.util.regex.Matcher; import java.util.regex.Pattern; public class Main { public static void main(String[] args) { Pattern p; Matcher m; int len; print("処理開始"); // NAVER の RSS String str = httpGet("http://matome.naver.jp/feed/hot"); // 部分一致の無い パターンを生成 p = Pattern.compile("<title>.+?</title>"); m = p.matcher(str); // 部分一致した数( 0 になります ) len = m.groupCount(); print( Integer.toString(len) ); while(m.find()) { // 部分一致は無いので、m.group() で パターン // に対する全体一致を取得 System.out.println(m.group()); } print("------------------------------------------"); // 部分一致のあるパターンを生成 p = Pattern.compile("<title>(.+?)</title>"); m = p.matcher(str); // 部分一致した数 ( 1になります ) len = m.groupCount(); print( Integer.toString(len) ); while(m.find()) { // m.group(0) はパターンに対する全体一致なので // 1 から始めて部分一致のみ表示 for( int i = 1; i < (len +1); i++) { System.out.println(m.group(i)); } } print("------------------------------------------"); // 部分一致のあるパターンを生成 p = Pattern.compile("(<title>)(.+?)(</title>)"); m = p.matcher(str); len = m.groupCount(); print( Integer.toString(len) ); String partsString; StringBuilder buffer; while(m.find()) { buffer = new StringBuilder(); for( int i = 1; i < (len +1); i++) { // title 開始タグ if ( i == 1) { buffer.append("『"); } // title 内容 if ( i == 2) { partsString = m.group(2); // String クラスの正規表現置換 // 文の区切り的文字で改行 partsString = partsString.replaceAll("[。、.…!?]+", "\n"); buffer.append(partsString); } // title 終了タグ if ( i == 3) { buffer.append("』"); } } print(buffer.toString()); print(""); } } // ******************************** // データ表示用 // ******************************** public static void print( String s ) { System.out.println(s); } // ******************************** // static void main より呼び出す為の // static な インターネットアクセス関数 // ******************************** public static String httpGet( String s ) { String result = ""; try { URL url = new URL(s); HttpURLConnection http = (HttpURLConnection)url.openConnection(); http.setRequestMethod("GET"); http.connect(); InputStream is = http.getInputStream(); InputStreamReader isr = new InputStreamReader(is,"UTF8"); BufferedReader br = new BufferedReader(isr); String line_buffer; StringBuilder sb = new StringBuilder(); while(null != (line_buffer = br.readLine() )) { sb.append(String.format("%s\n",line_buffer)); } br.close(); isr.close(); is.close(); result = sb.toString(); } catch (Exception e) { e.printStackTrace(); } return result; } }
2016年05月30日
PHP で 自家製 API を作成して jQuery の簡単なコードで更新処理を行うサンプル
以下のような『社員マスタ』を使って、まず PHP のコードを用意します。
create table `社員マスタ` ( `社員コード` varchar(4) ,`氏名` varchar(50) ,`フリガナ` varchar(50) ,`所属` varchar(4) ,`性別` int ,`作成日` datetime ,`更新日` datetime ,`給与` int ,`手当` int ,`管理者` varchar(4) ,`生年月日` datetime ,primary key(`社員コード`) )
全てのデータが空でも、SQL 的にはエラーは起こりません。但し、エラーが発生した場合は、kj にエラーメッセージをセットし、furi に 更新 SQL をセットします。 dbdata_update_json.php
<?php header( "Content-Type: application/json; Charset=utf-8" ); header( "pragma: no-cache" ); header( "Expires: Wed, 31 May 2000 14:59:58 GMT" ); header( "Cache-control: no-cache" ); header( "Access-Control-Allow-Origin: *" ); // *********************************************** // 初期設定 // *********************************************** if ( $_GET["sdata"] == "" ) { $_GET["sdata"] = "{}"; } $data = json_decode($_GET["sdata"]); $data->type = "UPDATE"; // *********************************************** // 利用変数設定 // *********************************************** $json_type = JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT; $db_data_type = MYSQLI_ASSOC; $_GET["sdata"] = str_replace("'","''",$_GET["sdata"]); // ----------------------------------------------- // *********************************************** // 接続情報 // *********************************************** $server = 'localhost'; $db_name = 'lightbox'; $user = 'root'; $password = 'trustno1'; // ----------------------------------------------- // *********************************************** // 接続 // *********************************************** $connect = @ new mysqli($server, $user, $password, $db_name); if ($connect->connect_error) { $data->status = "ERROR"; $data->kj = "接続エラーです"; print json_encode($data,JSON_UNESCAPED_UNICODE|JSON_PRETTY_PRINT); exit(); } $connect->set_charset("utf8"); // ----------------------------------------------- // *********************************************** // NULL 項目の対応 // *********************************************** if ($data->kyuyo == '') { $data->kyuyo = "null"; } if ($data->teate == '') { $data->teate = "null"; } if ($data->seibetu == '') { $data->seibetu = "0"; } if ($data->birth == '') { $data->birth = "null"; } else { $data->birth = "'{$data->birth}'"; } // ----------------------------------------------- // *********************************************** // 更新 SQL // *********************************************** $query = <<< QUERY update `社員マスタ` set `氏名` = '{$data->kj}' ,`フリガナ` = '{$data->furi}' ,`性別` = {$data->seibetu} ,`給与` = {$data->kyuyo} ,`手当` = {$data->teate} ,`所属` = '{$data->syozoku}' ,`管理者` = '{$data->kanri}' ,`生年月日` = $data->birth where `社員コード` = '{$data->scode}' QUERY; // ----------------------------------------------- // *********************************************** // クエリ実行 // *********************************************** $result = $connect->query($query); if ( !$result ) { $data->status = "ERROR"; $data->kj = "クエリに誤りがあります"; $data->furi = $query; print json_encode( $data, $json_type ); exit(); } else { $data->status = "SUCCESS"; } // ----------------------------------------------- // *********************************************** // 接続解除 // *********************************************** $connect->close(); // ----------------------------------------------- // *********************************************** // 結果 // *********************************************** print json_encode($data,JSON_UNESCAPED_UNICODE|JSON_PRETTY_PRINT); // ----------------------------------------------- ?>
PHP で Access-Control-Allow-Origin: * をセットしているので、どこに置いても JavaScript から呼び出し可能です。 以下のような簡単なコードで更新のテストが可能です。
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script> <script> $(function(){ var sdata = {}; $("#build").on("click", function(){ $(".entry").find("input").each(function(idx){ sdata[$(this).prop("id")] = $(this).val(); }); $("#result").text( JSON.stringify(sdata,null," ") ); }); $("#send").on("click", function(){ var sdata = encodeURIComponent( $("#result").text() ); $.get("http://localhost/log/easy_board/dbdata_update_json.php?sdata="+sdata ,function(data){ console.dir(data); }); }); }); </script> <input id="build" type="button" value="JSON 文字列作成"> <input id="send" type="button" value="サーバ送信"> <pre class="entry"> <input id="scode"> scode <input id="kj"> kj <input id="furi"> furi <input id="seibetu"> seibetu <input id="kyuyo"> kyuyo <input id="teate"> teate <input id="syozoku"> syozoku <input id="kanri"> kanri <input id="birth"> birth </pre> <pre id="result"> </pre>
tools.jar の callHttpGet のテストと include による画面再利用と HttpPost クラスで掲示板書き込み / Android Studio
tools.jar libs フォルダに保存して、右クリックから Add as Library を実行すると参照可能になります。 ▼ ソースコード Tools, Tools2, TestArrayAdapter, AndroidTools.java ) tools.jar は、気軽にアンドロイドのアプリケーションのテストができるように作成したライブラリです。Android の動作テストはとても時間がかかり、結構デリケートな部分が多いので、できればこのライブラリの中にあるような内容は適当にしたい事が多くあります。特に、商品では無く他人への説明や他の機能の習熟目的で使用し、自分自身は学生をターゲットにしており、授業で使用しています。 それらの中でも、特に面倒くさいのがインターネットに対するアクセスです。tools.jar では、GET アクセスは実装していますが、POST アクセスは実装していません。POST には POST するだけの意味がある時にしか利用されないので、ここで HttpPost クラスをソースで実装して 超簡易掲示板(CSV) を使って投稿するテストをしています。 画面を二つ使い、include でボタン3つの定義を両方で利用しています。 (Android Studio では、新しいアクティビティを作成すると、AndroidManifest も自動的に書き換えられます。) ※ 具体的なタイムアウト時の処理は行っていません(何も起きません) MainActivity.java 次画面2ボタンでインターネットよりテキストデータを取得し(tools.jar の callHttpGet)、次画面に引き渡してテキストエリアに表示します。そこで投稿ボタンで実際の WEB に対する投稿(HttpPost) となります。
package lightbox.may.toolstest; import android.content.Intent; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.TextView; import jp.android.work.Tools; public class MainActivity extends AppCompatActivity { // テキストビュー( 表示用 ) private TextView tv; // ***************************************** // 初期画面構築 // ***************************************** @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 表示部分のインスタンスの取得 tv = (TextView) MainActivity.this.findViewById(R.id.textView); // ***************************************** // ボタン1 の設定 // ***************************************** Button btn1 = (Button)MainActivity.this.findViewById(R.id.button); btn1.setText("次画面"); MainActivity.this.findViewById(R.id.button).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 呼び出し番号 (1) Tools.callActivity(MainActivity.this,Main2Activity.class, 1); } }); // ***************************************** // ボタン2 の設定 // インターネットのデータを次画面に引き渡す // ***************************************** Button btn2 = (Button)MainActivity.this.findViewById(R.id.button2); btn2.setText("次画面2"); btn2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Tools.callHttpGet( "http://toolbox.winofsql.jp/kumonoito.txt", "utf-8", new Tools.OnAsyncTaskListener() { @Override public void onAsyncTaskListener(String s) { Intent intent = new Intent(MainActivity.this, Main2Activity.class); intent.putExtra("requestCode",2); intent.putExtra("text",s); startActivityForResult(intent, 2); } }); } }); // ***************************************** // ボタン3 の設定 // ブラウザ呼び出し // ***************************************** Button btn3 = (Button)MainActivity.this.findViewById(R.id.button3); btn3.setText("ブラウザ"); btn3.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Tools.callBrowser(MainActivity.this,"http://weather.yahoo.co.jp/weather/jp/27/6200.html"); } }); } // ***************************************** // 第二画面から戻って来た時の処理 // onActivityResult // ***************************************** @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); Log.i("lightbox", String.format("呼び出し番号 : %d", requestCode) ); Log.i("lightbox", String.format("戻り番号 : %d", resultCode) ); if ( data != null ) { // 戻りデータの取得 String returnData = data.getStringExtra("returnData"); if (returnData != null) { // テキストビューに表示 tv.setText(returnData); } } } }
Main2Activity.java
package lightbox.may.toolstest; import android.content.Intent; import android.graphics.Color; import android.os.AsyncTask; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.EditText; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; import java.util.Map; public class Main2Activity extends AppCompatActivity { // 呼び出し番号 private int requestCode; // テキストエリア private EditText et; // ***************************************** // 初期画面構築 // ***************************************** @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main2); // 入力部分のインスタンスの取得 et = (EditText) Main2Activity.this.findViewById(R.id.editText); // ***************************************** // 前の画面から送られたデータの取得 // ***************************************** Intent intent = getIntent(); // 1) テキストデータ String text = intent.getStringExtra("text"); if ( text != null ) { et.setText(text); } // 2) 整数データ requestCode = intent.getIntExtra("requestCode", 0); if ( requestCode != 0 ) { Log.i("lightbox", String.format("呼び出し番号 : %d", requestCode)); } // ***************************************** // ボタン1 の設定 // 整数のみを戻す // ***************************************** Button btn1 = (Button)Main2Activity.this.findViewById(R.id.button); btn1.setText("戻る"); btn1.setTextColor(Color.parseColor("#f84848")); btn1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 戻り値のみ返す setResult(100); // 第二画面を終了して初期画面に戻る finish(); } }); // ***************************************** // ボタン2 の設定 // ***************************************** Button btn2 = (Button)Main2Activity.this.findViewById(R.id.button2); btn2.setText("投稿"); btn2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(); setResult(200,intent); // エミュレータから PC の WEBサーバへアクセスする場合 // String url = "http://10.0.2.2/log/easy_board/csvtype/board.php"; // 実機を PC につないで、WiFi 接続を可能にした場合 // 192.168.1.2 は PC の IPアドレス String url = "http://192.168.1.2/log/easy_board/csvtype/board.php"; Map<String,String> url_param = new HashMap<String,String>(); url_param.put("url", url); Map<String,String> param = new HashMap<String,String>(); param.put("send", "send"); param.put("subject", "テスト投稿"); param.put("name", "ウインドウビルダー"); param.put("text", et.getText().toString()); SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); param.put("datetime", sdf.format(new Date())); new AsyncTask<Map,Void,String>(){ @Override protected String doInBackground(Map... params) { // 引数より URL 部分を取得 String url = params[1].get("url").toString(); Log.i("lightbox",url); // インターネットアクセス return HttpPost.execute(url, params[0], "utf-8"); } @Override protected void onPostExecute(String s) { Log.i("lightbox",s); finish(); } }.execute(param,url_param); } }); // ***************************************** // ボタン3 の設定 // 整数と文字列を戻す // ***************************************** Button btn3 = (Button)Main2Activity.this.findViewById(R.id.button3); btn3.setText("戻る+データ"); btn3.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 渡す値 Intent intent = new Intent(); intent.putExtra("returnData", et.getText().toString()); // 戻り値と値を返す setResult(300, intent); finish(); } }); } }
ボタン部分の画面パーツ( action_buttons.xml ) デザインタブから <include> を選択できます。クリックすると参照可能な画面一覧が表示されるので、選択するとカーソルがコントロールを選択した状態になり、デザイン画面やツリーにドロップ可能になります。
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Button1" android:id="@+id/button" android:layout_weight="1" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Button2" android:id="@+id/button2" android:layout_weight="1" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Button3" android:id="@+id/button3" android:layout_weight="1" /> </LinearLayout>
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="lightbox.may.toolstest.MainActivity"> <include android:layout_width="match_parent" android:layout_height="wrap_content" layout="@layout/action_buttons" android:id="@+id/include2"/> <ScrollView android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/scrollView" android:layout_alignParentStart="true" android:layout_below="@+id/include2"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/textView"/> </ScrollView> </RelativeLayout>
activity_main2.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="lightbox.may.toolstest.Main2Activity"> <include android:layout_width="match_parent" android:layout_height="wrap_content" layout="@layout/action_buttons" android:id="@+id/include"/> <EditText android:layout_width="match_parent" android:layout_height="match_parent" android:inputType="textMultiLine" android:ems="10" android:id="@+id/editText" android:textSize="20dp" android:layout_below="@+id/include" android:layout_alignParentStart="true" android:gravity="top|left"/> </RelativeLayout>
2016年05月29日
Java WindowBuilder から超簡易掲示板(CSVタイプ)投稿
HttpPost クラスのテストです。 超簡易掲示板(CSV)は以下からダウンロードできます。 超簡易掲示板 : 保存タイプは CSV WindowBuilder 側では、複数行のテキストフィールドを使って単純投稿です。
import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; import java.util.Map; import javax.swing.JOptionPane; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; import org.eclipse.jface.window.ApplicationWindow; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; import com.google.gson.Gson; public class TopWindow extends ApplicationWindow { private int width = 600; private int height = 440; private Gson gson; private Text text; // ********************************* // コンストラクタ // ********************************* public TopWindow() { super(null); } // ********************************* // コントロールの追加 // ※ Design での変更が反映されます // ********************************* @Override protected Control createContents(Composite parent) { Composite container = new Composite(parent, SWT.NONE); // ボタンの定義 Button button = new Button(container, SWT.NONE); // ボタンのイベント button.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { // プログラム開始時に実行すると、固まるので直前に try { UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e1) { e1.printStackTrace(); } // 確認ダイアログ( OK_CANCEL )の表示 int result = JOptionPane.showConfirmDialog( null, "データを POST しますか", "確認", JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE); // OK を選択 if ( result == JOptionPane.OK_OPTION ) { // POST データ Map<String,String> param = new HashMap<String,String>(); param.put("send", "send"); param.put("subject", "テスト投稿"); param.put("name", "ウインドウビルダー"); param.put("text", text.getText()); SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); param.put("datetime", sdf.format(new Date())); // インターネットアクセス String data = HttpPost.execute("http://localhost/log/easy_board/csvtype/board.php", param, "utf-8"); // データを取得できた if ( !data.equals("") ) { // コンソールで確認 System.out.println(data); } } } }); button.setBounds(10, 10, 81, 28); button.setText("実行"); text = new Text(container, SWT.BORDER | SWT.MULTI); text.setBounds(10, 44, 483, 341); return container; } // ********************************* // アプリケーションの開始 // ********************************* public static void main(String args[]) { try { // 自分自身(TopWindow) の作成 TopWindow window = new TopWindow(); // open を実行したら、Window を閉じるまで次の行を実行しない window.setBlockOnOpen(true); window.open(); // Window を閉じたら以下を実行してアプリケーションを終了する Display.getCurrent().dispose(); } catch (Exception e) { e.printStackTrace(); } } // ********************************* // Window の初期設定 // ********************************* @Override protected void configureShell(Shell newShell) { super.configureShell(newShell); // タイトルの設定 newShell.setText("タイトル文字列"); } // ********************************* // Window サイズの初期設定 // ********************************* @Override protected Point getInitialSize() { // プライベート変数を使用してウインドウサイズを決定しています return new Point(width, height); } }
プロジェクトを一から作る方法
超簡易掲示板 : 保存タイプは CSV
board.php、model.php、view.php の 3 ファイルで動作します。json.php が同梱されていますが、出力ファイルである board.csv を JSON 形式で取得する為のコードです。( JavaScript からアクセスする場合は、header( "Access-Control-Allow-Origin: *" ); を追加して下さい ) 他のアプリケーションからのアクセスを簡単にテストできる仕様になっています。 board.php
<?php // ************************************** // php.ini の output_buffering をチェックして // 有効になっていた場合は、header の前に出力可能です // ************************************** // ************************************** // 通常の HTML として出力します // ************************************** header( "Content-Type: text/html; Charset=utf-8" ); // ************************************** // キャッシュを無効にするヘッダ // ※ いろいろあるのは念のため // ************************************** header( "pragma: no-cache" ); header( "Expires: Wed, 31 May 2000 14:59:58 GMT" ); header( "Cache-control: no-cache" ); // ************************************** // 関数の定義を読み込みます // ************************************** require_once("model.php"); // ************************************** // $_POST['send'] != "" は送信ボタンが // クリックされた事を示します // さらに、テキストエリアに何か入力され // た場合に処理を行います // ************************************** $_POST['text'] = preg_replace( "/^[ \s]+/u", "", $_POST['text'] ); $_POST['text'] = preg_replace( "/[ \s]+$/u", "", $_POST['text'] ); if ( $_POST['send'] != "" && $_POST['text'] != "" ) { // データの書き込み処理 post_data(); } // ************************************* // データの表示処理 // ************************************* disp_data(); // ************************************** // ▼ 以下は画面です。$log_text を // 埋め込んでいます // ************************************** require_once("view.php"); ?>
model.php
<?php // ************************************** // データの書き込み処理 // ************************************** function post_data() { // データを一括読み込み $log_text = @file_get_contents("board.csv"); // ************************************** // 本文中の改行コードを "\n" という // 文字列に変換しています // ************************************** $_POST['text'] = str_replace("\r\n","\\n",$_POST['text']); $_POST['text'] = str_replace("\n","\\n", $_POST['text'] ); $_POST['text'] = str_replace("\r","\\n", $_POST['text'] ); // HTML 要素を無効にする $_POST['text'] = str_replace("<","<",$_POST['text']); $_POST['text'] = str_replace(">",">",$_POST['text']); // HTML 要素を無効にする $_POST['subject'] = str_replace("<","<",$_POST['subject']); $_POST['subject'] = str_replace(">",">",$_POST['subject']); $_POST['name'] = str_replace("<","<",$_POST['name']); $_POST['name'] = str_replace(">",">",$_POST['name']); // シングルクォートとダブルクォートとカンマ $_POST['text'] = str_replace("'","'",$_POST['text']); $_POST['text'] = str_replace("\"",""",$_POST['text']); $_POST['text'] = str_replace(",",",",$_POST['text']); // シングルクォートとダブルクォートとカンマ $_POST['subject'] = str_replace("'","'",$_POST['subject']); $_POST['subject'] = str_replace("\"",""",$_POST['subject']); $_POST['subject'] = str_replace(",",",",$_POST['subject']); $_POST['name'] = str_replace("'","'",$_POST['name']); $_POST['name'] = str_replace("\"",""",$_POST['name']); $_POST['name'] = str_replace(",",",",$_POST['name']); $log_wk = "{$_POST['text']},{$_POST['subject']},{$_POST['name']},{$_POST['datetime']}"; // ************************************** // 前回データとの境界に改行コードを // 設定しています // ************************************** $log_text = $log_wk . "\n" . $log_text; // 書き込み file_put_contents("./board.csv", $log_text ); // GET メソッドで再表示します header( "Location: board.php" ); exit(); } // ************************************** // データの表示処理 // ************************************** function disp_data() { // 埋め込み用データを global 宣言 global $log_text; // データを一括読み込み $rows = @file("./board.csv"); // ファイルが存在しない場合 if ( $rows === false ) { $log_text = "ここに投稿データが表示されます"; return; } // 表示用の埋め込みに使用される文字列変数 $log_text = ""; foreach( $rows as $v ) { $data = explode(",", $v); // ************************************** // 本文の改行は br 要素で表現します // ************************************** $row = str_replace("\\n", "<br>\n", $data[0] ); // ************************************** // 行毎に表示 HTML を作成 // ************************************** $row = "<h3>{$data[1]}</h3>{$row}<br><span class='sb'>({$data[2]} : {$data[3]} )</span><br>"; // ************************************** // 記事の境界を hr 要素で表現します // ************************************** $row .= "<hr>\n"; // ************************************** // 表示画面全体 を作成 // ************************************** $log_text .= $row; } } ?>
行データの作成は、以下のように置き換えるとメンテナンスしやすくなります。また、この部分を別ファイルにして require するともっと使いやすくなるでしょう。
// ************************************** // 行毎に表示 HTML を作成 // ************************************** $row = <<<HTML <h3>{$data[1]}</h3> {$row}<br> <span class='sb'>({$data[2]} : {$data[3]} )</span><br> HTML;
view.php
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <script src="//ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script> <style> * { font-family: "ヒラギノ角ゴPro W3","Hiragino Kaku Gothic Pro","メイリオ",Meiryo,"MS Pゴシック",Verdana,Arial,Helvetica,sans-serif; } body { margin: 5px; } form { padding-right: 5px; } .sb { font-size: 8px; } #text { height: 100px; width: 500px; } #subject,#name { width: 400px; } @media screen and (max-width:479px) { #text { width: 100%; } #subject,#name { width: 230px; } #line_control { display: none; } } </style> <script> $( function(){ $("form").on("submit", function(){ var dateNow = new Date(); var dateString = dateNow.getFullYear() + "/" + ("0"+(dateNow.getMonth()+1)).slice(-2)+ "/" + ("0"+(dateNow.getDate())).slice(-2); var timeString = ("0"+(dateNow.getHours())).slice(-2) + ":" + ("0"+(dateNow.getMinutes())).slice(-2) + ":" + ("0"+(dateNow.getSeconds())).slice(-2); $("#datetime").val( dateString + " " + timeString ); }); }); </script> </head> <body> <h3><a href="board.php" style="color:black;">超簡易掲示板 ( CSV )</a></h3> <form method="POST"> タイトル <input type="text" id ="subject" name="subject"> <br> 名 前 <input type="text" id ="name" name="name"> <br> <textarea id ="text" name="text"></textarea> <input type="hidden" id="datetime" name="datetime"> <br> <input type="submit" name="send" value="送信"> </form> <br> <?= $log_text ?> </body> </html>
json.php
<?php // ************************************** // 通常の HTML として出力します // ************************************** header( "Content-Type: application/json; charset=utf-8" ); header( "pragma: no-cache" ); header( "Expires: Wed, 31 May 2000 14:59:58 GMT" ); header( "Cache-control: no-cache" ); // データを一括読み込み $rows = @file("./board.csv"); // ファイルが存在しない場合 if ( $rows === false || $rows[0] == "" ) { print '{ "error": "ファイルが存在しません" }'; exit(); } // 全ての行用の JSON 用クラス作成 $json = new stdClass; // 行データを格納する配列を作成 $json->item = array(); foreach( $rows as $v ) { $data = explode(",", $v); // 新しい行用のクラス作成 $board_data = new stdClass; // text プロパティに 本文をセット $board_data->text = $data[0]; // subject プロパティに タイトルをセット $board_data->subject = $data[1]; // name プロパティに 名前をセット $board_data->name = $data[2]; // subject プロパティに タイトルをセット $board_data->datetime = $data[3]; // 配列の最後に投稿データをセット array_push ($json->item, $board_data); } print json_encode($json, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); ?>
Seesaa の各ページの表示について
Seesaa の 記事がたまに全く表示されない場合があります。その場合は、設定> 詳細設定> ブログ設定 で 最新の情報に更新の『実行ボタン』で記事やアーカイブが最新にビルドされます。 Seesaa のページで、アーカイブとタグページは要注意です。タグページはコンテンツが全く無い状態になりますし、アーカイブページも歯抜けページはコンテンツが存在しないのにページが表示されてしまいます。 また、カテゴリページもそういう意味では完全ではありません。『カテゴリID-番号』というフォーマットで表示されるページですが、実際存在するより大きな番号でも表示されてしまいます。 ※ インデックスページのみ、実際の記事数を超えたページを指定しても最後のページが表示されるようです 対処としては、このようなヘルプ的な情報を固定でページの最後に表示するようにするといいでしょう。具体的には、メインの記事コンテンツの下に『自由形式』を追加し、アーカイブとカテゴリページでのみ表示するように設定し、コンテンツを用意するといいと思います。 ※ エキスパートモードで表示しています アーカイブとカテゴリページはこのように簡単に設定できますが、タグページは HTML 設定を直接変更して、以下の『タグページでのみ表示される内容』の記述方法で設定する必要があります<% if:page_name eq 'archive' -%> アーカイブページでのみ表示される内容 <% /if %> <% if:page_name eq 'category' -%> カテゴリページでのみ表示される内容 <% /if %> <% if:page_name eq 'tag' -%> タグページでのみ表示される内容 <% /if %>この記述は、以下の場所で使用します
|