QT常用例程收集整理(易集成至主工程)

来源:互联网 发布:中国网络为什么多喷子 编辑:程序博客网 时间:2024/06/06 03:58


悬浮窗口,不规则窗口

http://blog.csdn.net/small_qch/article/details/7054750

QT TableViewe:

http://blog.csdn.net/qq61394323/article/details/12947983

QT 自定义按钮

http://blog.csdn.net/starcloud_zxt/article/details/5185556

QT的GridLayout设置

http://qimo601.iteye.com/blog/1413634

QT 鼠标右键菜单

http://blog.csdn.net/tju355/article/details/7652327


QT串口编程Linux和Windows

http://www.360doc.com/content/11/0420/23/6139921_111155547.shtml



QWidget及其子类都可有右键菜单,因为QWidget有以下两个与右键菜单有关的函数:

Qt::ContextMenuPolicy contextMenuPolicy () const

void setContextMenuPolicy ( Qt::ContextMenuPolicy policy )

Qt::ContextMenuPolicy枚举类型包括:Qt::DefaultContextMenu, Qt::NoContextMenu, Qt::PreventContextMenu, Qt::ActionsContextMenu, and Qt::CustomContextMenu。

使用方式如下:


1)默认是Qt::DefaultContextMenu。
它是利用右键菜单事件contextMenuEvent()来处理(which means the contextMenuEvent() handler is called)。就是要重写contextMenuEvent( QContextMenuEvent * event )函数。

实例:

[cpp] view plaincopy
  1. void CGuiMainwindow::contextMenuEvent(QContextMenuEvent* e)  
  2. {  
  3. QMenu *menu = new QMenu();  
  4. menu->addSeparator();  
  5. menu->addSeparator();  
  6. menu->addAction(Act_Maxsize);  
  7. menu->addSeparator();  
  8. menu->addSeparator();  
  9. menu->addAction(Act_Normal);  
  10. menu->addSeparator();  
  11. menu->addSeparator();  
  12. menu->exec(e->globalPos());  
  13. delete menu;  
  14. }  

注意,里面的action是需要自己实现编辑好的,可以在action editor内先进行编辑。


2)使用Qt::CustomContextMenu。
它是发出QWidget::customContextMenuRequested信号,注意仅仅只是发信号,意味着要自己写显示右键菜单的slot。
这个信号是QWidget唯一与右键菜单有关的信号(也是自有的唯一信号),同时也是很容易被忽略的signal:

void customContextMenuRequested ( const QPoint & pos )

该信号的发出条件是:用户请求contextMenu(常规就是鼠标右击啦)且同时被击的widget其contextMenuPolicy又是Qt::CustomContextMenu。
注意:pos是该widget接收右键菜单事件的位置,一般是在该部件的坐标系中。但是对于QAbstratScrollArea及其子类例外,是对应着其视口viewport()的坐标系。如常用的QTableView、QHeaderView就是QAbstratScrollArea的子类。
因为仅发信号,所以需自己写显示右键菜单的slot来响应,例如一个表格(QTableView类型)表头的显示右键菜单槽:
datatable->horizontalHeader()->setContextMenuPolicy(Qt::CustomContextMenu);
connect(datatable->horizontalHeader(), SIGNAL(customContextMenuRequested(const QPoint&)), 

        this, SLOT(show_contextmenu(const QPoint&)));//this是datatable所在窗口
QMenu *cmenu = NULL;
show_contextmenu(const QPoint& pos)
{
    if(cmenu)//保证同时只存在一个menu,及时释放内存
    {
        delete cmenu;
        cmenu = NULL;
    }
    QMenu cmenu = new QMenu(datatable->horizontalHeader());
    
    QAction *ascendSortAction = cmenu->addAction("升序");
    QAction *descendSortAction = cmenu->addAction("降序");
    QAction *filterAction = cmenu->addAction("过滤");
    QAction *reshowAction = cmenu->addAction("重载");
    
    connect(ascendSortAction, SIGNAL(triggered(bool)), this, SLOT(sort_ascend()));
    connect(descendSortAction, SIGNAL(triggered(bool)), this, SLOT(sort_descend()));
    connect(filterAction, SIGNAL(triggered(bool)), this, SLOT(show_filter_dlg()));
    connect(reshowAction, SIGNAL(triggered(bool)), this, SLOT(reshow_data()));
    
    cmenu->exec(QCursor::pos());//在当前鼠标位置显示
    //cmenu->exec(pos)是在viewport显示
}

