2008年9月3日 星期三

qt - canvas - 動畫播放

QCanvasSprite 可以根據一組給定的圖片進行連續的圖片播放,這組圖片是設定在QCanvasPixmapArray類別中,QCanvasPixmapArray中的圖片都是以索引來管理,我們可以使用setImage()方法來讀入圖片,我們使用setSequence()指定這組 QCanvasPixmapArray圖片給QCanvasSprite物件。

下面這個程式很簡單,示範如何使用QCanvasSprite進行動畫播放,畫面會有兩隻小毛蟲進行賽跑,不斷的一伸一縮並向右移動:

在QCanvasSprite的精神就是設定一個物件,它的顯示圖片可以變化~
這一個例子就是兩個圖片一直循環變化~
因為QCanvasSprite是繼承QCanvasItem,所以,呼叫void QCanvasItem::setVelocity ( double vx, double vy ) [virtual],可以設定它的移動速度~

main.cpp

#include <qapplication.h>
#include <qcanvas.h>
#include <qimage.h>

class Caterpillar : public QCanvasSprite {
public:
  Caterpillar(QCanvas *canvas) : QCanvasSprite(0, canvas) {
    static QCanvasPixmapArray ani;

    ani.setImage(0, new QCanvasPixmap("cater1.jpg")); // 讀入一組圖片
    ani.setImage(1, new QCanvasPixmap("cater2.jpg"));

    setSequence(&ani); // setup圖片組

    setFrameAnimation(QCanvasSprite::Cycle); // 循環播放
  }
};

class View : public QCanvasView {
public:
  View(QCanvas& canvas) : QCanvasView(&canvas){
    canvas.resize(300, 200);
    setFixedSize(sizeHint());

    Caterpillar *cater1 = new Caterpillar(&canvas);
    cater1->move(250, 50);
    cater1->setVelocity(-1, 0);
    cater1->setZ(10);
    cater1->show();

    Caterpillar *cater2 = new Caterpillar(&canvas);
    cater2->move(250, 100);
    cater2->setVelocity(-1.5, 0);
    cater2->setZ(10);
    cater2->show();
  }
};

int main(int argc, char** argv) {
  QApplication app(argc, argv);

  QCanvas canvas(0, 0);

  canvas.setAdvancePeriod(500); // 移動更新間隔,同時,每500ms會變換圖片一次
  canvas.setDoubleBuffering(true); // double buffer
  View c(canvas);

  app.setMainWidget(&c);
  c.show();

  return app.exec();
}


參考資料:
QCanvas 類別 - QCanvasSprite 動畫播放

網路上的blog - 學習歷程

用來記錄網路上有人的學習歷程,以後,無聊的時候可以看哩~
還在思考要如何分類~
就把每一個blog有我想要的分類放在超聯結上面吧~到時候用ctrl+F去找就好了~

史丹利部落格

B生的部落格

[賴榮樞]的軟體資訊誌


軟體工程師:謝坤龍

資訊工程師...
MrMo.cc

Embedded Linux經驗分享

工程師的網頁
大頭鰱的部落格格

某一個老師的網頁
Jing Mine Chuan(井民全)

vim
Rickey's pets

正因為活著
linux學習筆記

C/C++、PHP、Linux、Windows
記錄生活點滴及IT學習筆記


心情、雜事、好文
▁▂▃▄ⓟⓔⓣⓔⓡⓙⓐⓜⓔⓢ▄▃▂▁

C++、C、PHP、Linux、ASP
心情雜物間

PHP、雜
慢條斯理的溫柔

雜
Tsung's Blog

C++、C、PHP、ASP、Linux、雜
尺有所短,寸有所長

電腦-雜
世樺部落格

電腦-雜、C++/C、QT
擴擴咱 2.0

電腦-雜
矇矇的秘密基地

電腦-雜-8051-linux device driver-C/C++
啾啾ㄟ部落格

電腦-程式教學
Victor's程式設計教學

軟體品質
中文品質筆記

電腦-雜-linux
小惡魔 - 電腦技術 - 生活日記 - 美食介紹 - AppleBOY

