火曜日, 12月 26, 2017

互換性(mysql_xxx)

年末の大掃除ですね。古いコードを再利用しようとしたらひっかかりました。PHP って互換性ないんですね。

mysql_xxx この辺を全部 mysqli クラスの関数へ変換。変数の順序が違う。

迷惑ですね。

しかしながら思うんですが…

プログラミング言語ってのはプロトコルですよ。一方的な変更は勝手ですよね。

少なくとも互換性は確保してほしい。


月曜日, 12月 25, 2017

MySQL で、NULL 値

MySQL で、NULL 値を許可するかどうかで条件分岐が変わってきます。

LIKE では NULL 値をはじけないんですね。

コラムの値で NULL 値を許可するなら、OR で指定せねばなりません。


SELECT * FROM pages WHERE menuid=$id AND NOT status LIKE 'onhold' ORDER BY id desc



これなんですが、ここの status の値が NULL の場合、こうやって指定せねばなりません。


SELECT * FROM pages WHERE menuid=$id AND (status IS NULL OR NOT status LIKE 'onhold') ORDER BY id desc


気を付けましょう。

金曜日, 11月 24, 2017

デジタルからアナログへ

PC を使わないアナログ回路は設計・制作が(かなり)手間ではありますが省電力です。

LED を点滅させるだけならトランジスタでいけます。


それはいいんですが、アナログ回路の欠点といえばモジュール化できないところ。回路を組み合わせるのはケースバイケース、至難の業です。これが PC を使っていればどのようなセンサーでも使えます。標準化されたインターフェース(HIGH-LOW)だからですね。

ここでは回路をフォトダイオードで制御する回路を組み合わせてみました。

感度の調整は可変抵抗です。





木曜日, 11月 23, 2017

Arduino: アナログからデジタルへ

大抵のセンサーの出力はアナログです。光セル、音声マイク、赤外線距離センサーなど。Arduino ならアナログでもアナログ端子があるので使えるんですが、これを割り込み操作で使おうと思うとデジタルな値が欲しい場合があります。

オペアンプでセンサーの出力をデジタル化できます。



この回路は赤外線距離センサーの出力を増幅し、オペアンプでコンパレータ回路を実現したものです。基準値は非反転入力で調整します。

これでアナログの束縛から解放されますね。

割り込みを使った Arduino 用のプログラムはこちらです。

#include <avr/sleep.h>
int ledPin = 13;
void setup() {
pinMode(2, INPUT_PULLUP);
pinMode(3, INPUT_PULLUP);
pinMode(ledPin, OUTPUT);
digitalWrite(ledPin, LOW);
}
void lightOff()
{
digitalWrite(ledPin, LOW);
}
void lightOn()
{
digitalWrite(ledPin, HIGH);
}
void sleepNow()
{
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
attachInterrupt(0, lightOff, FALLING);
attachInterrupt(1, lightOn, RISING);
sleep_mode();
sleep_disable();
detachInterrupt(0);
detachInterrupt(1);
}
void loop() {
sleepNow();
}
view raw wakup.ino hosted with ❤ by GitHub

日曜日, 11月 19, 2017

可変電源+ケース


可変電源を組んでケースを作ってみた。実用性はともかくきれいなのができた。青いケース、青い7セグがいい。こんないいのができると夢を誘う。



人間心理ってのは微妙なもので、「アクリル板曲げ」のサイトを読んでいたら危機感(これはまずい)が襲ってきたっていうか。急遽CADでデザインして3Dプリンタでケースを印刷。

金曜日, 11月 03, 2017

太陽電池+スーパーキャパシタでフルカラーLEDランプを点灯


晴れた日が続き、ようやっと太陽電池モジュールが動いてくれました。天気次第ってのがなんですね。でもこうやって光ってくれてると太陽のエネルギーが感じられますね。ほぼ永久機関。いいですね。

ソーラーパネルを使って充電するスーパーキャパシタを使った回路です。逆流防止用ダイオード挟んでますが、そのまま充電してフルカラーLEDを光らせてます。


ATTiny13A でグラデーションで色が変化するよう設定してます。ランプシェードは Thingiverse 一番人気のこれ。お気に入りです。