也可先做好cmenu,好处是始终使用一个:
    QMenu cmenu = new QMenu(datatable->horizontalHeader());
    
    QAction *ascendSortAction = cmenu->addAction("升序");
    QAction *descendSortAction = cmenu->addAction("降序");
    QAction *filterAction = cmenu->addAction("过滤");
    QAction *reshowAction = cmenu->addAction("重载");
    
    connect(ascendSortAction, SIGNAL(triggered(bool)), this, SLOT(sort_ascend()));
    connect(descendSortAction, SIGNAL(triggered(bool)), this, SLOT(sort_descend()));
    connect(filterAction, SIGNAL(triggered(bool)), this, SLOT(show_filter_dlg()));
    connect(reshowAction, SIGNAL(triggered(bool)), this, SLOT(reshow_data()));
show_contextmenu(const QPoint& pos)
{
    if(cmenu)
    {
        cmenu->exec(QCursor::pos());
    }
}


3)使用Qt::ActionsContextMenu。
把部件的所有action即QWidget::actions()作为context menu显示出来。
还是上面的例子,要在表格(QTableView类型)表头显示右键菜单:
        QAction *ascendSortAction = new QAction("升序", this);
        QAction *descendSortAction = new QAction("降序", this);
        QAction *filterAction = new QAction("过滤", this);
        QAction *unfilterAction = new QAction("取消过滤", this);
    
        connect(ascendSortAction, SIGNAL(triggered(bool)), this, SLOT(sort_ascend()));
        connect(descendSortAction, SIGNAL(triggered(bool)), this, SLOT(sort_descend()));
        connect(filterAction, SIGNAL(triggered(bool)), this, SLOT(filter_table()));
        connect(unfilterAction, SIGNAL(triggered(bool)), this, SLOT(unfilter_table()));
    
        datatable->horizontalHeader()->addAction(ascendSortAction);
        datatable->horizontalHeader()->addAction(descendSortAction);
        datatable->horizontalHeader()->addAction(filterAction);
        datatable->horizontalHeader()->addAction(unfilterAction);
         
        datatable->horizontalHeader()->setContextMenuPolicy(Qt::ActionsContextMenu);

另外两个就是不显示context menu了:
Qt::NoContextMenu
    the widget does not feature a context menu, context menu handling is deferred to the widget's parent.
    
Qt::PreventContextMenu
    the widget does not feature a context menu, and in contrast to NoContextMenu, the handling is not deferred to the widget's parent. This means that all right mouse button events are guaranteed to be delivered to the widget itself through mousePressEvent(), and mouseReleaseEvent().

补充:
    使用Qt::ActionsContextMenu比较简洁,但是如果需要根据当前菜单弹出的位置来定义不同菜单,或者像上个例子,在表格(QTableView类型)表头显示右键菜单时,我需要知道是哪一列表头被点击,从而在后来调用sort_ascend()排序函数时能够根据不同列进行不同排序策略,那么Qt::ActionsContextMenu就做不到了。
    这种需要捕捉弹出位置的情况只好用Qt::ActionsContextMenu了,customContextMenuRequested ( const QPoint & pos )信号返回点击位置pos(在表头视口坐标系中位置),然后表头即可调用logicalIndexAt(pos)函数得到被点击section对应的index即被点击部分的列号,然后存下来可供后面action激活的排序槽使用。
show_contextmenu(const QPoint& pos)
{
    //get related column of headerview
    contextmenu_column = datatable->horizontalHeader()->logicalIndexAt(pos);

    //show contextmenu
    if(cmenu)
    {
        cmenu->exec(QCursor::pos());
    }
}



4)二级菜单实例

准备工作一:定义和实现需要的action,可以用代码编写,也可以用creator进行制作。代码编写如下