電腦、旅遊、linux、雜
麥雞來福

emacs、數學、心情,筆記
炎龍的筆記本

網路
研究手記--我的研究生活

c/c++、 ANN、Dreamweaver、EP/GP、Fedora、Firefox、Fireworks、Flash、Flex、Gtk/Qt/wxWidget、Java、Perl、Short Flim、SQL、SSH/SSL、Ubuntu、Windows
#define KNOWLEDGE FREE

2008年9月2日 星期二

qt -canvas - 物件之間的碰撞

現在要開始研究如何讓canvasitem之間的物件碰撞時,會觸發碰撞的訊息~

非常好~在QT中就內建了這一個函數!

bool QCanvasItem::collidesWith ( const QCanvasItem * other ) const [pure virtual]

這一個透過上一篇文章的例子做一些修改,可以知道這一個可以正確運作無誤~

void contentsMousePressEvent(QMouseEvent *e)
{
  r->move(e->pos().x(), e->pos().y());
  if (r->collidesWith(p))
    t->setText("Collision");
  else
    t->setText("That is ok!");
}

當我按滑鼠時,程式會判斷三角型與正方型是否有碰撞~

基本上應該是要讓程式自己去偵測兩物是否有碰撞,而不是我去按滑鼠後,才去偵測~

目前我知道設定完setAdvancePeriod後,時間到後會自動呼叫advance(),
基本上偵測的function應該是要放在advance()裡面~
但是,void QCanvas::advance () [virtual slot]是父類別的function,而時間到的時候呼叫的是父類別的advance(),那麼應該如何修改,才會讓它呼叫子類別另外定義的advance哩~這是我目前需要解決的問題~明天試試看,先新建一個類別繼承QCanvas,然後,重新定義advance()試試看~有點累了~回家睡覺吧~

[2008.09.3 更新]
在今天早上研究到現在總算成功的讓每30毫秒就去判斷一次物件是否有碰撞到~
話不多說~直接把程式碼貼上來吧~我覺得我的方法還蠻笨的,沒有用到物件導向的精神~
我想當我上過這一個學期的物件導向後,應該會有更深入的認知吧~

說明主要的精神:
現在有兩個類別myqcanvas、View這兩個類別,而在main.cpp設定myqcanvas的velocity後,每30ms會呼叫advance()一次。因此我另外改寫了myqcanvas的advance,這裡有用到virtual function的觀念,請參考c++ - virtual function。
本來View、myqcanvas是兩個獨立的類別,但是,為了要讓View中的兩個圖形可以在myqcanvas的advance()判斷是否有碰撞,因此,在View中設定了三個回傳指標的public function。並在myqcanvas設定一個function可以設定這三個物件的指標。
本來每30豪秒會呼叫QCanvas::advance(),但是,因為,它是virtual function,所以,當我重新宣告一個advnace()時,就算是QCanvas指標指到MyQcanvas的物件,當透過QCanvas指標呼叫advance()時,就會是呼叫我新增的advance()了,而不是QCanvas的advance()~因此,完成了這一個碰撞的目標了~
myqcanvas.h

#ifndef MYQCANVAS_H
#define MYQCANVAS_H

#include <qcanvas.h>

class MyQCanvas:public QCanvas
{
Q_OBJECT
  public:
    MyQCanvas(int w=0,int h=0);
    void setAddress(QCanvasPolygon*,QCanvasRectangle*,QCanvasText*); // 新增的部分,設定這三個物件的指標
  protected:
    void advance(); // 修改父類別的virtual function

  private:
    QCanvasPolygon *my_p; // 新增的變數,用來記錄多角形的指標
    QCanvasRectangle *my_r; // 新增的變數,用來記錄方形的指標
    QCanvasText *my_t; // 新增的變數,用來記錄文字的指標
};

#endif // MYQCANVAS_H

myqcanvas.cpp

#include "myqcanvas.h"

MyQCanvas::MyQCanvas(int w,int h):QCanvas(w,h)
{
  // do nothing
}

