Qt浅谈之四十七下拉列表菜单

一、简介

      在QGraphicsItem下使用QListWidget实现下拉列表的功能,并显示所有的选项,便于浏览和查询数据。

二、详解

1、部分代码

(1)clusterlistwidget.h

#ifndef CLUSTERLISTWIDGET_H
#define CLUSTERLISTWIDGET_H
#include <QWidget>
#include <QtGui>
#include "custombtn.h"
#include "pagenumbercontrol.h"
class SearchLineEdit;
enum TYPE{cluster=0,host,vm};
class ClusterListWidget : public QWidget
{
    Q_OBJECT
public:
    explicit ClusterListWidget(TYPE type = cluster,QWidget *parent = 0);

    void setListWidget();
    void setTitle(QString title);

    void listInit();
signals:

public slots:
    void textChange(QString text);
    void pageChange(int currentnumber);
    void editClicked();
    void btnClicked();
    void itemEnteredSlot(QListWidgetItem * i);
    void itemClickedSlot(QListWidgetItem * i);

    void rowChanged(int row);
protected:
    //bool eventFilter(QObject * obj, QEvent *e);
    void paintEvent(QPaintEvent *e);
    void showEvent(QShowEvent *e);
    void keyPressEvent(QKeyEvent *e);
private:
    void setImgs(const QString &normal,const QString &abnormal,const QString &error);
    void setVmImgs(const QString &linux_normal,const QString &linux_abnormal,const QString &linux_error,const QString &linux_off,
                   const QString &windows_normal,const QString &windows_abnormal,const QString &windows_error,const QString &windows_off);
private:
    //QString _icon;
    QPixmap backGroundPix;
    QStringList NameList;
    QStringList _searchList;
    QStringList _list;
    QLabel *lb1;
    QLabel *lb2;
    PageNumberControl *_page;

    int _maxNum;
    int _currentNum;
    int _searchNUm;
    SearchLineEdit *_searchLineEdit;
    QListWidget * _cluster;
    QPushButton *_btn;
    int _n;//记录键盘 上下见

    int _x;
    int _y;
    QPixmap _enterPixmap;
    bool _enter;

    QString _title;
    QString _normal;
    QString _abnormal;
    QString __error;

    TYPE _type;

    QString _linux_normal;
    QString _linux_abnormal;
    QString _linux_error;
    QString _linux_off;
    QString _windows_normal;
    QString _windows_abnormal;
    QString _windows_error;
    QString _windows_off;
};
class SearchLineEdit : public QLineEdit
{
    Q_OBJECT
 public:
    explicit SearchLineEdit(QWidget *parent = 0);
 signals:
    void pressed();
 protected:
    void focusInEvent(QFocusEvent *e);
    void focusOutEvent(QFocusEvent *e);
 private:
};
#endif // CLUSTERLISTWIDGET_H
(2)clusterlistwidget.cpp
#include "clusterlistwidget.h"