头文件定义:

[cpp] view plaincopy
  1. QMenu              *popupMenu;                      /*popupMenu*/  //主菜单  
  2.     QMenu              *twoPictures;                    /*two pictures*/  // 二级菜单  
  3.     QMenu              *onePictures;                    /*one pictures*/ // 二级菜单  
  4.     QAction            *firstChannel;                   /*channel 1*/  
  5.     QAction            *secondChannel;                  /*channel 2*/  
  6.     QAction            *thirdChannel;                   /*channel 3*/  
  7.     QAction            *forthChannel;                   /*channel 4*/  
  8.     QAction            *frontSection;  
  9.     QAction            *backSection;  
  10.     QActionGroup       *channels;     //用来实现子菜单选项互斥  
  11.     QActionGroup       *sections;  

       cpp文件实现:

[cpp] view plaincopy
  1. void layout3::createActions(void)  
  2. {  
  3.     firstChannel = new QAction(tr("first channel"), this);  //创建新的菜单项  
  4.     firstChannel->setCheckable(true);                            //属性是可选的  
  5.     connect(firstChannel, SIGNAL(triggered()), this, SLOT(firstChannelSlot()));       //该菜单项的连接信号和槽  
  6.   
  7.     secondChannel = new QAction(tr("second channel"), this);  
  8.     secondChannel->setCheckable(true);  
  9.     connect(secondChannel, SIGNAL(triggered()), this, SLOT(secondChannelSlot()));  
  10.   
  11.     thirdChannel = new QAction(tr("third channel"), this);  
  12.     thirdChannel->setCheckable(true);  
  13.     connect(thirdChannel, SIGNAL(triggered()), this, SLOT(thirdChannelSlot()));  
  14.   
  15.     forthChannel = new QAction(tr("forth channel"), this);  
  16.     forthChannel->setCheckable(true);  
  17.     connect(forthChannel, SIGNAL(triggered()), this, SLOT(forthChannelSlot()));  
  18.   
  19.     frontSection = new QAction(tr("front section"), this);  
  20.     frontSection->setCheckable(true);  
  21.     connect(frontSection, SIGNAL(triggered()), this, SLOT(frontSectionSlot()));  
  22.   
  23.     backSection = new QAction(tr("back section"), this);  
  24.     backSection->setCheckable(true);  
  25.     connect(backSection, SIGNAL(triggered()), this, SLOT(backSectionSlot()));  
  26.   
  27.     channels = new QActionGroup(this);        //创建菜单项组,里面的菜单项为互斥  
  28.     channels->addAction(firstChannel);         //添加菜单项到组里  
  29.     channels->addAction(secondChannel);  
  30.     channels->addAction(thirdChannel);  
  31.     channels->addAction(forthChannel);  
  32.     firstChannel->setChecked(true);          //设置默认的菜单组的菜单项状态,firstChannel被选中  
  33.   
  34.     sections = new QActionGroup(this);   //同上  
  35.     sections->addAction(frontSection);  
  36.     sections->addAction(backSection);  
  37.     frontSection->setChecked(true);  
  38.   
  39. }  

      准备工作二:编写相应的action对应的槽函数

[cpp] view plaincopy
  1. /* 
  2.  * 槽函数准备为 
  3.  */  
  4. void layout3::firstChannelSlot(void)  
  5. {  
  6. }  
  7.   
  8. void layout3::secondChannelSlot(void)  
  9. {  
  10. }  
  11.   
  12. void layout3::thirdChannelSlot(void)  
  13. {  
  14. }  
  15.   
  16. void layout3::forthChannelSlot(void){  
  17. }  
  18.   
  19. void layout3::frontSectionSlot(void)  
  20. {}  
  21.   
  22. void layout3::backSectionSlot(void)  
  23. {}  
 最后进行菜单的编辑,重写void contextMenuEvent ( QContextMenuEvent *event);