void MyQCanvas::advance() // 新增的部分
{
  if (my_r->collidesWith(my_p)) // 判斷是否有發生碰撞
    my_t->setText("Collision");
  else
    my_t->setText("There is no Collision!");

  QCanvas::advance(); // 衍生類別呼叫基底類別的advance function
}

void MyQCanvas::setAddress(QCanvasPolygon* p,QCanvasRectangle* r,QCanvasText* t)
{
  my_p = p;
  my_r = r;
  my_t = t;
}

view.h

#ifndef VIEW_H
#define VIEW_H

#include <qcanvas.h>

class View:public QCanvasView
{
Q_OBJECT
  public:
    View(QCanvas& canvas);
    QCanvasPolygon* getPolygon() const; // 新增的function,用來傳回多角形的指標
    QCanvasRectangle* getRectangle() const; // 新增的function,用來傳回方形的指標
    QCanvasText* getText() const; // 新增的function,用來傳回文字的指標

  protected:
    void contentsMousePressEvent(QMouseEvent *e);

  private:
    QCanvasPolygon *p;
    QCanvasRectangle *r;
    QCanvasText *t;
};

#endif // VIEW_H

view.cpp

#include <qfont.h>
#include <qimage.h>

#include "view.h"

View::View(QCanvas &canvas):QCanvasView(&canvas)
{
  canvas.setBackgroundPixmap(QPixmap("logo.jpg"));
  canvas.resize(370,300);
  setFixedSize(sizeHint());

  p = new QCanvasPolygon(&canvas);
  QPointArray a;
  a.setPoints(3,50,100,200,200,50,200);
  p->setPoints(a);
  p->setBrush(Qt::blue);
  p->setZ(10);
  p->show();

  r = new QCanvasRectangle(100,100,50,100,&canvas);
  r->setVelocity(0.5,0);
  r->setBrush(Qt::red);
  r->setZ(10);
  r->show();

  t = new QCanvasText("What will you",&canvas);
  t->setFont(QFont("Helvetica",12,QFont::Bold));
  t->setColor(Qt::blue);
  t->setZ(20);
  t->setTextFlags(AlignBottom);
  t->move(5,20);
  t->show();
}

void View::contentsMousePressEvent(QMouseEvent *e)
{
  r->move(e->pos().x(),e->pos().y());
}

QCanvasPolygon* View::getPolygon() const
{
  return p;
}

QCanvasRectangle* View::getRectangle() const
{
  return r;
}

QCanvasText* View::getText() const
{
  return t;
}

main.cpp

#include <qapplication.h>

#include "view.h"
#include "myqcanvas.h"

int main(int argc,char** argv)
{
  QApplication app(argc,argv);

  MyQCanvas canvas(0,0);

  View c(canvas);
  canvas.setAddress(c.getPolygon(),c.getRectangle(),c.getText()); // 新增的部分
  canvas.setAdvancePeriod(30);
  canvas.setDoubleBuffering(true);

  app.setMainWidget(&c);
  c.show();

  return app.exec();
}


參考資料:回傳指標資料範例

qt - canvas

除了使用QPainter相關類別來進行簡單的繪圖之外,我們還可以使用Qt所提供的繪圖模組QCanvas,每一個QCanvas繪圖都是一個物件,可以分別為它們設定位置與深度,也可以設定移動速度,在製作動畫上相當的方便。

在繪圖時,我們準備一個QCanvas物件,它就像是一塊畫布,我們在這塊畫布上畫上QCanvasItem物件,是否顯示一個QCanvasItem物件可以使用show()方法來控制,而觀看繪圖結果時是使用QCanvasView物件。

在程式撰寫上,我們繼承QCanvasView類別,將QCanvas傳遞給它,然後定義每個QCanvasItem繪圖方法;我們將這個QCanvasView類別當作Qt的主Widget,就可以顯示在視窗上。

下面這個程式是個簡單的示範,畫面中的長方形會不斷的往右移動,您可以使用滑鼠將之設定回來,而由於我們設定了深度,所以長方形會一直被三角形所覆蓋:
main.cpp