ClusterListWidget::ClusterListWidget(TYPE type,QWidget *parent) :
    QWidget(parent,Qt::FramelessWindowHint)
  ,_maxNum(0)
  ,_searchNUm(0)
  ,_n(-1)
  ,_x(0)
  ,_y(0)
  ,_enter(false)
{
    NameList<<"a"<<"b"<<"c"<<"d"<<"e"<<"a"<<"b"<<"c"<<"d"<<"e"
             <<"a"<<"b"<<"c"<<"d"<<"e"<<"a"<<"b"<<"c"<<"d"<<"e"
               <<"a"<<"b"<<"c"<<"d"<<"e"<<"a"<<"b"<<"c"<<"d"<<"e"
                 <<"a"<<"b"<<"c"<<"d"<<"e"<<"a"<<"b"<<"c"<<"d"<<"e"<<"hjhjha";
    backGroundPix = QPixmap(":/images/handleMenu_bg.png");
    resize(backGroundPix.width(),  backGroundPix.height());
    qDebug()<<backGroundPix.width()<<backGroundPix.height();
    QPalette pal = palette();
    pal.setColor(QPalette::Background, QColor(0xFF,0xFF,0xFF,0x00));
    setPalette(pal);
    _list= NameList;
    _type = type;
    lb1 = new QLabel(this);
    lb1->setPixmap(QPixmap(":/images/handleMenu_allClusters.png"));
    lb1->move(10,12);

    lb2 = new QLabel(this);
    lb2->move(33,12);
    lb2->setStyleSheet("color:#b4e5fd");

    _page = new PageNumberControl(this);
    _page->setCluster(true);
    _maxNum = (_list.count() - 1) / 16 +1;
    _currentNum = 1;
    _page->setTotalPage(_maxNum);
    _page->move(145,12);

    _searchLineEdit = new SearchLineEdit(this);
//    _searchLineEdit->setImgs(":/images/handleMenu_searchInput.png",":/images/handleMenu_searchInput_click.png",
//                             ":/images/handleMenu_searchInput.png",":/images/handleMenu_searchInput.png");
    _searchLineEdit->setStyleSheet("background-image:url(:/images/handleMenu_searchInput.png);border:1px solid #536874;");
    _searchLineEdit->move(8,38);
    _searchLineEdit->resize(168,23);
    _searchLineEdit->installEventFilter(this);
    //_searchLineEdit->setFocusPolicy(Qt::NoFocus);
     _btn = new QPushButton(this);
     _btn->resize(14,14);
     _btn->move(155,41);
     _btn->setStyleSheet("QPushButton{background-color:transparent;border:0px;}");
     _btn->setFocusPolicy(Qt::NoFocus);
     _btn->setVisible(false);

     connect(_btn,SIGNAL(clicked()),this,SLOT(btnClicked()));
     _cluster = new QListWidget(this);
    _cluster->show();
    setListWidget();
    _cluster->setMouseTracking(true);
    _cluster->setFocusPolicy(Qt::NoFocus);
    //_cluster->installEventFilter(this);
    connect(_searchLineEdit,SIGNAL(textChanged(QString)),this,SLOT(textChange(QString)));
    connect(_page,SIGNAL(currentPageChanged(int)),this,SLOT(pageChange(int)));
    connect(_searchLineEdit,SIGNAL(pressed()),this,SLOT(editClicked()));
    connect(_cluster,SIGNAL(itemEntered(QListWidgetItem*)),this,SLOT(itemEnteredSlot(QListWidgetItem*)));
    connect(_cluster,SIGNAL(itemClicked(QListWidgetItem*)),this,SLOT(itemClickedSlot(QListWidgetItem*)));
    connect(_cluster,SIGNAL(currentRowChanged(int)),this,SLOT(rowChanged(int)));
    //this->setFocus();
    //this->installEventFilter(this);
}

void ClusterListWidget::setListWidget()
{
    _cluster->setStyleSheet("QListWidget{background-color:transparent;color:#19649F;border:0px solid gray;}"
                                          "QListWidget::item{background-color:transparent;border:0px solid gray;padding-left:28px;color:#b4e5fd}"
                                          //"QListWidget::item:!selected{border:0px solid gray;padding-left:28px;color:#b4e5fd}"
                                          //"QListWidget::item:selected:active{background-image:url(:/images/handleMenu_lixt_bg_selected.png);color:#b4e5fd;border-width:0;}"
                                          "QListWidget::item:selected{background-image:url(:/images/handleMenu_lixt_bg_selected.png);}"
                                          );
    _cluster->move(0,62);
    _cluster->resize(183,540);
    _cluster->clear();

    pageChange(1);

}

void ClusterListWidget::setTitle(QString title)
{
    lb2->setText(title);
}

void ClusterListWidget::setImgs(const QString &normal, const QString &abnormal, const QString &error)
{
    _normal = normal;
    _abnormal = abnormal;
    __error = error;
}

void ClusterListWidget::setVmImgs(const QString &linux_normal,
                                  const QString &linux_abnormal,
                                  const QString &linux_error,
                                  const QString &linux_off,
                                  const QString &windows_normal,
                                  const QString &windows_abnormal,
                                  const QString &windows_error,
                                  const QString &windows_off)
{
    _linux_normal = linux_normal;
    _linux_abnormal = linux_abnormal;
    _linux_error = linux_error;
    _linux_off = linux_off;
    _windows_normal = windows_normal;
    _windows_abnormal = windows_abnormal;
    _windows_error = windows_error;
    _windows_off = windows_off;
}