[cpp] view plaincopy
  1. void layout3::contextMenuEvent(QContextMenuEvent* e)  
  2. {  
  3.   
  4.     popupMenu = new QMenu();  //创建主菜单  
  5.   
  6.     onePictures = popupMenu->addMenu("one pictures");   //在主菜单中创建子菜单one pictures  
  7.     onePictures->addAction(firstChannel);               //把action项放入子菜单中  
  8.     onePictures->addAction(secondChannel);  
  9.     onePictures->addAction(thirdChannel);  
  10.     onePictures->addAction(forthChannel);  
  11.   
  12.     popupMenu->addSeparator();  
  13.     popupMenu->addSeparator();  
  14.   
  15.     twoPictures = popupMenu->addMenu("two pictures");  //在主菜单中创建子菜单two pictures  
  16.     twoPictures->addAction(frontSection);  
  17.     twoPictures->addAction(backSection);  
  18.   
  19.     popupMenu->addSeparator();  
  20.     popupMenu->addSeparator();  
  21.   
  22.     popupMenu->addAction(ui->actionAbout);              //把action项放入主菜单中  
  23.     popupMenu->addSeparator();  
  24.     popupMenu->addSeparator();  
  25.     popupMenu->addAction(ui->actionBuild);  
  26.     popupMenu->addSeparator();  
  27.     popupMenu->addSeparator();  
  28.   
  29.     popupMenu->exec(e->globalPos());                    //选择菜单弹出的位置  
  30.     delete popupMenu;  
  31.     popupMenu = NULL;  
  32.   
  33. }  


结果如下:




QT 拖拽功能

QT拖拽功能简介

Drag和Drop是两个完全不同的动作。Qt中的控件可以作为拖动(drag)的地点,也可以作为松开(drop)的地点,或者同时作为拖动和松开的地点。
第一个例子用来说明一个Qt应用程序接受另一个程序触发的拖动事件。该Qt应用程序是一个QTextEdit为中央控件的主窗口。当用户从桌面或者一个文件浏览器中拖动一个文本文件到Qt程序时松开,程序把文件显示在QTextEdit控件中。
下面是主窗口的定义
class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    MainWindow();
protected:
    void dragEnterEvent(QDragEnterEvent *event);
    void dropEvent(QDropEvent *event);
private:
    bool readFile(const QString &fileName);
    QTextEdit *textEdit;
};
 
在MainWindow类中,重新实现了QWidget的函数dragEnterEvent()和dropEvent()。由于这个例子主要用来显示托拽,主窗口的很多其他功能都省略了。
 
MainWindow::MainWindow()
{
    textEdit = new QTextEdit;
    setCentralWidget(textEdit);
    textEdit->setAcceptDrops(false);
    setAcceptDrops(true);
    setWindowTitle(tr("Text Editor"));
}
 
在构造函数中,我们创建了一个QTextEdit控件,并设置为中央控件。缺省情况下,QTextEdit接受来自其他应用程序拖拽来的文本,把文件名显示出来。由于drop事件是由子控件向父控件传播的,通过禁止QTextEdit控件的drop事件,允许主窗口得到drop事件,我们就得到了MainWindow中的整个窗口的drop事件。
void MainWindow::dragEnterEvent(QDragEnterEvent *event)
{
    if (event->mimeData()->hasFormat("text/uri-list"))
        event->acceptProposedAction();
}
 
任何时候用户拖动一个对象到一个控件上,函数dragEnterEvent()都会被调用。如果在这个事件处理函数中调用函数acceptProposeAction(),说明我们允许用户把这个对象拖拽到这个控件上。默认情况,控件不接收drag事件。Qt会自动改变光标状态指示用户当前的控件是否是一个合法的drop地点。
在这里我们只允许用户drag一个文本文件,因此,我们检查这个这个drag的MIME类型。MIME类型text/uri-list用来保存URL的一个地址列表,可以是文件名,URL(HTTP或者FTP路径),也可以是其他的全局资源标识。标准的MIME类型由IANA(Internet Assigned Numbers Authority)定义,由一个类型名/子类型名组成。MIME类型用于在剪贴板和拖拽使用时区别不同的数据类型,MIME类型列表可以点击访问http://www.iana.org/assignments/media-types/得到
void MainWindow::dropEvent(QDropEvent *event)
{
    QList<QUrl> urls = event->mimeData()->urls();
    if (urls.isEmpty())
       return;
    QString fileName = urls.first().toLocalFile();
    if (fileName.isEmpty())
        return;
    if (readFile(fileName))
        setWindowTitle(tr("%1 - %2").arg(fileName)
                                    .arg(tr("Drag File")));
}
 