#include <qapplication.h>
#include <qcanvas.h>
#include <qfont.h>
#include <qimage.h>

class View : public QCanvasView {
public:
  View(QCanvas& canvas) : QCanvasView(&canvas){
    canvas.setBackgroundPixmap(QPixmap("logo.jpg"));
    canvas.resize(370, 300);
    setFixedSize(sizeHint());

    p = new QCanvasPolygon(&canvas); // 多邊形
    QPointArray a;
    a.setPoints(3, 50, 100, 200, 200, 50, 200); // 意思是共有3個點分別為(30,100)、(200,200)、(50,200)
    p->setPoints(a);
    p->setBrush(Qt::blue);
    p->setZ(10); // 深度
    p->show(); // 顯示繪圖物件

    r = new QCanvasRectangle(100, 100, 50, 100, &canvas); // 四方形
    r->setVelocity(0.5, 0); // 移動速度
    r->setBrush(Qt::red);
    r->setZ(10);
    r->show();

    t = new QCanvasText("What will you study today? ^o^", &canvas); // 文字
    t->setFont(QFont("Helvetica", 12, QFont::Bold));
    t->setColor(Qt::blue);
    t->setZ(20);
    t->setTextFlags(AlignBottom);
    t->move(5, 20);
    t->show();
  }


protected:
  void contentsMousePressEvent(QMouseEvent *e) {
    r->move(e->pos().x(), e->pos().y());
  }

private:
  QCanvasPolygon *p;
  QCanvasRectangle *r;
  QCanvasText *t;

};

int main(int argc, char** argv) {
  QApplication app(argc, argv);

  QCanvas canvas(0, 0);

  canvas.setAdvancePeriod(30); // 移動更新間隔:
  canvas.setDoubleBuffering(true); // double buffer
  View c(canvas);

  app.setMainWidget(&c);
  c.show();

  return app.exec();
}

QCanvas的畫面更新是由setAdvancePeriod()來控制,配合QCanvasItem的setVelocity()方法,就可以製作出移動的效果,下圖為執行的結果畫面:


virtual void advance ( int phase )
當phase是1時,QCanvasItem就依速率在移動;當phase是0時,QCanvasItem就算有設速率,一樣不會有動作。

參考資料:Qt3 Gossip: QCanvas 類別 - 簡單深度與移動設定

延伸閱讀:
Canvas Example
Qt開發雜記(三)

如何辦認電容的好壞

老弟傳來訊息說因為LCD換了新的電容,可以不用整個LCD都換掉,省了一筆錢哩~

消費者不可不知的權利
國內有些公司(如華碩,技嘉等等)針對生產品皆有免費換電容服務
 不論保固期與否,如有電容目視如上文所述之(A級明顯不良品.或B級不良品)免費更換電容不收取任何檢測費及任何零件費
 即使不清楚是否故障與否之產品若有明顯不良品之電容問題,也可送回更換
 更換完畢將例行性測試產品功能是否正常
 如果更換電容尚有其他故障將再次報價(顧客也可不付任何費用取回)


介紹主角-電解質電容


 電路板上會有一些圓柱體,側面膠皮也並標示了以uF和V為單位物體
 (例:常見的有3300uF6.3V)
參考資料:富大電腦工作室

2008年9月1日 星期一

QT - 建立一個空心圓

修改example08的
cannon.cpp

void CannonField::paintEvent( QPaintEvent * )
{
 QPainter p( this );
 p.setBrush( NoBrush );
 p.setPen( red ); // 讓圖的外圍為紅色畫的
 p.drawEllipse(0,0,120,120);
 s = "Angle = " + QString::number(ang);
 p.setPen( SolidLine );
 p.drawText(rect(),AlignCenter,s);
}


明天任務:畫出一個有顏色的空心圓畫出來啦~就在原程式改一下就好啦~結果在上面啦~

測出來的結果就算是空心圓,實際上其實不是~只是空心的部分沒有畫出來而以。基本上還是要用Canvas來畫會比較好~而且基本上Canvas本身就使用雙緩沖哩~另外,可以根據需要更新的部分去更新就好哩,不會整個都刪掉再重畫哩~