MySQL でコラム(列)の値を交換

MySQL でコラム(列)の値を交換する方法です。

変数を使います。

使わないと MySQL ではできないようです。

update 'table' set start=(@tmp:=`X`), X=Y, Y=@tmp

日曜日, 10月 29, 2017

レーザーダイオード用定電流電源

ふとレーザーダイオードを点灯させよう!などと思い立ち、定電流電源を作ってみました。レーザーポインターなどで使われているあれですね。これはダイオードなので一定の電流を流してやる必要があります。

ボタン電池でそのままつなぐなる荒業があるらしいんですが、ここは電流を制限するほうが安心だってことでLM317で回路を組んでみました。

データシートそのままの回路ですが、Adjust - Out 間の電圧が1.25Vで保たれる性質を利用します。間の抵抗を調整することで電流を制御します。

久しぶりの電子工作のせいか手間取ったのみならず、なんだかできあがりは散々でしたが動きます。





追記:折角つくった定電流回路なのでケースを3Dプリンタで設計。

フィラメントがPLAなので、熱したはんだごてで成形できるわけなんです。

部品がきっちり収まるケースができました。感動ですね。





火曜日, 8月 29, 2017

Python 3.6 でユニコードを扱う場合。

Python 3.6 でデータベースからユニコード文字列をとってきて書きだそうと思うと引っかかります。

要はこれです。

f=open('test.txt', 'w', encoding="utf-8")

ユニコードを指定します。でないとエラーを出します。

月曜日, 8月 28, 2017

Python/MySQL のクエリーで%を使う

単純な話ですが ...

Python 3.6 はライブラリが一通りそろっていて文字列処理が楽です。

データベースを使うなら mysql-connector-python のようなドライバを導入してアクセスします。

クエリの書き方ですが、カーソルの execute() メソッドを使います。

クエリをそのままかくのもいいんですが、パラメタ化してエスケープするやり方です。

cur.execute("select * from genera where latin like %s", (genus,))

このカッコ、コンマは省略できません。

ここまでは既出だと思うんですが、ここで % を使いたい場合。

つまんない話なんですが、ネットでなかったんですよね。直接の記述が。これパラメタそのものをいじればいいんです。

genus = genus +"%"

これで%が使えます (いや、それだけです)。

火曜日, 8月 22, 2017

Laravel 5.4 のすすめ (データベース篇)

Laravel でデータベースのテーブルを作る作業は ORM まできちんと定式化されています。

