2011年11月30日水曜日

( Qt C++ )GUI Programming with Qt4 3日目

はい、本日最後の投稿。
GUI Programming with Qt4 3日目に入りました。順調に60ページづつ進んでおります。
今のところ各GUI部品の使い方や設定例、カスタム部品作成法やイベントなどの基本的な説明ばかりなので特に問題なく順調に進めています。まぁこのあたりは頭に叩き込むというところではなく、「こんな使い方があるんだぁ~。」ぐらいの感覚で問題ないでしょう。実際に使う時に見ながらただ設定していけばいいだけですからね。

ダブルバッファの章でMSチャートみたいなサンプルがありました。やっぱりQtに部品は用意されていないようです。サンプルでは1からDrawする形で書かれていました。

(エラーチェックやフィルタリングなしでもかなりめんどくさいです。)

しかし、なんだろ、やればやるほど微妙な気持ちになる...。慣れなのかなぁ...。

( デザインパターン )イテレータパターン

今回はイテレータパターン。
独習デザインパターン ではJavaですが、C#で書きます。
このパターンの目的は
「集約オブジェクト内の個々のオブジェクトに統一化された手段でアクセスできるようにするためのパターン」
だそうです。
本には例として社員名簿一覧を表示する場合があげられています。一人分の社員情報を保持するEmployeeクラスを作り、これを使ってあらかじめ社員の名前と住所を登録して名簿を作成するというもの。
うだうだうんちく書くよりコード書くほうが理解しやすいので以下コード

public class Employee
{
    private string name;
    private string address;
    public Employee(string name, string address)
    {
        this.name = name;
        this.address = address;
    }

    public string getName()
    {
        return name;
    }

    public string getAddress()
    {
        return address;
    }
}

public interface Aggregate
{
    Iterator iterator();
}

public interface Iterator
{
    bool hasNext();
    object next();
}

public class IteratorOffice : Iterator
{
    private Office office;
    private int cursor;

    public  IteratorOffice(Office office)
    {
        this.office = office;
        this.cursor = 0;
    }

    public Office Office
    {
        get
        {
            throw new System.NotImplementedException();
        }
        set
        {
        }
    }

    public bool hasNext()
    {
        if(cursor < office.size())
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    public object next()
    {
        object employee = office.get(cursor);
        cursor++;
        return employee;
    }
}

public class Office : Aggregate
{
    private List<object> employees;

    public Office(int max)
    {
        employees = new List<object>(max);
    }

    public IteratorOffice IteratorOffice
    {
        get
        {
            throw new System.NotImplementedException();
        }
        set
        {
        }
    }

    public Employee Employee
    {
        get
        {
            throw new System.NotImplementedException();
        }
        set
        {
        }
    }

    public void add(object obj)
    {
        employees.Add(obj);
    }

    public object get(int index)
    {
        return employees[index];
    }

    public int size()
    {
        return employees.Count;
    }

    public Iterator iterator()
    {
        return new IteratorOffice(this);
    }
}

書いていて気付いたのだが、C#ではインターフェイスの中でabstructが使えないようだ。C#の場合

interface I 
{
    void M();
}
abstract class C: I 
{
    public abstract void M();
}
(MSDNより)
のように書けば書籍と同じようになるのだろう。今回は却下。(めんどい)

話しを戻します。上記プログラムを使う場合は 
 


Office office = new Office(3);

office.add(new Employee("山田", "神奈川"));

office.add(new Employee("土田", "香川"));

office.add(new Employee("木田", "東京"));

Iterator iter = office.iterator();

string temp = "";

while (iter.hasNext())

{
    Employee employee = (Employee)iter.next();
    temp += employee.getName() + " : " + employee.getAddress() + "\n";

}

MessageBox.Show(temp);

 

のようにする。このプログラムでは最後にメッセージボックスに名簿リストが表示されます。 
 
それでこのパターンを適用するとどうなるかというと
①Iteratorオブジェからの取得方法統一化。内部構造を考えず、常に決まった取り出しが可能
②集約オブジェの変更があってもIteratorオブジェを仲介するので取得側コード変更不要。
③Iteratorクラスのサブクラスを定義することで、様々な走査方法を実現できる。(*1)
というメリットがあるそうです。


なんとなくわかったようなわからんような...。今のところこのパターンを適用したいと思うアプリは思いつかないなぁ...。

(*1)今回はこのメリットは見られない。

( Java )ファイルを複数拡張子フィルタリングし取得する。

時間がとれたので今日は2~3回投稿。
まずはJavaの話題。
ファイルを複数の拡張子でフィルタリングする場合以下のクラスを使う。

public class FileFilter implements FilenameFilter{
    private final String FILTER_KEYWORD = ".jpg";
    private final String FILTER_KEYWORD2 = ".JPG";
   