計算機網路實驗 - 以NS2模擬工具實作

這是我今天看了這一本書的大綱:

NS2是一套物件導向的網路模擬器,由UC Berkeley完成,具有模擬真實系統的架構和特性
網路架構:模擬router、link、end-point
網路特性:packet delay、packet drop

第二章:TCL語法
可以參考這裡~作者的網站

第三章:
TCP與UDP模擬實驗
呈現網路效能、評比指標:
1. End-to-End Delay
2. Jitter - 兩個封包傳送的延遲時間的差異
3. Packet Loss
4. Throughput
在NS2中,我們都透過awk去分析出來的報表

第四章:亂數產生器(Random Number Generator)
如何產生合乎現實的例子
NS2提供Pareto、Constant、Uniform、Exponential、HyperExponential

第五章:信賴區間(Confidence Interval)
這裡是說明什麼是信賴區間,這一個在網路上找有一堆資料
1. 母群體(population):為特定研究的所有元素所組成的集合
2. 樣本(sample):母群體的部分集合
3. 母群體平均數(population mean)
4. 樣本平均數(sample mean)
5. 變異數(variance)
6. 樣本變異數(sample variance):由母群體取出一部分樣本的變異數
7. 母群體標準差(standard deviation)
8. 樣本標準差(sample standard deviation)
9. 信賴區間(confidence interval)
求得一個機率範圍(probability bound)使母群體平均有很高的機率能在上限c1與下限c2的範圍內
(1). 信賴區間
(2). 顯著水準

中央極限定理 (Central Limit Theorem)
商用統計學

第六章:佇列管理機制
被動式佇列:DropTail
基於路由器的RED和Droptail算法比較
佇列管理演算法
主動式佇列:RED(Random Early Detection)
主動式會在佇列滿之前就把封包丟棄。

第七章:路由(Dynamic Routing)
靜態路由(static route):由網管人員手動輸入。優點:頻寬都用在傳送資料;缺點:路由器不會主動發現新的router
動能路由(dynamic route):根據協定(routing protocol)或演算法來動態維護路由表中的內容。優點:router彼此交換訊息不用手動維護routing table。缺點:需要消耗網路的頻寬。
預設路由(default router):預設路由是當router無法判斷IP封包轉送的路徑時,就會將封包送往一個預設的閘道器(default gateway)

在決定router table時,會依到達目地的時的成本來考量,這裡的成本可以是hop count、propagation delay、load、bandwidth、reliability

第八章:TCP提供reliable傳輸服務具flow control、congestion control

第十一章:同步化現象(TCP Global Synchronization)
由於網路上的TCP Connection可能會在不同的時間啟動,因此當一個新的TCP Connection進入網路時,在這一個時間點上,它的Congestion window (cwnd)和其它的TCP Connect的cwnd大小可能是不同的,那麼這一些TCP Connection要怎麼公平地競爭頻寬呢?

第十二章:影響TCP效能的幾個因素
1. Round-Trip (RTT):當同時有多個TCP Connection共同相同的Link時,由於RTT較短的Connection等待ACK開啟Congestion window的時間較短,因此和RTT時間較長的TCP Connection比較起來,資料傳輸的效能會比較好。
2. Timer Granulariy:一般而言,通常TCP在實際運作時,並不會真的隨時去注意封包是否過期,而是設定一個時間值,稱為"Coarse-grain timer",每隔一段時間才去檢查是否有封包已經Timeout了。因此,當有封包遺失時,這意謂著一個封包從遺失到直到timeout被重送的時間也會大大的增長。
3. Slow-start threshold:ssthresh的值決定終止slow-start、開始進入Congestion avoidance時window的大小。若設的太小,會使得TCP因為太早進入Congestion avoidance階段,而使得頻寬的使用率變的很差。
4. 封包大小、網路的佇列管理機制、有線/無線的環境。

第十五章:資料流整形器 (Traffic Shaper)
1. 漏桶演算法 (leaky bucket algorithm)
2. 令牌桶演算法 (token bucket algorithm)