void ClusterListWidget::editClicked()
{
    _searchLineEdit->setStyleSheet("background-image:url(:/images/handleMenu_searchInput_click.png);border:1px solid #536874;");
    _searchLineEdit->update();
    _btn->setVisible(true);
}

void ClusterListWidget::btnClicked()
{
    _searchLineEdit->clear();
    _searchLineEdit->setStyleSheet("background-image:url(:/images/handleMenu_searchInput.png);border:1px solid #536874;");
    this->setFocus();
}

void ClusterListWidget::itemEnteredSlot(QListWidgetItem *i)
{
    _n = _cluster->row(i);
    if(_n == _cluster->currentRow())
    {
        _enter = false;
    }else{
    _enter = true;}
    _x = 0;
    _y = _cluster->row(i)*33 +62;
    _enterPixmap = QPixmap(":/images/handleMenu_lixt_bg_hover.png");

    _cluster->update();
}

void ClusterListWidget::itemClickedSlot(QListWidgetItem *i)
{
    int row =_cluster->row(i);
    qDebug()<< (_currentNum -1)*16 + row;
    _enter = false;//选中跟悬停  只显示选中背景图片
    _cluster->update();

}

void ClusterListWidget::rowChanged(int row)
{

    //qDebug()<< (_currentNum -1)*16 + row;
    _enter = false;//选中跟悬停  只显示选中背景图片
    _cluster->update();
    _n = row;
}

//bool ClusterListWidget::eventFilter(QObject *obj, QEvent *e)
//{
//    if(obj == _cluster){
//        if(e->type() == QEvent::Leave)
//        {
//            _enter = false;
//            _cluster->update();
//            _n = _cluster->currentRow();
//            return true;
//        }
//    }
//   return false;
//    QWidget::eventFilter(obj,e);
//}

void ClusterListWidget::textChange(QString text)
{
    _cluster->clear();
    _list.clear();
    _searchList.clear();
    for(int i = 0;i < NameList.count();i++){
        if(NameList.at(i).contains(text))
        {
            _searchList.append(NameList.at(i));
        }
    }
    _list = _searchList;
    _maxNum = (_list.count() - 1) / 16 +1;
    _currentNum = 1;
    _page->setTotalPage(_maxNum);
    pageChange(1);
    _cluster->update();

}

void ClusterListWidget::pageChange(int currentnumber)
{

    _currentNum = currentnumber;
    _cluster->clear();

    switch (_type) {
    case 0:
        setTitle(tr("all cluster"));
        setImgs(":/images/handleMenu_clusters.png",
                ":/images/handleMenu_clusters_abnormal.png",":/images/handleMenu_clusters_error.png");
        if(_currentNum != _maxNum)
        {
            for(int i= (_currentNum -1) * 16;i <(_currentNum) * 16 ;i++ )
            {
                QListWidgetItem *item = new QListWidgetItem;
                item->setSizeHint(QSize(183,33));
                item->setText(" "+_list.at(i));
                item->setIcon(QIcon(_normal));
                _cluster->addItem(item);
            }
        }else{
            for(int i = (_currentNum -1) * 16;i < _list.count();i++)
            {
                QListWidgetItem *item = new QListWidgetItem;
                 item->setSizeHint(QSize(183,33));
                item->setText(" "+_list.at(i));
                item->setIcon(QIcon(__error));
                _cluster->addItem(item);
            }
        }
        break;
    case 1:

        setImgs(":/images/handleMenu_host.png",
                ":/images/handleMenu_host_abnormal.png",":/images/handleMenu_host_error.png");
        if(_currentNum != _maxNum)
        {
            for(int i= (_currentNum -1) * 16;i <(_currentNum) * 16 ;i++ )
            {
                QListWidgetItem *item = new QListWidgetItem;
                item->setSizeHint(QSize(183,33));
                item->setText(" "+_list.at(i));
                item->setIcon(QIcon(_abnormal));
                _cluster->addItem(item);
            }
        }else{
            for(int i = (_currentNum -1) * 16;i < _list.count();i++)
            {
                QListWidgetItem *item = new QListWidgetItem;
                 item->setSizeHint(QSize(183,33));
                item->setText(" "+_list.at(i));
                item->setIcon(QIcon(__error));
                _cluster->addItem(item);
            }
        }
        break;
    case 2:
        setVmImgs(":/images/handleMenu_vm.png",":/images/handleMenu_vm_linux_abnormal.png",":/images/handleMenu_vm_linux_error.png",
                  ":/images/handleMenu_vm_linux_shutdown.png",":/images/handleMenu_vm_windows.png",":/images/handleMenu_vm_windows_abnormal.png",
                  ":/images/handleMenu_vm_windows_error.png",":/images/handleMenu_vm_windows_shutdown.png");
        if(_currentNum != _maxNum)
        {
            for(int i= (_currentNum -1) * 16;i <(_currentNum) * 16 ;i++ )
            {
                QListWidgetItem *item = new QListWidgetItem;
                item->setSizeHint(QSize(183,33));
                item->setText(" "+_list.at(i));
                item->setIcon(QIcon(_linux_abnormal));
                _cluster->addItem(item);
            }
        }else{
            for(int i = (_currentNum -1) * 16;i < _list.count();i++)
            {
                QListWidgetItem *item = new QListWidgetItem;
                 item->setSizeHint(QSize(183,33));
                item->setText(" "+_list.at(i));
                item->setIcon(QIcon(_windows_error));
                _cluster->addItem(item);
            }
        }
        break;
    default:
        break;
    }

    _cluster->setCurrentRow(0);
}

