Kohshi's Blog
2014/08/28
C++ std::list, std::vector, std::dequeをまとめておく
# vector [cplusplus](http://www.cplusplus.com/reference/vector/vector/) arrayのように連続ストレージ系のコンテナ。 + * arrayと違って可変長。 * ランダムアクセス性が高い。 * endに対してのaddやremoveはlist,dequeに対して効率的 ー * 頻繁なallocationを防ぐために余分にメモリ確保される。 * (actual sizeに対してcapacityを大きく確保するから。ライブラリによってallocationタイミングは分かれるが、一般的いはlogインターバル) * end以外へのinsertやremoveはlist,dequeに対して遅い * iteratorの定常性というかconsistencyはlistに比べると低い # list [cplusplus](http://www.cplusplus.com/reference/list/list/) 固定処理時間でのinsert、erase(場所によらない)が特徴の双方向リストコンテナ + * insert, erase, moveが他のコンテナと比較して速い ー * ランダムアクセス性は低い、begin/endとかからたどる必要がある(はず)O(n) # deque [cplusplus](http://www.cplusplus.com/reference/deque/deque/) Double-Ended-Queueの略。Queueの一種なのでbeginとendからしか拡張できない。 + * arrayと違って、可変長 * listと違って、ランダムアクセス性は高い * vectorと違って分割されたChunk(+ランダムアクセス用の情報)に分けてデータを保存しているらしい。 * vectorと違って、endだけでなくbeginへのaddやremoveも効率的 ー * vectorと違って、連続的な保存は保証されない(ポインタ+オフセットでアクセスしちゃダメ) * beginやend以外へのinsert、removeは遅い * iteratorの定常性というかconsistencyはlistに比べると低い
ツイート
自分用Sublime Text Plugin/設定メモ
# Emacsライクな使い方にする為にST3のほうがおすすめな印象 * SublemacsPro * 基本的なキーバインドはこれで * IMESupport(Win) * Windowsの場合は日本語入力をインライン化する為に必要 * Alignment * Brackethighlighter * AutoFileName * OrigamiEmacs (ST2の場合のみ、ST3には同様の機能が入ってる) * ペインの分割とそのショートカット 参考サイト:http://xoyip.hatenablog.com/entry/2014/03/27/211804 * Markdown用 * OmniMarkupPreviewer Ctrl+Alt+Oでデフォルトブラウザでプレビューしてくれるらしいが、 Ubuntu?SublemacsPro?だからか効かななった。でも右クリックからプレビュー表示が可能なので問題なし * Trailing Spaces 改行になるスペースx2をハイライトしてくれてグー * monokai extended * Markdown Extended * KeyBinding ST3の時(Macでは不要だった) * ctrl+hのキーをleft_deleteに切り替える ``` { "keys": ["ctrl+h"], "command": "left_delete" }, // for markdown { "keys": ["shift+enter"], "command": "insert_snippet", "args": {"contents": " \n"}}, ``` * Preference追加した項目を晒す ``` "theme": "Flatland Dark.sublime-theme", "color_scheme": "Packages/Theme - Flatland/Flatland Dark.tmTheme", "flatland_square_tabs": false, "translate_tabs_to_spaces": true, "highlight_line": true, "draw_white_space": "all", ```
ツイート
2014/03/08
QCustomPlotで表示したグラフをマウスホイールズームやDragシフトする際の範囲を制限する
[QCustomPlotでマウスホイールズーム&Dragでシフト](http://kohshi.blogspot.jp/2014/03/qcustomplotdrag.html)で紹介したようにほんの数行加えるだけで、 表示領域を操作できるのだが、0原点だけはズームやシフトしたい場合にも固定したい場合は結構多い。 そういう時はどういう風にするかを紹介する。 [ここ](http://www.qcustomplot.com/index.php/support/forum/289)で書かれている内容だが、 まず、制限したいQCPAxisのrangeChangedシグナルにslotを接続する↓。 ```cpp MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); mpHistogramBars = new QCPBars(ui.histogram->xAxis, ui.histogram->yAxis); mpHistogramBars->setPen(QPen(Qt::gray));// 色指定 mpHistogramBars->setBrush(QBrush(Qt::gray));// 色指定 ui.histogram->addPlottable(mpHistogramBars);// 追加 ui.histogram->setInteraction(QCP::iRangeDrag, true); ui.histogram->setInteraction(QCP::iRangeZoom, true); ui.histogram->axisRect()->setRangeDrag(Qt::Vertical); ui.histogram->axisRect()->setRangeZoom(Qt::Vertical); // yAxisRangeChanged()はslot connect(ui.histogram->yAxis, SIGNAL(rangeChanged(const QCPRange &)), this, SLOT(yAxisRangeChanged(const QCPRange &))); } ``` のようにしておいてRangeが変わったら、すなわちズームやシフトが発生したらyAxisRangeChangedが呼ばれるようにしておき、 yAxisRangeChangedの中で以下のようにRangeを再セットしてやる。 ```cpp void MainWindow::yAxisRangeChanged(const QCPRange &newRange) { ui.histogram->yAxis->setRange(0, ui.histogram->yAxis->range().upper);// y軸の下限を0に固定 } ``` 当然、マイナスの値にはしたくないという制限の場合には以下のようになる。 ```cpp void MainWindow::yAxisRangeChanged(const QCPRange &newRange) { if(newRange.lower < 0){ ui.histogram->yAxis->setRange(0, ui.histogram->yAxis->range().upper); } } ``` 常に下限を0にした場合こんな感じになる
ツイート
2014/03/07
QCustomPlotでマウスホイールズーム&Dragでシフト
あんまり簡単なんで書くのもなんなのだが・・・。 ```cpp MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); mpHistogramBars = new QCPBars(ui.histogram->xAxis, ui.histogram->yAxis); mpHistogramBars->setPen(QPen(Qt::gray));// 色指定 mpHistogramBars->setBrush(QBrush(Qt::gray));// 色指定 ui.histogram->addPlottable(mpHistogramBars);// 追加 // 以下を追加する事でマウスホイールズームとDragでシフトができるようになる ui.histogram->setInteraction(QCP::iRangeDrag, true); ui.histogram->setInteraction(QCP::iRangeZoom, true); // 例えばさらに垂直方向(y軸方向)だけズームやシフトすると制限する事も可能 ui.histogram->axisRect()->setRangeDrag(Qt::Vertical); ui.histogram->axisRect()->setRangeZoom(Qt::Vertical); } ``` これだけでマウスホイールズームとDragでのシフトができるようになる。 こんな感じ
[次回](http://kohshi.blogspot.jp/2014/03/qcustomplotdrag_8.html)ではシフト・ズーム範囲を制限してみる。
ツイート
2014/02/17
popplerを使ってpdfファイルをQImageに読み込む(おまけにQimageをpdfファイルとして書き出す)
[前回](http://kohshi.blogspot.jp/2014/02/popplerhomebrew.html)でインストールしたpopplerを使ってQtアプリでpdfファイルを読み込む。 今回はpdfといってもページ=画像ファイルなのでわりと簡単。 ```cpp #include
openPdfFile(QString fileName){ Poppler::Document *doc = Poppler::Document::load(fileName); if(doc == 0) return; for(int pageNum = 0; pageNum < doc->numPages(); pageNum++){ Poppler::Page *pdfPage = doc->page(pageNum); QImage image = pdfPage->renderToImage(); // このimageを使って描画処理等を行う // pdfPageは使い終わったらdeleteが必要 delete pdfPage; } // docは使い終わったらdeleteが必要 delete doc; } ``` 一方でpdf出力に関しては、これもテキストを出力するのでなければQt自体がもっているpdf出力を使えるので 以下のようにすればQImageをページいっぱいに描画したpdfが出力できる。 ```cpp exportPagesAsPdf(QString fileName){ // QtはQPrinterをつかってpdfファイル出力ができる QPrinter printer(QPrinter::HighResolution); printer.setOutputFormat(QPrinter::PdfFormat); printer.setPageMargins(0, 0, 0, 0, QPrinter::Point);// margin 0にして縁なしにする printer.setOutputFileName(fileName); const int dpi = 72; printer.setResolution(dpi); QPainter painter; for(int i = 0; i < mPages.size(); i++){ QImage image = mPages[i].image(); // 仮に毎ページサイズが変わってもOKにしてる printer.setPaperSize(image.size(), QPrinter::Point); if(i == 0){ painter.begin(&printer);// 最初のページはnewPage()をいれてはいけないので特別処理 } else{ printer.newPage();// サイズを指定した後にnewPage()を呼ぶとそのサイズのPageが挿入される } painter.drawImage(0, 0, image); } } ``` dpiをなぜ72にしたらいいのか実はちょっとわかってないんだが、[popplerのdocumentのPage::renderToImage()](http://people.freedesktop.org/~aacid/docs/qt4/classPoppler_1_1Page.html)のdpiのデフォルト引数が72.0だったので、一緒にしたらいいんじゃないかなぁと思ったらうまくいった。 QPrinterのAPIをみるとテキストをセットするようなものはないので、 OCRしたテキストをpdfに埋め込みたい時には多分QPrinterでは無理なんじゃないかな? きっと[Handling PDF](http://qt-project.org/wiki/Handling_PDF)にあるようにほかのthird partyライブラリを 使えばできるんだろうけど。今回はまぁこの辺で。
ツイート
popplerをhomebrewを使ってインストール
最近、ドキュメントスキャナを購入してから細々と自炊して本・マンガ本の省スペース化を図っている。 Windowsは[eTritran](http://no722.cocolog-nifty.com/blog/etiltran/)という素晴らしいソフトがあるが、 Macで同じような事(簡単なトーンカーブ補正、ページ回転等々)をやろうとした時に、 ちょうどいいソフトが見つからなかったので、機能は制限されるがQtを使って自分で作ってたりする → こんな感じ[ePage](https://bitbucket.org/kohshi/epages/wiki/Home) 今の所zip(jpegのzip化)の解凍はquazipを使って読み込むことができるようになったんだが、 段々欲が出てきてpdfも読み書きしたくなってきた。 ということでQtにpdfを読み書きする方法があるのかと探すと・・どうもなさそう。 詳細は[Handling_PDF](http://qt-project.org/wiki/Handling_PDF)に書かれているが、 出力する事はQPrinterを使ってできるみたい。でも読む方はQtにはなくて3rd partyのライブラリを使わないといけないみたい。 こんな感じで3つほど紹介されてる。
今回は自炊した漫画本をメインで考えてるので出力はQPrinterを使って、読み込む機能があるpopplerを使う事にする。 Qt wrapperがあってQtとの親和性も高そう。 で、popplerをソースからコンパイルしてもいいんだが、freetype2が必要だったりlibpngやlibopenjpegが必要だったり 結構依存ライブラリがおおい。なので、この際今まで使った事がなかったhomebrewを使って入れてみようかなと。 homebrewとそのインストールついては[パッケージ管理システム Homebrew](http://qiita.com/b4b4r07/items/6efebc2f3d1cbbd393fc)など、いい参考サイトがあるのでそちらをみてもらうとして。 コマンド一つでインストールできる所が美しい・・。 ``` $brew update $brew install poppler --with-qt4 ``` とすると、デフォルトでは/usr/local/Cellar/以下にpopplerと依存ファイル(qt4も)インストールしてくれます。 楽だなー。 なので、.proファイルに以下を追加する事でプログラム中でpopplerを使えるようになります。 ``` LIBS += -lpoppler-qt4 INCLUDEPATH += /usr/local/Cellar/poppler/0.24.5/include DEPTHDPATH += /usr/local/Cellar/poppler/0.24.5/lib ``` 具体的な使い方は次回で。
ツイート
2014/01/07
QTableViewへ登録するQStandardItemにでユーザ定義型をくるませる
QTableView等のQ*View系のQt Model/View構造で管理されているビューを使用する場合、 もっとも簡単な使い方として、QStandardItemModelへQStandardItemをセットしていく事になる。 * QStandardItem = Table等に表示される1項目 * QStandardItemModel = Itemの集合(row/column/parent/childの概念) この際に、Tableのセルに表示させる文字列(QString)以外にユーザ定義型をQStandardItem::setDataを使って格納することができる。 個人的にはクラスのポインタを各Itemに格納させておいて、TableView(or ListView)でDrag&Dropして順番を入れ替えた後、 入れ替えた順番でクラスのポインタを順にとってくるという事をしたかった。 [このサイト(QVariant の使い方)](http://qt-project.org/wiki/How_to_use_QVariant_Japanese)によるとポインタはもたせられなくてvoid*にしなさいとあるんだが、実際にはvoid*にしてもうまくいかなかったので追加調査 参考にしたのは以下の2つのサイト * [Custom QVariant crash on drag in QTreeView](https://qt-project.org/forums/viewthread/22238) * [QMetaType Class Reference](http://qt-project.org/doc/qt-4.8/qmetatype.html) 今回はポインタだったので不要だったかもしれないが、[こちらのサイト](http://milukiriu2010.blog71.fc2.com/blog-entry-145.html)によるとユーザ定義型の場合は追加で以下の3つが必要となるよう。 * QObjectの継承 * コピーコンストラクタの定義 * 代入演算子の定義 以下ではMyClassのconstポインタをQStandardItemに格納している。 まず、下準備として以下が必要。 ```cpp // const MyClass*をQMetaTypeとして使いますよという宣言 Q_DECLARE_METATYPE(const MyClass*); // 以下のoperator定義はDrag&Dropをしたい場合に必要 // もしやらないと、"QVariant Invalid type to save" のようなエラーが大量にでる // see. https://qt-project.org/forums/viewthread/22238 QDataStream& operator<<(QDataStream& out, const MyClass* const& rhs) { out.writeRawData(reinterpret_cast
(&rhs), sizeof(rhs)); return out; } QDataStream& operator >> (QDataStream& in, const MyClass*& rhs) { in.readRawData(reinterpret_cast
(&rhs), sizeof(rhs)); return in; } // const MyClass*をQMetaTypeとして使う前(たとえばコンストラクタ)に以下を書く MyApp::MyApp(){ qRegisterMetaTypeStreamOperators
("const MyClass*"); } ``` そして、実際に値をセットするときは ```cpp void MyApp::setData(QList
myClasses){ QStandardItemModel* model = qobject_cast
(myTableView->model()); foreach(const MyClass* class, myClasses) { QStandardItem* item = new QStandardItem(class->name()); item->setData(QVariant::fromValue(class)); model->appendRow(item); } } ``` な感じでセット(myTableView => QTableView*ね) 逆に値を引っ張ってくる時は ```cpp QList
MyApp::getData(){ QStandardItemModel* model = qobject_cast
(myTableView->model()); QList
myClasses; const int COLUMN_NO = 0;// setDataでMyClass*を格納したQStandardItemが入っているColumn番号 = 0 for (int i = 0; i < model->rowCount(); i++) { myClasses.push_back(model->item(i, COLUMN_NO)->data().value
()); } return myClasses; } ``` のような感じで取得できる。
ツイート
新しい投稿
前の投稿
ホーム
登録:
投稿 (Atom)