    public boolean accept(File dir, String name){
        File file = new File(name);
        if(file.isDirectory()){
            return false;
        }
        return(name.endsWith(FILTER_KEYWORD)|| name.endsWith(FILTER_KEYWORD2));
    }
}

んでこれを

String[] imageArray;
File dir;

dir = new File("C:\とか");
imageArray = dir.list(new FileFilter());

のようにして使う。FILTER_KEYWORDの部分を変更したり、あるいは増やせば、さらに別の拡張子を取得したり、拡張子フィルタの種類を増やすことができる。

2011年11月29日火曜日

( Qt C++ )GUI Programming with Qt4 2日目





今日は2日目。順調に60ページ進めることができた。
スプレッドシート(エクセルみたいな)を作る例題が載っているのだが
どうにも直感的に使いづらいと思うところが多数あった。QStringlistとかQString[]みたいな感じにならないのかな...個人的に使いづらい。まぁ慣れるしかないんだろうけど...。

あと思ったのだが 、
Qtが有利なのは用意されているGUI部品で済み、用意されているAPIでなんとかなる場合だけなんじゃないかと思う。用意されていない要求に応えるのはめんどくさそう。msチャートのような部品が必要となり、1から自作しなければならない場合なんかを考えると頭痛がしてくる。そういう時はQtをあきらめて各プラットフォームで主流になっているやり方でやったほうが早いんだろうな...。

2011年11月28日月曜日

( Qt C++ )GUI Programming with Qt4 1日目


今日はGUI Programming with Qt4 (英語PDF版)を60ページほど読み進めました。
感想は

「初見じゃキツイ。"Qtをはじめよう" で少し使い方に慣れてから読まないとSlot? emit? は?は?みたくなる。ただ全体としては図もプログラムも豊富なので読みやすい部類。」

です。Qtをはじめよう シリーズでは今のところ19個の学習コンテンツが公開されている。この19個をやれば簡単なアプリケーションなら作成できるようになる。(たとえば電卓アプリとか)
これをやった上で読むとスイスイ進む。

んで、今日の私にとっての収穫は
Exceptionally, if a signal has more parameters than the slot it is connected to,
the additional parameters are simply ignored:

connect(ftp, SIGNAL(rawCommandReply(int, const QString &)),
this, SLOT(checkErrorCode(int)));


の「シグナルの関数の引数の数がスロットの引数より多い場合、多い部分は無視される。」みたいな意味の部分、
 あとは
QChar ch = 'A';
QChar last = 'F'
while(ch <= last){
   ch = ch.unicode() + 1;
   ///....なんかの処理
}
でA~Fまでをどうにかできるとか、60ページの
QAction *action = qobject_cast<QAction *>(sender()); //(動的キャスト)
のqobject_cast<T>()のあたりです。

このペースで行けば10日で終わりそう。10日後にはリネームソフトでも作ろうかなぁ...。
まぁどこかでペースダウンするんだろうけど...。

雑記

結構ブログって続けるの面倒だわ。
自分でホームページ管理するよりはマシだけど。
なんていうか、こう、義務のように感じてきちゃってストレスになるんだよね。自分の場合。

とまぁ、愚痴ってもしょうがないことなのだが...。

今日は特に書くことはなし。プログラミング自体をやっていないからね。
明日からはQt GUI Programingの英語版を少しづつやっていこうと思っている。
まぁこれは1日50~100ページとして5~10日で終わればいいかなと思っている。
だけど、参考書のサンプルって頭にあんま残んないんだよなぁ。あれ何でなんだろ?
やっぱ目的意識に欠けるからかな?まぁやらないよりはマシなんだろうけど...。

2011年11月26日土曜日

( デザインパターン )シングルトンパターンとか

今日はデザインパターンをメモします。
というのも独習デザインパターンが格安で手に入ったからです。
Javaで書かれていますがJavaの気分じゃないのでC#で書きます。

シングルトンパターンはその名の通りオブジェクトが一つであることを保証するというものと書かれています。

public class CourtScheduler
{
    private static CourtScheduler courtScheduler = new CourtScheduler();
    private string[] schedule;
    public static int HOURS = 24;