void ClusterListWidget::paintEvent(QPaintEvent *e)
{
    QPainter painter(this);
    painter.drawPixmap(0, 0, backGroundPix.width(), backGroundPix.height(), backGroundPix);
    if(_enter)
    {
        painter.drawPixmap(_x,_y,183,33,_enterPixmap);
    }
    //painter.setPen(QColor("#b4e5fd"));
}

void ClusterListWidget::showEvent(QShowEvent *e)
{
    setListWidget();
}

void ClusterListWidget::keyPressEvent(QKeyEvent *e)
{
    qDebug()<<"aaaaaaaaaaaaaaaaaaaaaa"<<_n;
    //n = _cluster->currentRow();
    if(e->key() == Qt::Key_Up)
    {
        if(_n > 0)
        {
            _n -= 1;
        }
        itemEnteredSlot(_cluster->item(_n));
        //_cluster->setCurrentRow(n);
        return;
    }
    if(e->key() == Qt::Key_Down)
    {
        if( _n < _cluster->count() -1){
            _n += 1;
        itemEnteredSlot(_cluster->item(_n));
        }
        //_cluster->setCurrentRow(n);
        return;
    }
    if(e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return)
    {
        qDebug()<<"777777777777777";
        _cluster->setCurrentRow(_n);
        return;
    }
    QWidget::keyPressEvent(e);
}
SearchLineEdit::SearchLineEdit(QWidget *parent)
   :QLineEdit(parent)
{

}

void SearchLineEdit::focusInEvent(QFocusEvent *e)
{
    emit pressed();

    QLineEdit::focusInEvent(e);

}

void SearchLineEdit::focusOutEvent(QFocusEvent *e)
{
    QLineEdit::focusInEvent(e);
}
(3)clusterlistitem.h
#ifndef CLUSTERLISTITEM_H
#define CLUSTERLISTITEM_H

#include <QGraphicsItem>
#include "graphicsitembutton.h"
#include "clusterlistwidget.h"
#include <QPalette>
#include <QtGui>
class clusterListItem : public QObject, public QGraphicsItem
{
    Q_OBJECT
public:
    explicit clusterListItem(QGraphicsItem *parent = 0);
    QRectF boundingRect() const;
signals:

protected:
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);

    bool eventFilter(QObject *obj, QEvent *event);

private slots:
    void slotBtnClicked();

private:
    int _width;
    int _height;
    GraphicsItemButton * _listBtn;
    ClusterListWidget * _clusterWidget;
    QGraphicsProxyWidget *_proxy;
    bool _show;
    bool _focus;
};

#endif // CLUSTERLISTITEM_H
(4) clusterlistitem.cpp
#include "clusterlistitem.h"