当用户将一个对象放在控件上drop时,函数dropEvent()就会调用。QMineData::urls()得到一个QUrls列表。通常用户一次只会拖动一个文件,但是拖动多个文件也是允许的。如果用户拖动了多个URLs,或者URL不是一个文件名,程序立即返回。
QWidget还提供了dragMoveEvent()和dragLeaveEvent(),但是对于大多数应用程序,这两个函数都不需要重写。
第二个例子来说明怎样进行drag,怎样接受drop。我们将会创建一个QListWidget子类,它可以接受drag和drop。并把它作为Project Choonser 程序的一个组件,如9.1所示:
Figure 9.1. The Project Chooser application
Project Chooser程序由两个名字列表控件组成。每一个列表控件表示一个项目。用户可以drag和drop列表中的名字,把一个名字从一个项目移到另一个项目中。
在列表控件的子类中实现了drag和drop部分的代码。下面是类的定义:
class ProjectListWidget : public QListWidget
{
    Q_OBJECT
public:
    ProjectListWidget(QWidget *parent = 0);
protected:
    void mousePressEvent(QMouseEvent *event);
    void mouseMoveEvent(QMouseEvent *event);
    void dragEnterEvent(QDragEnterEvent *event);
    void dragMoveEvent(QDragMoveEvent *event);
    void dropEvent(QDropEvent *event);
private:
    void startDrag();
    QPoint startPos;
};
该类重新实现了5个QWidget中声明的事件处理函数。 
ProjectListWidget::ProjectListWidget(QWidget *parent)
    : QListWidget(parent)
{
    setAcceptDrops(true);
}
在构造函数中,我们让列表控件允许接受drop。
 
void ProjectListWidget::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton)
        startPos = event->pos();
    QListWidget::mousePressEvent(event);
}
当用户点击了鼠标左键时,我们把鼠标位置保存在startPos变量中。然后调用基类QListWidget的mousePressEvent(),使QListWidget能处理鼠标点击事件,即列表控件的鼠标点击事件进入程序的消息循环。
 
void ProjectListWidget::mouseMoveEvent(QMouseEvent *event)
{
    if (event->buttons() & Qt::LeftButton) {
        int distance = (event->pos() - startPos).manhattanLength();
        if (distance >= QApplication::startDragDistance())
            startDrag();
    }
    QListWidget::mouseMoveEvent(event);
}
如果用户按住鼠标左键同时移动鼠标,把这个过程认为是一个drag。计算当前鼠标位置和鼠标第一次点击的位置之间的距离,如果这个距离大于QApplication认定的拖动的最小距离(通常为四个象素),调用私有函数startDrag()开始拖动。通过判断距离可以避免因为用户手抖动引起的误操作。
 