    private CourtScheduler()
    {
        initialize();
    }

    public static CourtScheduler getInstance()
    {
        return courtScheduler;
    }

    private void initialize()
    {
        schedule = new string[24];
        for (int i = 0; i < HOURS; i++)
            schedule[i] = "";
    }

    public string getSchedule(int hour)
    {
        return schedule[hour];
    }

    public void setSchedule(int hour, string person)
    {
        schedule[hour] = person;
    }
} 

理解のために重要なのは
private static CourtScheduler courtScheduler = new CourtScheduler();
private CourtScheduler(){...}
public static CourtScheduler getInstance(){...}
で 、これらがオブジェクトを勝手に複数作らせないようにしている。
呼び出し側がオブジェクトを管理しなくていいというメリットもあるそうです。

2011年11月25日金曜日

( C# ) 日付のクイックソートなど

私はだいたい、めんどくさい処理を書いてそいつをコンピュータにやらせている。
例えば何度もループすることや、大きな整数計算。画像処理や一括処理などがそうだ。
私なんかがサクサクプログラミングできるのだからプログラミング手法は年々より効率的な
ものになっているのだと思う。
しかしながら、こういっては失礼かもしれないが

”めんどくさい処理をあらかじめ書いておきそれを実行させる。”

これは未だに変わっちゃいない。統合開発環境などでデザイナを使ってると一見自動で
プログラミングされているように見えるが、これもやはり、そうなるようにそういった処理をあらかじめ書いてあるのである。

で、だから何だという話だが

”実行させ、めんどくさい処理を書かせ、結果のみ返す”

ようになればこれって革命だよなぁとふと思ったわけです。

あれ?でもその仕組作るにはまためんどくさい処理を自分で書かなきゃならないわけで…
…自分で何考えてるかこんがらがってきた。まぁどうでもいいことなんですけど...。


はい、さて、タイトルの件ですが、C#で画像ファイルの日付によるクイックソートは

Array.Sort(Array array,  IComparer comparer)

を使えば簡単でスッキリとかけるのだが、自分で書いたほうがもっと速いんじゃないかと思ったので自作クイックソートを書いてみた。

//クイックソート
private string[] quickSort(string[] filename, DateTime[] days, int left, int right)
{
    Stack<int> lstack = new Stack<int>(right - left + 1);
    Stack<int> rstack = new Stack<int>(right - left + 1);
    string work;
    DateTime work_time;
    int end = right;

    lstack.Push(left);
    rstack.Push(right);

    while (lstack.Count != 0)
    {
        int pl = left = lstack.Pop();
        int pr = right = rstack.Pop();
        DateTime pivot = days[(left + right) / 2];
        do
        {
            while (pl <= right && days[pl].CompareTo(pivot) < 0) {pl++;}
            while (pr >= 0 && days[pr].CompareTo(pivot) > 0) {pr--;}
            if (pl <= pr)
            {
                work_time = days[pl];
                work = filename[pl];

                days[pl] = days[pr];
                filename[pl] = filename[pr];

                days[pr] = work_time;
                filename[pr] = work;
                pl++; pr--;
            }
        } while (pl <= pr);

        if (left < pr)
        {
            lstack.Push(left);
            rstack.Push(pr);
        }
        if (pl < right)
        {
            lstack.Push(pl);
            rstack.Push(right);
        }
    }           
    return filename;
}

引数は順にファイル名、そのファイルと同じ順番のDateTime配列、開始位置、終了位置
である。で問題の速度差なんだけど...なんと!

ほとんど変わりません。

ファイル数が少ないからかなぁ?まぁ速い遅いどちらにせよどこかで使うかもしれないので
メモ。

2011年11月24日木曜日

( Java ) 絶対パスからディレクトリパスのみを取り出す

今日は本当に疲れた。
仕事ではムカつくことばかりだったし...。
現実で「俺を誰だと思ってるんだっ!」なんて初めて聞いたよ。
とりあえず怒鳴るなっての。すんげー偉い人間だっていうなら権力使ってサッサと俺をクビにすればいいだろ?めんどくせぇ。怒鳴ろうがあんたへの信頼はなおらねぇっての! ...

はい。さて、今日はJavaで、C#のようにパスからディレクトリパスのみを取り出す関数が用意されていないようなのでそれをメモしておく。

private String getDirectoryName(String absolutepath)
{
    File file = new File(absolutepath);
    int index = file.getAbsolutePath().lastIndexOf("\\");
    String dirName = "";
    if(index > 0 && index <= file.getAbsolutePath().length() - 1)
    {
        dirName = file.getAbsolutePath().substring(0, index);
    }
    return dirName;
}

この関数を正常に使用するためには引数となる絶対パスをあらかじめチェックするか、
あるいはこの関数内でチェックする必要がある。

2011年11月23日水曜日

( Qt C++ )リストビューに表示した項目の取得など


あぁ寒い。冬は虫がいなくていいけど寒いのがいやだね。燃料代も馬鹿みたいにかかるし。

今日はQtプログラミングについてのメモ。
Qtに関する日本語による情報は本当に少ない。(C#やJavaなどに比べるとかなり少ない)
リストビューに表示までは日本語による解説ページもチラホラあり、わりとすんなりいくのだけど、リストビューの項目を取り出そうとすると日本語による解説ページがないのでかなり
苦戦した。これがベストなやり方とは到底思えないが、解決の糸口になると思うので一応メモしておく。

void MainWindow::fileReName()
{
    if(ui->listView->model() != NULL && 
ui->listView->selectionModel()->isSelected(ui->listView->currentIndex()))
    {
        QItemSelectionModel *temp;
        temp = ui->listView->selectionModel();

        QModelIndexList qModelIndexList = temp->selectedIndexes();
        QModelIndex qMIndex = qModelIndexList[0];

        QFile::rename(dirName + "/" + qMIndex.data(0).toString(),
                      dirName + "/fuck.txt");
        //...以下は不必要なので省略
    }
}

上記では単項目リストビューから選択したモデルを取り出し、そのデータを利用しファイル名をリネームしている。
なお、QModelIndexListはtypedefで "Synonym for QList<QModelIndex>."ならしい。

今回はリファレンスだけを見ながら組んだのだが、リファレンスだけでは作業効率が悪すぎる。それらしい関数名を探すだけでかなりの時間を要する。素直にQt入門書を買って、ある程度広く浅い知識をつけてからリファレンス片手にプログラムを組んでいけば、こんなつまらないことでつまづくことはないんじゃないかと思う。
だけど書籍って場所とるし高いんだよなぁ...。

追記: このコードは無駄が多いです。 temp->selectedIndexes();でQModelIndexList保持するところが特にです。この後の記事でモデルからのデータ取り出しを扱っています。そちらを参考にしたほうがいいかもしれません。

2011年11月22日火曜日

( Java ) フォルダダイアログとファイル名フィルタについて

    フォルダ選択ダイアログを表示し、ファイル名フィルタをかけるというもの
ここではテキストファイルのみをフィルタリングしている。ダイアログ関係で
結構頻繁に使うのでメモ。
http://www.syboos.jp/java/doc/listfiles-by-filefilter.htmlを参考)

private void folderOpenDialog(ActionEvent arg0)
{
    JFileChooser fldlg = new JFileChooser();
    fldlg.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
    if(fldlg.showOpenDialog(this) == JFileChooser.APPROVE_OPTION)
    {
        File fl = fldlg.getSelectedFile();
        File[] txtFiles = fl.listFiles(getFileExtensionFilter(".txt"));

        table.setValueAt(txtFiles[0], 0, 0);//テーブルにセットしてみる。
   }       
}

private FilenameFilter getFileExtensionFilter(String extension)
{ 
    final String _extension = extension; 
    return new FilenameFilter()
    { 
        public boolean accept(File file, String name)
        { 
            boolean ret = name.endsWith(_extension);  
            return ret; 
        } 
    }; 
}  

Javaは最近Eclipseをインストールしたので触っているのだが、なかなかわかりやすく、
使いやすい。日本語のサイトも豊富なので勉強はさくさく進みそうな感じがする。

2011年11月21日月曜日

ブログの開設

ブログを開設しました!...といっても普段気付いたことをメモしていくような、個人的な主観で書かれたブログになりますのであまりおもしろくはならないと思います。
なお、このブログで書かれた記事やプログラムなんかは他で使ってもらっても構いません。(そんなすごいことも書けませんし...)いちいち
メールとかいりません。では。