まずはテンプレートを使って migration のファイルを自動生成し、テーブルを記述。ファイルはここ database/migrations/* 。

php artisan make:migration create_テーブル名 --create=テーブル名

テーブルの記述はこのような形式です。

$table->string('en');
$table->string('ja');
$table->integer('order_id');        

コマンドを使用してテーブルを作成します。データベース設定ファイルは .env です。

php artisan migrate

あとはモデルを自動生成。これでマッピングが完了。

php artisan make:model テーブル名

 $table 変数でテーブル名を指定できます。

class Office extends Model
{
    protected $table = 'office';
}

専用のページを作りたければ、コントローラーを作ってビューを生成します。個々のレコードのページを作っておくと、編集ができますね。その際は routes/web.php の編集が必要です。

php artisan make:controller コントローラー名 --resource

ロールバックでテーブルを消去したり、シードを使ってデータを放り込むこともできます。

日曜日, 8月 20, 2017

(仕様が変更された)Laravel 5.4 を使う

故あって Laravel で PHP サイトを作ることとなりました。ので概要をメモっておきたいと思います。

これ MVC とか ORM とか DI とか軽く使えるよくできてるシステムなんですが、いまだマイナー系なのかなんなのか仕様がバージョンごとコロコロ変わる。

ついこのあいだ ver. 5.1 で書いて ver. 5.4 で動かそうと思うと… 動きます。ライブラリをそのままコピーしてあるからなんですが、これが新たなプロジェクトをたちあげようとするとライブラリの仕様が変更されている。

新しいライブラリはメソッドなど整理されていて使いやすくなっていますが、仕様が異なるので同じ調子で書いていくとエラーが続出します。

まずは新しいプロジェクトの作り方から。

laravel new プロジェクト名

これでライブラリなどすべてコピーされて完全なシステムが出来上がります。それはいいんですが、ここでまずルーティングのファイルの置き場所が違う。ファイル名まで違う。ver. 5.3 で変更されたようです。

ROUTING:
routes/web.php

ここですね。あとビューとかコントローラーとかは同じです。

VIEW:
resources/views/*.blade.php

CONTROLLER:
app/Http/Controllers/*.php

ルーティングの書き方はこんな感じです。

Route::resource('/dashboard','OrderController');

これですべてページからのリクエストが仕分けされてコントローラーで処理できます。これはいいですね。

動詞 URI アクション ルート名
GET /photos index photos.index
GET /photos/create create photos.create
POST /photos store photos.store
GET /photos/{photo} show photos.show
GET /photos/{photo}/edit edit photos.edit
PUT/PATCH /photos/{photo} update photos.update
DELETE /photos/{photo} destroy photos.destroy

これどういうことかってページから投げられるリクエストでそれぞれアクションを呼べるわけなんです。DELETE って投げれば destroy ってメソッドを定義するだけできちんと動くサイトが出来てしまうわけです。

こうやってビューでフォームを指定します。DELETE を投げてるわけですね。

<form method="post" action="/dashboard/{{$task->id}}">
{{ csrf_field() }} 
{{ method_field('delete') }} 
<input type='submit' value='Remove' 
class='btn btn-danger btn-sm' />
</form>

で、コントローラーを定義します。

    public function destroy($id)
    {
        $order= Order::findOrFail($id);
        $order->delete();
        return redirect ( '/dashboard' );
    }

これだけでリクエストが仕分けされて処理できるって仕組みです。うまいですね。

Order ってのはデータベースのテーブルがマップされたオブジェクトです。ORM ってのは便利ですね。delete() って呼ぶだけで作業は完了です。

Laravel ってのは頭が整理されるとってもよいフレームワークだと思います。しかしながら仕様変更が激しいので要注意です。

土曜日, 5月 06, 2017

GitHub: 排除されないファイルを指定する

GitHub 便利です。置いとくだけで世界中どこでもコンパイルできます。書いてアップデートすればいいわけです。バックアップの手間もない。

で、調子よくコード書いてたわけなんですが、なぜか lib ディレクトリがアップデートされていない。ファイルが出てこないのでコミットできない。

どうも .gitignore で JAR ファイルを排除したのがまずかったらしいんですが、これです。

*.jar

これだと JAR ファイルすべて排除されちゃうんですね。lib ディレクトリ以下のものもです。

ここは排除されないよう例外を設定します。

!lib/*

これです。!をつけておくと排除されないんですね。


水曜日, 4月 26, 2017

Java: アダプターを作る。

車輪を発明なんていいますよね。でも自前で直せるっていうメリットはあります。

あれ?これなんでないんだろうって思ったらネットで探してなければ作る。この精神(勢い)が大事ですね。

よく考えてみると作れる!ってのは存外いけます。作ったら仕組みが理解できます。

Java アダプターの話です。アダプターってのは addActionListener() でリスナーをつけるとき、リスナーを実装したクラスを使うのでなくてその場で内部クラス(アダプター)をつくる方法です。

機能がまとまって書けるのでコードが読みやすくなります。

この便利なアダプターですが、なぜか ActionListener のがない。

で、作りました。アダプターってなんだろうって考えたわけですね。なんかのクラスでリスナーが実装されていればいい。

import java.awt.event.ActionListener;
abstract class ActionAdaptor implements ActionListener {
}
これで動きます。これだけなんですね。んー なんか探すより作ったほうが早い。

こんなケースもあるわけなんですね。

土曜日, 4月 22, 2017

文字列変換:変換文字列をそれぞれ指定する

学校で習うような複雑なアルゴリズムを使う機会ってのは実際ほとんどないですね。

クイックソートを実装するなんてのはまずない。あれを一発で通せなんていう無茶な要求がありましたよね。ハノイの塔とか。

複雑であればライブラリを使う。

それでも多少は面倒なときもあります。

文字列を分割するとか。

これ、特定の文字列を変換するコードです。全ての文字列を単変換ならライブラリがありますが、各変換ごと数値を当てはめるとかカスタマイズするとなるとやっぱり書かざるを得ない。

public String replaceParam(String str, String[] list) {
String res = "";
int index = 0;
int count = 0;
int prev = 0;
while ((index = str.indexOf('?', index)) != -1) {
if (count < list.length) {
if (prev < index) {
res += str.substring(prev, index);
}
res += list[count];
count++;
}
index++;
prev = index;
}
if (prev < str.length()) {
res += str.substring(prev);
}
return res;
}

金曜日, 4月 21, 2017

Java: タイムアウト実践編

タイム・アウト実践編です。

終わらない(かもしれない)仕事を時間制限をつけて実行します。

ここはスレッドを用いたクラスを用います。

スレッドを synchronized された関数で呼び出します。

一定時間のち interrupt() を呼び出してスレッドを終了します。

FileTask task=new FileTask(fn);
try {
Thread.sleep(10);
task.interrupt();
if(task.retrieved && task.exists){
// file exists
}else{
// otherwise
}
} catch (InterruptedException e) {
// time out
}

FileTask の定義です。

時間がかかるファイルアクセスをスレッドで実行します。コマンドを走らせて終了時フラグをセットします。

class FileTask extends Thread{
boolean retrieved=false;
boolean exists=false;
String fn="";
FileTask(String fn){
this.fn=fn;
start();
}
public void run(){
try{
File file=new File(fn);
String[] list=file.list();
if(list!=null)
{
exists=true;
}
retrieved=true;
}catch(Exception e){
log.error("File access error",e);
}
}
}
view raw FileTask.java hosted with ❤ by GitHub

これで終わらない仕事は強制終了です。

木曜日, 4月 20, 2017

Java: タイム・アウト

この仕事が終わらない

なんて状態はよくあります。

終わらないなら強制終了させねばなりません。

指定時間内で終わらない仕事は強制終了する、そんな方法(コード)をお見せします。

Java で時間を指定するならスレッドを使うしかありません。

便利なクラスが提供されていますが基本はスレッドです。

行う動作を別スレッドで走らせて、指定時間が来たら interrupt() をかけます。

public class TimeOut extends Thread{
MyTask task;
public TimeOut(MyTask task){
this.task=task;
start();
}
public void run(){
try{
Thread.sleep(1000);
task.interrupt();
}catch(Exception e){
}
}
public static void main(String args[]){
MyTask task=new MyTask();
new TimeOut(task);
}
}
class MyTask extends Thread{
MyTask(){
start();
}
public void run(){
try{
for(;;){
System.out.print("*");
sleep(100);
}
}catch(Exception e){
}
}
}
view raw TimeOut.java hosted with ❤ by GitHub

月曜日, 3月 27, 2017

Quartz で定期処理: Job へ値を引き渡す方法

プログラムを一定時間ごと走らせたい場合、スケジューラーを使います。

シェルスクリプトなどで走らせる方法もありますが、異質なものを組み合わせるのは限界があります。

Java で書けるスケジューラーで、Quartz なる優れた(ちょっと癖のある)ライブラリがあります。

Quartz の使い方はネットでもあがってますが、自前の Job を走らせたいときつまづきやすいのが Job へ値を引き渡したいとき。

ネットであまり記述がなかったので書きます。

このさいコンストラクタを使って値を引き渡す方法はx(だめ)です。

ここは .usingJobData(String, String) を用います。

import static org.quartz.SimpleScheduleBuilder.simpleSchedule;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;
public class CronTest {
public static void main(String[] args) {
try {
JobDetail job = JobBuilder.newJob(CronTestJob.class).usingJobData("cmd", "echo")
.withIdentity("trigger", "group").build();
Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger", "group").startNow()
.withSchedule(simpleSchedule().withIntervalInMilliseconds(1000).repeatForever()).build();
Scheduler scheduler = null;
scheduler = StdSchedulerFactory.getDefaultScheduler();
scheduler.scheduleJob(job, trigger);
scheduler.start();
Thread.sleep(10000);
scheduler.shutdown();
} catch (Exception e) {
e.printStackTrace();
}
}
}
view raw CronTest.java hosted with ❤ by GitHub

受け取る側は JobExecutionContext から getJobDataMap() を使って受け取ります。

import java.io.IOException;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
public class CronTestJob implements Job{
String cmd="yahho";
@Override
public void execute(JobExecutionContext arg0) throws JobExecutionException {
try {
String cmd=(String)arg0.getJobDetail().getJobDataMap().get("cmd");
System.out.println(cmd);
} catch (Exception e) {
e.printStackTrace();
}
}
}

土曜日, 3月 11, 2017

Java でログを出力:slf4j+logger

Jar 実行形式ファイルではコンソール入出力が使えません。コンソールが使えずともファイルを使う便利な方法があります。ロガーを使う方法です。

そうでなくともログは重要です。デバッグでなくともアプリのトレースが必要な場合は多いです。

Java でログを出力するための便利なライブラリは多種さまざまありますが、そのなかでも slf4j+logger なる方法が便利です。static で Logger を定義できて、出力形式を XML で指定できます。

必要な jar ファイルは以下の通りです[*]。

logback-classic-1.2.1.jar
logback-core-1.2.1.jar
slf4j-api-1.7.24.jar

必要最小限なコードを示します。

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class LogTest {
public static void main(String[] args) {
Logger log = LoggerFactory.getLogger(LogTest.class);
log.info("LogTest running ...");
}
}
view raw LogTest.java hosted with ❤ by GitHub

出力用のログファイルの設定は logback.xml で。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE logback>
<configuration>
<timestamp key="time" datePattern="yyyy-MM-dd_HHmmss" />
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>log/SCDFgen-${time}.log</file>
<encoder>
<charset>UTF-8</charset>
<pattern>%m%n</pattern>
</encoder>
</appender>
<root>
<appender-ref ref="FILE" />
</root>
</configuration>
view raw logback.xml hosted with ❤ by GitHub

こいつは奥が深いです。ライブラリのソースの規模を見ると圧倒されます。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE logback>
<configuration>
<timestamp key="time" datePattern="yyyy-MM-dd_HHmmss" />
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>log/WavSplit-${time}.log</file>
<encoder>
<charset>UTF-8</charset>
<pattern>%m%n</pattern>
</encoder>
</appender>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%-7([%level]) %m%n</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<root>
<appender-ref ref="STDOUT" />
</root>
</configuration>

ログのレベルは error>warn>info>debug>trace などあります。デフォルトではファイル出力はすべて、標準出力はデバッグレベルまで。レベルごと分けておくと便利です。

Apache Commons CLI: Java でコマンドライン処理

JavaをWindows上で使うのはだからちょっとした障壁をクリアせねばなりません。この種の困難は「世界市場を独占するマイクロソフトへモノを言っているんだ」ぐらいのノリで立ち向かう必要があります。

ですからJavaでコンソールアプリってのはどうしても多少の困難を覚悟せねばなりません。コマンドライン処理など想定されていないわけです。

プロパティファイルで初期化パラメタを設定なる方法がありますが、昔ながらの伝統的スタイルを継承し、クラシックなノリでコマンドライン引数なるものを使うとプロパティなどというものを使わずまるでUnix/Linux/Gnuのコマンドのようなプログラムが書けます。

ここは外部ライブラリを使うのがオススメです。Apache Commons CLI を使う方法を示します。

public static void main(String args[]) {
Options opt = new Options();
try {
opt.addOption("?", OPTION_HELP, false, "print this message");
Option option = Option.builder("f").required(true).longOpt(OPTION_FILE).hasArgs().desc("file name").build();
opt.addOption(option);
Option dirOption = Option.builder("d").required(true).longOpt(OPTION_DIR).hasArgs().desc("target directory")
.build();
opt.addOption(dirOption);
CommandLineParser parser = new DefaultParser();
CommandLine cmd = parser.parse(opt, args);
if (cmd.hasOption(OPTION_HELP)) {
throw new Exception();
} else if (cmd.hasOption(OPTION_DIR) && cmd.hasOption(OPTION_FILE)) {
String dir = cmd.getOptionValue(OPTION_DIR);
String fileName = cmd.getOptionValue(OPTION_FILE);
new FindFile(fileName, dir);
}else{
throw new Exception();
}
} catch (Exception e) {
HelpFormatter help = new HelpFormatter();
help.printHelp("DirList", opt, true);
}
}

Java: jar 実行ファイルをつくる

Windows で動く Java の実行ファイルを作るのは手間がかかります。

マイクロソフト社の陰謀ですね。ちょっとした関税外障壁があるわけです。

まず、そのままjavacでコンパイルしてもclassファイルができるだけです。ライブラリを組み込んで動いても、とっても不便なディレクトリ構造は動かせない。

ここは jar ファイルの作り方を工夫すれば動きます。プロジェクトを右クリック、Export からダイアログで Runnable JAR file を選択します。



或いはライブラリを組み込んでマニフェストファイルを設定し Main-Class を設定します。これだってかなりな手間ですが、話はこれで終わらない。

<target name="jar" depends="build">
<jar jarfile="SCDF_Generator.jar" basedir="bin">
<manifest>
<attribute name="Main-Class" value="DirList" />
</manifest>
<zipgroupfileset dir="lib" includes="*.jar" />
</jar>
</target>
view raw build.xml hosted with ❤ by GitHub

出来上がった jar 実行ファイルがエラーも出さず動いたと思えば動かしているのはjavawでjavaです。つまりコンソールアプリは動かない。出力はまったくなしです。

どうしてもコマンド一つで動く jar 実行ファイルを作りたい場合。copy コマンドでバッチファイルをコピーする裏技があります。

@echo off
java -jar "%~f0" %*
exit /b %ERRORLEVEL%
view raw src.bat hosted with ❤ by GitHub
copy /b src.jar+DirList.ar DirList.bat
view raw copy hosted with ❤ by GitHub

火曜日, 2月 28, 2017

Java の enum 列挙型の変数名を値から逆引きする

Java の enum 列挙型は値を設定せず列挙するだけで値を設定してくれる優れ
モノです。

Java の enum は C/C++ のより拡張性があってもっと便利です。

変数値から要素名を得る「逆引き」などという動作は、enum の一部として定義できます。

public class ReverseLookup {
enum PRQ{
KEY
,CLIENT_CODE
,ITEM_CODE
,ORDER_NUMBER
,PROVIDER_NUMBER};
public static String getValue(int n) {
String res = "";
PRQ valueList[] = PRQ.values();
for (PRQ p : valueList) {
if (p.ordinal() == n) {
return p.name();
}
}
return res;
}
}


values() を使えば列挙型の設定されたすべての値を得ることができます。

 便利な Java の enum 列挙型ですが、得られた配列から値を得てももとの値を得ることができない。ようです。

あるのは ordinal() 関数のみ。これだと順番が出てきます。

設定された変数へ値を代入する、あとはメンバ関数を自作するなどいう方法が巷ではあるようですが、これだと列挙型である意味がない。並べておいて代入しなくていいのが列挙型の利点です。

???な Java の enum 列挙型ですが、そもそも最初の設計でなかった機能です。なにか考えがあるのかも。

値を設定しているのでない、順番があるだけだ、ってことでしょうか。

水曜日, 2月 22, 2017

Struts: web.xml がない場合

故あって Struts なるものを使ってます。

温故知新ならぬあらためて再評価ってところでしょうか。

データ管理がOOP!

受け渡すパラメタがカプセル化!

いいですね。ですが

ページ遷移はアクションが管理!つまりJavaファイルからは見えない。

つまり xml ファイルが問題重要なわけです。これが脳内で構成できればシステムが見える... これらの犠牲を払うとJavaのすべての機能を使える。
これはまりました。
web.xml が読み込むクラスを指定するわけなんですが、明示的な指定はないわけです。

ログなぞながめても何も書いていない。

サーバーの管理画面だと「running」でプロセスはなし。
結論をいうと web.xml が迷子だったわけなんですが... それだけです。

Qt: 外部プログラムを起動する

  Qt/C++ のアプリは、外部へ直接アクセスできます。これはネットアプリでは不可能な Qt のメリットです。 外部プログラムを起動することもできます。QProcess::startDetached() を使うと独立したプロセスを立ち上げることができます。 この QProces...