void ProjectListWidget::startDrag()
{
    QListWidgetItem *item = currentItem();
    if (item) {
        QMimeData *mimeData = new QMimeData;
        mimeData->setText(item->text());
        QDrag *drag = new QDrag(this);
        drag->setMimeData(mimeData);
        drag->setPixmap(QPixmap(":/images/person.png"));
        if (drag->start(Qt::MoveAction) == Qt::MoveAction)
            delete item;
    }
}
在startDrag()中,我们创建一个QDrag对象,this指针表示父类为当前的列表控件ProjectListWidget。QDrag对象保存了一个QMimeData对象中的数据。在这个例子中,我们只是使用QMimeData::setText()保存了一个text/plain 串。QMimeData提供了很多函数处理经常用到的拖动类型(如图像,URLs,颜色等等),对于用QByteArrays表示的任意MIME类型都可以处理。当drag发生时,函数QDrag::setPixmap()设置了跟随鼠标的图标。
调用QDrag::start()开始拖动,直到用户drop或者取消了拖动。函数的参数为多个“drag actions”的组合(Qt::CopyAction, Qt::MoveAction, Qt::LinkAction)。返回值为执行拖动的“drag action”,如果没有执行拖动的操作,则返回Qt::IgnoreAction。具体执行哪个action取决于源控件允许的操作,目标控件允许的操作和drop的同时是否有附加键按下。调用start()后,Qt拥有被拖动的对象,在不需要时将其删除。
void ProjectListWidget::dragEnterEvent(QDragEnterEvent *event)
{
    ProjectListWidget *source =
            qobject_cast<ProjectListWidget *>(event->source());
    if (source && source != this) {
        event->setDropAction(Qt::MoveAction);
        event->accept();
    }
}
ProjectListWidget不但可以产生drag,还可以接受来自程序中其他ProjectListWidget控件的drag。如果drag发生在同一个应用程序中,QDragEnterEvent::source()得到产生drag控件的指针。如果不是一个程序,则返回空指针。qobject_cast<T>()可以确保拖动来自与一个ProjectListWidget控件。如果一切正常,则调用accept()通知Qt接受这个action作为一个移动操作
 
void ProjectListWidget::dragMoveEvent(QDragMoveEvent *event)
{
    ProjectListWidget *source =
            qobject_cast<ProjectListWidget *>(event->source());
    if (source && source != this) {
        event->setDropAction(Qt::MoveAction);
        event->accept();
    }
}
函数dragMoveEvent()和dragEnterEvent()的代码是相同的。这有必要,因为需要覆盖QListWidget的(实际上是QAbstractItemView的)函数实现。
 
void ProjectListWidget::dropEvent(QDropEvent *event)
{
    ProjectListWidget *source =
            qobject_cast<ProjectListWidget *>(event->source());
    if (source && source != this) {
        addItem(event->mimeData()->text());
        event->setDropAction(Qt::MoveAction);
        event->accept();
    }
}
在dropEvent()中,调用QMimeData::text()得到拖动的文本,并用这个文本创建一个列表项目。我们还需要调用event->setDropAction(Qt::MoveAction),用参数Qt::MoveAction通知源控件可以删除原来拖动的项目。
在程序间需要转移数据时,拖拽是一个非常有用的机制。但是有时候不用拖拽机制也可以实现拖拽同样的操作。如果我们只是想在同一个程序同一个控件中移动数据,只需要重写mousePressEvent()和mouseReleaseEvent()就可以

GraphicView的拖拽功能加入

void QGraphicsScene::dragEnterEvent(QGraphicsSceneDragDropEvent *event)  {  qDebug("%s\n",__FUNCTION__); ;event->accept();}void QGraphicsScene::dragMoveEvent(QGraphicsSceneDragDropEvent *event)  {  qDebug("%s\n",__FUNCTION__); ;event->accept();  } void QGraphicsView::dropEvent(QDropEvent *event){qDebug("%s\n",__FUNCTION__); ;QList<QUrl> urls = event->mimeData()->urls();if (urls.isEmpty()){qDebug("It's empty \n");return;}QString fileName = urls.first().toLocalFile();qDebug("%s\n",fileName.toStdString().c_str());if (fileName.isEmpty())return;}


悬浮窗口,不规则窗口


主要思路:
1:将窗体设为Qt::FramelessWindowHint(去掉标题栏)。
2:用一幅有部分区域是透明的图片作为程序的界面,并将图片透明的地方设为穿透。

3:重载程序的鼠标事件。


运行时截图(浅绿色的是桌面背景)



源代码:


[cpp] view plaincopyprint?
  1. #include <QtGui>    
  2.   
  3. class IrregularWidget : public QWidget    
  4. {    
  5.     Q_OBJECT    
  6. public:    
  7.     IrregularWidget(QWidget *parent = 0);    
  8.   
  9. protected:    
  10.     void mousePressEvent(QMouseEvent *event);    
  11.     void mouseMoveEvent(QMouseEvent *event);    
  12.     void paintEvent(QPaintEvent *event);    
  13.     void enterEvent(QEvent *event);    
  14.     void leaveEvent(QEvent *event);    
  15.   
  16. private:    
  17.     QPoint m_CurrentPos;    
  18.     QPixmap m_Pixmap;    
  19. };    
  20.   
  21. IrregularWidget::IrregularWidget(QWidget *parent)    
  22. : QWidget(parent, Qt::FramelessWindowHint)    
  23. {    
  24.     setWindowTitle("Irregular widget");    
  25.     //加载一幅有部分区域是透明的图片作为程序的界面    
  26.     m_Pixmap.load("delete.png");    
  27.     resize( m_Pixmap.size() );    
  28.     //不规则窗口的关键,将图片透明的地方设为穿透    
  29.     setMask( m_Pixmap.mask() );    
  30. }    
  31.   
  32. void IrregularWidget::mousePressEvent(QMouseEvent *event)    
  33. {    
  34.     //按住左键可以托动窗口,按下右键关闭程序    
  35.     if(event->button() == Qt::LeftButton)    
  36.     {    
  37.         m_CurrentPos = event->globalPos() - frameGeometry().topLeft();    
  38.         event->accept();    
  39.     }    
  40.     else if(event->button() == Qt::RightButton)    
  41.         close();    
  42. }    
  43.   
  44. void IrregularWidget::mouseMoveEvent(QMouseEvent *event)    
  45. {    
  46.     if (event->buttons() && Qt::LeftButton)    
  47.     {    
  48.         move(event->globalPos() - m_CurrentPos);    
  49.         event->accept();    
  50.     }    
  51. }    
  52.   
  53. void IrregularWidget::paintEvent(QPaintEvent *event)    
  54. {    
  55.     QPainter painter(this);    
  56.     painter.drawPixmap(0, 0, m_Pixmap);    
  57. }    
  58.   
  59. void IrregularWidget::leaveEvent(QEvent *event)    
  60. {    
  61.     //鼠标离开窗口时是普通的指针    
  62.     setCursor(Qt::ArrowCursor);    
  63. }    
  64.   
  65. void IrregularWidget::enterEvent(QEvent *event)    
  66. {    
  67.     //鼠标留在窗口上时是一个手指    
  68.     setCursor(Qt::PointingHandCursor);    
  69. }    
  70.   
  71. #include "main.moc"    
  72.   
  73. int main(int argc, char *argv[])    
  74. {    
  75.     QApplication app(argc, argv);    
  76.     IrregularWidget *widget = new IrregularWidget;    
  77.     widget->show();    
  78.     return app.exec();    
  79. }    

Qt 自定义 标题栏


int main(int argc, char **argv){InitSys();QApplication app(argc, argv);QFile qss("skin.qss");qss.open(QFile::ReadOnly);qApp->setStyleSheet(qss.readAll());qss.close();Frame box;QVBoxLayout *l = new QVBoxLayout(box.contentWidget());l->setMargin(0);CenDVC *w= new CenDVC(box.contentWidget());l->addWidget((QWidget*)w);box.resize(1280,720);box.move ((QApplication::desktop()->width() - box.width())/2,(QApplication::desktop()->height() - box.height())/2);box.show();return app.exec();    }