clusterListItem::clusterListItem(QGraphicsItem *parent) :
    QGraphicsItem(parent)
  ,_show(false)
{
    setFiltersChildEvents(true);
    //setAcceptedMouseButtons(Qt::LeftButton);
    //setAcceptHoverEvents(true);
    _width = 22;
    _height =21;
    _listBtn = new GraphicsItemButton(":/images/handleMenu_icon.png",
                                      ":/images/handleMenu_icon_hover.png",
                                      ":/images/handleMenu_icon_hover.png",
                                      "",
                                       GraphicsItemButton::normal,this);

    _listBtn->setSize(22,21);
    _listBtn->setPos(0,0);
    _listBtn->installEventFilter(this);
    _clusterWidget = new ClusterListWidget(cluster);
    _proxy = new QGraphicsProxyWidget(this);
    _proxy->setWidget(_clusterWidget);
    _proxy->setPos(0,21);
    _proxy->setVisible(_show);
    _clusterWidget->installEventFilter(this);
    //this->installEventFilter(this);
    connect(_listBtn,SIGNAL(clicked()),this,SLOT(slotBtnClicked()));
}

QRectF clusterListItem::boundingRect() const
{
    return QRectF(0, 0, _width, _height);
}

void clusterListItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
      //painter->fillRect(QRectF(0, 0, _width, _height), QColor("#FF0000"));
}

bool clusterListItem::eventFilter(QObject *obj, QEvent *event)
{
    if (event->type() == QEvent::FocusIn) {
        qDebug() << "QEvent::FocusIn---" << obj;
    }
    if (event->type() == QEvent::FocusOut) {
        qDebug() << "QEvent::FocusOut---" << obj;
    }
    if (event->type() == QEvent::MouseButtonPress) {
        qDebug() << obj;
        if (obj == _clusterWidget) {
            return true;
        }
        else {
            if (_show == true) {
                _listBtn->setCurrent(false);
                _show = false;
                //_clusterWidget->hide();
                QPropertyAnimation *animation = new QPropertyAnimation(_clusterWidget, "geometry");
                animation->setDuration(300);
                animation->setStartValue(QRect(0,21,183,602));
                animation->setEndValue(QRect(0,21,183,0));
                animation->start();
            }
        }
    }
     return QObject::eventFilter(obj, event);
}

void clusterListItem::slotBtnClicked()
{
    this->setFocus();
    _listBtn->setCurrent(true);
    if(!_show){
        //_proxy->setVisible(!_show);
        _proxy->show();
        QPropertyAnimation *animation = new QPropertyAnimation(_clusterWidget, "geometry");
        animation->setDuration(300);
        animation->setStartValue(QRect(0,21,183,0));
        animation->setEndValue(QRect(0,21,183,602));
        animation->start();
        _show = true;
    }
    else{

        QPropertyAnimation *animation = new QPropertyAnimation(_clusterWidget, "geometry");
        animation->setDuration(300);
        animation->setStartValue(QRect(0,21,183,602));
        animation->setEndValue(QRect(0,21,183,0));
        animation->start();
        _show = false;
    }
}
(5)main.cpp
#include "clusterlistwidget.h"
#include <QApplication>
#include <QTextCodec>
#include <QtGui>
#include "clusterlistitem.h"
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QTextCodec::setCodecForTr(QTextCodec::codecForLocale());

    QGraphicsView view;
    //view.resize(300,800);

    QGraphicsScene scene;

    scene.setSceneRect(-100, -300, 200, 600);
    view.setScene(&scene);
    view.setSceneRect(0, 0, 200, 600);
    //view.setCacheMode(QGraphicsView::CacheBackground);
    //view.setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate);
    clusterListItem *item = new clusterListItem;
    scene.addItem(item);
    item->setPos(0, 0);
    view.resize(314, 814);
    view.show();
    view.installEventFilter(item);
    return a.exec();
}

三、总结

(1)可以在eventFilter的QEvent::FocusIn和QEvent::FocusOut增加当鼠标移出菜单后自动回收的功能。其他的功能还需进一步完善。
(2)若有问题或建议,请留言,在此感谢!

你可能感兴趣的:(linux,qt)