Qt2.3.10製作冒泡式彈出對話框

Snail    07年7月第一個星期製作

製作冒泡式彈出對話框主要涉及2個技術要點(主要供觸摸屏使用)

1 實用的Qtimer類的使用(計算鼠標在對象上的停留時間確定是否彈出屬性對話框)

2 漂亮的對話框的繪製(主要是QWidget::setMask(const QBitmap& bitmap)的使用)

 

詳細分析:

QTimer類的使用

QTimer的一般性使用

QTimer *timer = new QTimer( myObject );

    connect( timer, SIGNAL(timeout()),

             myObject, SLOT(timerDone()) );

timer->start( 2000, TRUE );                 // 2 seconds single-shot

注意: 1 myObject銷燬時,Qtimer會自動銷燬。不需要手工刪除。

2         QTimerint start ( int msec, bool sshot = FALSE )  方法第二個參數sshot如果

ture,則myObject的槽方法只會執行一次。不然的話會一直執行直到QTimer停止或者對象被銷燬爲止。

 

在本程序中如何使用QTimer

//頭文件

class MainPanel : public QWidget {                 // MainPanel爲被測試面板,測試彈出屬性框

         Q_OBJECT

public:

         MainPanel(QWidget *parent=0, const char *name=0, WFlags fl = 0);

         ~MainPanel() {}

public slots:

         void holdMouseToPopupDialog();            //QTimer鏈接的槽,確定是否彈出屬性框

protected:

         virtual void mousePressEvent ( QMouseEvent * );    //這三個虛函數需要被覆蓋用作計時

         virtual void mouseReleaseEvent(QMouseEvent *);

         virtual void mouseMoveEvent(QMouseEvent *);

private:

         QPoint* __popupPoint;                     //彈出面板的座標,也就是要顯示屬性的物體

         PopupInfoDialog* __propDialog;                //這個屬性框的製作放到後面

         QTimer* __mouseHoldClicker;                 //創建一個Qtimer類成員對象

};

//代碼文件

MainPanel::MainPanel(QWidget *parent, const char *name, WFlags fl) :QWidget(parent, name, fl) {

         __propDialog = new PopupInfoDialog(720,480,this,0,0,QDialog::WStyle_Customize | QDialog::WStyle_NoBorder | QDialog::WStyle_StaysOnTop);

         __mouseHoldClicker = new QTimer(this);                   

         __popupPoint = new QPoint();                                                      //創建一個默認彈出點

         connect(__mouseHoldClicker, SIGNAL(timeout()), this, SLOT(holdMouseToPopupDialog()));   //鏈接QTimer和麪板

}

 

void MainPanel::mousePressEvent(QMouseEvent * e) {     //這個方法的意思是如果當鼠標按下(觸摸屏的話就是手指按下)

         __popupPoint->setX(e->x());                               //保存當前的座標點

         __popupPoint->setY(e->y());

         __propDialog->hide();                                    //隱藏以前出現的彈出式屬性框

         __mouseHoldClicker->start(500, true);                     //0.5秒計時,如果手指沒有離開這個點,或者沒有移動,則

                                                          //觸發holdMouseToPopupDialog()槽一次。

}

 

void MainPanel::mouseReleaseEvent(QMouseEvent * e) {          //這個方法的意思是如果手指離開觸摸屏,就。。。

         __mouseHoldClicker->stop();                   //如果在槽還沒有觸發前就停止計時器,這樣不用彈出屬性框了

}

 

void MainPanel::mouseMoveEvent(QMouseEvent * e) {            //這個方法的意思是如果手指移動了的話,就。。。。。。。。

         if (e->x()-__popupPoint->x()>5 || e->y()- __popupPoint->y()>5) {  //如果手指在5個像素內移動,就認爲可接受的,如果超過5

                   __mouseHoldClicker->stop();                           //像素,則不予彈出對話框

         }

}

 

void MainPanel::holdMouseToPopupDialog() {                    //測試面板的槽,用來彈出屬性框

         __propDialog->popupAtPoint(__popupPoint->x(), __popupPoint->y());

         __propDialog->show();

}

 

 

在本程序中繪製漂亮的對話框

class PopupInfoDialog : public QDialog {

         Q_OBJECT

public:

         PopupInfoDialog (int areaWidth = 800 ,int areaHeight = 600,QWidget * parent=0, const char * name=0, bool modal=FALSE, WFlags f=0 );

         void popupAtPoint(int x,int y);

 

private:

         void __refreshMask(int popX, int popY);                        //重新刷新蒙板,隱藏對話框該的一些不需要顯示的地方。

         void __fillArrow(QPainter&,int,int,int,int,int,int);                   //這個是畫這個東東的---à

void PopupInfoDialog::popupAtPoint(int x, int y) {                   //對話框就彈出在這個點,在測試面板的             

//holdMouseToPopupDialog()中調用此方法。

         this->__refreshMask(x, y);

         this->show();

}

 

/*在這裏,大致的實現過程是這樣,QWidget可以通過一個QBitmap蒙板來大致決定需要顯示哪些部分,我們就通過繪製蒙板來讓QWidget顯示蒙板同樣大小區域來實現繪製任意形狀的對話框的效果*/

 

void PopupInfoDialog::__refreshMask(int popX, int popY) {            //重新刷新蒙板

         QBitmap mask(__PopupWidth, __PopupHeight, true);             //創建一個蒙板

         QPainter painter(&mask);                                   

         painter.setPen(popupBorder);

         painter.setBrush(blackBrush);                                 //必須設置筆刷,得把繪製區域全部填充滿

         painter.drawRoundRect(50, 0, 300, 300, 10, 10);//300是實際顯示內容框,10爲圓角矩形圓角半徑

 

         int distanceToBorder;

         if (__areaWidth-popX >= __PopupWidth-50) {//右邊能容納彈出框  //這是一個簡單的算法,在對象右邊能顯示對話框就在右邊

                   if (popY <= __areaHeight/2) {//三角符號在彈出框的上邊             //繪製屬性對話框,不然就在左邊繪製屬性對話框。

                            if (popY <= __DialogToBorderDistance) {

                                     distanceToBorder = popY;

                            } else {

                                     distanceToBorder = __DialogToBorderDistance;

                            }

                            __fillArrow(painter, 0, popY-distanceToBorder+20, 50, 100-20, 50, 100+20);

                            this->move(popX, distanceToBorder);

                   } else {//三角符號在彈出框的下邊

                            int dx = popX;

                            int dy = __areaHeight-__PopupHeight-__DialogToBorderDistance;

                            if ((__areaHeight - popY) <= __DialogToBorderDistance) {

                                     dy = __areaHeight-__PopupHeight-(__areaHeight - popY)+20;

                            }

                            __fillArrow(painter, 0, popY-(dy-20), 50, 200-20, 50, 200+20);

                            this->move(dx, dy);

                   }

         } else {//彈出框放在左邊

                   if (popY <= __areaHeight/2) {//三角符號在彈出框的上邊

                            if (popY <= __DialogToBorderDistance) {

                                     distanceToBorder = popY;

                            } else {

                                     distanceToBorder = __DialogToBorderDistance;

                            }

                            __fillArrow(painter, __PopupWidth, popY-distanceToBorder+20, __PopupWidth-51, 100-20, __PopupWidth-51,

                                               100+20);

                            this->move(popX-__PopupWidth, distanceToBorder);

                   } else {//三角符號在彈出框的下邊

                            int dx = popX-__PopupWidth;

                            int dy = __areaHeight-__PopupHeight-__DialogToBorderDistance;

                            if ((__areaHeight - popY) <= __DialogToBorderDistance) {

                                     dy = __areaHeight-__PopupHeight-(__areaHeight - popY)+20;

                            }

                            __fillArrow(painter, __PopupWidth, popY-dy+20, __PopupWidth-51, 200-20, __PopupWidth-51, 200+20);

                            this->move(dx, dy);

                   }

         }

         this->clearMask();                                            //清除原來的蒙板效果

         this->setMask(mask);                                         //添加新的蒙板效果

}

 

/*這個方法通過在給定的三點繪製多邊形,達到繪製屬性框箭頭的效果 */

void PopupInfoDialog::__fillArrow(QPainter& painter, int p1x, int p1y, int p2x, int p2y, int p3x, int p3y) {

         QPointArray points;

         points.setPoints(3, p1x, p1y, p2x, p2y, p3x, p3y);

         painter.drawPolygon(points);

}

 

最後的效果圖如下:

 

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章