#ifndef CEN_EXTERN_H_#define CEN_EXTERN_H_#include <cendvc.h>class TitleBar : public QWidget{Q_OBJECTpublic:TitleBar(QWidget *parent){// Don't let this widget inherit the parent's backround colorsetAutoFillBackground(true);// Use a brush with a Highlight color role to render the backgroundsetBackgroundRole(QPalette::Highlight);logobutton = new QToolButton(this);minimize = new QToolButton(this);maximize = new QToolButton(this);close= new QToolButton(this);// Use the style to set the button pixmapsQPixmap pix = style()->standardPixmap(QStyle::SP_TitleBarCloseButton);close->setIcon(pix);maxPix = style()->standardPixmap(QStyle::SP_TitleBarMaxButton);maximize->setIcon(maxPix);pix = style()->standardPixmap(QStyle::SP_TitleBarMinButton);minimize->setIcon(pix);restorePix = style()->standardPixmap(QStyle::SP_TitleBarNormalButton);minimize->setMinimumHeight(20);close->setMinimumHeight(20);maximize->setMinimumHeight(20);QLabel *label = new QLabel(this);label->setText(QString::fromUtf8("置辰海信流媒体客户端.2014 V1.0.14"));parent->setWindowTitle(QString::fromUtf8("置辰海信流媒体客户端.2014 V1.0.14"));logobutton->setIcon(QIcon("logo.ico"));QHBoxLayout *hbox = new QHBoxLayout(this);hbox->addWidget(logobutton) ;hbox->addWidget(label);hbox->addWidget(minimize);hbox->addWidget(maximize);hbox->addWidget(close);hbox->insertStretch(2, 500);hbox->setSpacing(0);setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);maxNormal = false;connect(close, SIGNAL( clicked() ), parent, SLOT(close() ) );connect(minimize, SIGNAL( clicked() ), this, SLOT(showSmall() ) );connect(maximize, SIGNAL( clicked() ), this, SLOT(showMaxRestore() ) );}public slots:void showSmall(){parentWidget()->showMinimized();}void showMaxRestore(){if (maxNormal) {parentWidget()->showNormal();maxNormal = !maxNormal;maximize->setIcon(maxPix);} else {parentWidget()->showMaximized();maxNormal = !maxNormal;maximize->setIcon(restorePix);}}protected:void mousePressEvent(QMouseEvent *me){startPos = me->globalPos();clickPos = mapToParent(me->pos());}void mouseMoveEvent(QMouseEvent *me){if (maxNormal)return;parentWidget()->move(me->globalPos() - clickPos);}private:QToolButton *logobutton ;QToolButton *minimize;QToolButton *maximize;QToolButton *close;QPixmap restorePix, maxPix;bool maxNormal;QPoint startPos;QPoint clickPos;};class Frame : public QFrame{public:Frame(){m_mouse_down = false;setFrameShape(Panel);// Make this a borderless window which can't// be resized or moved via the window systemsetWindowFlags(Qt::FramelessWindowHint);setMouseTracking(true);m_titleBar = new TitleBar(this);m_content = new QWidget(this);QVBoxLayout *vbox = new QVBoxLayout(this);vbox->addWidget(m_titleBar);vbox->setMargin(0);vbox->setSpacing(0);QVBoxLayout *layout = new QVBoxLayout(this);layout->addWidget(m_content);layout->setMargin(5);layout->setSpacing(0);vbox->addLayout(layout);}// Allows you to access the content area of the frame// where widgets and layouts can be addedQWidget *contentWidget() const { return m_content; }TitleBar *titleBar() const { return m_titleBar; }void mousePressEvent(QMouseEvent *e){m_old_pos = e->pos();m_mouse_down = e->button() == Qt::LeftButton;}void mouseMoveEvent(QMouseEvent *e){int x = e->x();int y = e->y();printf("mouseMoving  1 \n");if (m_mouse_down) {int dx = x - m_old_pos.x();int dy = y - m_old_pos.y();QRect g = geometry();if (left)g.setLeft(g.left() + dx);if (right)g.setRight(g.right() + dx);if (bottom)g.setBottom(g.bottom() + dy);setGeometry(g);m_old_pos = QPoint(!left ? e->x() : m_old_pos.x(), e->y());} else {QRect r = rect();left = qAbs(x - r.left()) <= 3;right = qAbs(x - r.right()) <= 3;bottom = qAbs(y - r.bottom()) <= 3;bool hor = left | right;if (hor && bottom) {if (left)setCursor(Qt::SizeBDiagCursor);elsesetCursor(Qt::SizeFDiagCursor);} else if (hor) {setCursor(Qt::SizeHorCursor);} else if (bottom) {setCursor(Qt::SizeVerCursor);} else {setCursor(Qt::ArrowCursor);}}}void mouseReleaseEvent(QMouseEvent *e){m_mouse_down = false;}private:TitleBar *m_titleBar;QWidget *m_content;QPoint m_old_pos;bool m_mouse_down;bool left, right, bottom;};#endif /* CEN_EXTERN_H_ */















0 0
原创粉丝点击