QT2.3.10下冒泡式弹出式对户框的制作

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);

}

 

最后的效果图如下:

 

 

你可能感兴趣的:(QT2.3.10下冒泡式弹出式对户框的制作)