程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> QGraphicsWidget自定義控件實現button

QGraphicsWidget自定義控件實現button

編輯:關於C語言

實現button和實現label功能相似,只是button有三種狀態,normal,hover,pressed,只要對這三種狀態進行不同的實現就可以了。


這裡還設計了三種不同的button,可以只顯示圖標,只顯示文字,同時顯示文字和圖標


int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QGraphicsScene *scene = new QGraphicsScene;
    QGraphicsView *view = new QGraphicsView(scene);
    scene->setSceneRect(0, 0, 300, 300);
                                                                                                                                                                                                  
    QPixmap normalPixmap("images/button_normal.png");
    QPixmap hoverPixmap("images/button_hover.png");
    QPixmap pressedPixmap("images/button_pressdown.png");
    ShowButton *showbutton1 = new ShowButton(normalPixmap, hoverPixmap, pressedPixmap);
        ......
}

   這裡同樣是基於QGraphicsWidget的,所以要先創建場景scene,然後要讀取三張不同的圖片作為三種不同狀態時候button的背景圖。


       這裡的ShowButton就是我們要實現的控件,下面給出控件的頭文件

showbutton.h

#ifndef SHOWBUTTON_H
#define SHOWBUTTON_H
#include <QGraphicsWidget>
class QGraphicsSceneMouseEvent;
class QGraphicsSceneHoverEvent;
class ShowButton: public QGraphicsWidget
{
    Q_OBJECT
public:
    enum State { NormalState, HoverState, PressedState };
    enum Style { TextOnly, IconOnly, TextBesidesIcon, TextUnderIcon};
public:
    ShowButton(const QPixmap &, const QPixmap &, const QPixmap &);
    void setText(const QString &, const QFont &, const QColor &);
    void setIcon(const QPixmap& icon);
    void setStyle(Style style);
    QString getText();
signals:
    void clicked();
protected:
    void mousePressEvent(QGraphicsSceneMouseEvent *e);
    void mouseReleaseEvent(QGraphicsSceneMouseEvent *e);
    void hoverEnterEvent(QGraphicsSceneHoverEvent *e);
    void hoverLeaveEvent(QGraphicsSceneHoverEvent *);
protected:
    virtual QRectF boundingRect();
    virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
private:
    void setPixmap(State state);
private:
    int m_cnt;
    bool m_isPressed;
    bool m_iconOn;
    bool m_textOn;
    QPixmap m_pixmap;
    QPixmap m_normalPixmap;
    QPixmap m_hoverPixmap;
    QPixmap m_pressedPixmap;
    QPixmap m_icon;
    QString m_text;
    QSize m_size;
    QFont m_font;
    QColor m_color;
    Style m_style;
                                                                                                                                                       
};
#endif // SHOWBUTTON_H

這裡之所以把setPixmap(State state)作為私有的是因為這個函數並不對外提供接口,只是內部進行button背景圖片設置的時候會用到。


有關函數的具體實現如下,

showbutton.cpp

#include <QPainter>
#include <QGraphicsSceneMouseEvent>
#include <QGraphicsSceneHoverEvent>
#include "showbutton.h"
#include "clickhandler.h"
ShowButton::ShowButton(const QPixmap &normalPixmap, const QPixmap &hoverPixmap, const QPixmap &pressedPixmap)
: m_isPressed(false), m_iconOn(false), m_textOn(false)
{
    m_cnt = 0;
    m_text = "";
    m_icon = NULL;
    m_pixmap = normalPixmap;
    m_normalPixmap = normalPixmap;
    m_hoverPixmap = hoverPixmap;
    m_pressedPixmap = pressedPixmap;
    setAcceptHoverEvents(true);
}
void ShowButton::setStyle( Style style )
{
    if ( style == m_style)
    {
        return;
    }
    m_style = style;
    if (IconOnly == style)
    {
        m_iconOn = true;
        m_textOn = false;
    }
    else if (TextOnly == style)
    {
        m_iconOn = false;
        m_textOn = true;
    }
    else
    {
        m_iconOn = true;
        m_textOn = true;
    }
}
void ShowButton::setText(const QString &string, const QFont &font, const QColor &color)
{
    m_text = string;
    m_textOn = true;
    m_font = font;
    m_color = color;
}
void ShowButton::setIcon( const QPixmap &icon )
{
    m_icon = icon;
    m_iconOn = true;
}
void ShowButton::paint( QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    Q_UNUSED(option);
    Q_UNUSED(widget);
    const QRect &rect = boundingRect().toRect();
    setPreferredSize(rect.width(), rect.height());
    //畫button的背景
    painter->drawPixmap(rect, m_pixmap);
    if (m_iconOn && !m_icon.isNull())
    {
        QRect iconRect(0, 0, m_icon.size().width(), m_icon.size().height());
        painter->drawPixmap(iconRect, m_icon);
    }
    else if (m_textOn && !m_text.isEmpty())
    {
        QFontMetrics metrics(m_font);
        qreal width = metrics.width(m_text);
        qreal height = metrics.height();  
        QRect textRect(0, 0, width, height);
        painter->drawText(textRect, Qt::AlignCenter, m_text);
    }
    //圖標和文本都有
    if (m_textOn && m_iconOn && !m_icon.isNull() && !m_text.isEmpty())
    {
        //文字在圖標旁邊
        if(TextBesidesIcon == m_style)
        {
            QRect mixRect(0, 0, m_icon.size().width(), rect.height());
            painter->drawPixmap(mixRect, m_icon);
            QRect textRect(m_icon.size().width(), 0, rect.width() - m_icon.size().width(), rect.height());
            painter->drawText(textRect, Qt::AlignCenter, m_text);
        }
        //文字在圖標下面
        if (TextUnderIcon == m_style)
        {
            QRect mixRect(0, 0, rect.width(), m_icon.size().height());
            painter->drawPixmap(mixRect, m_icon);
            QRect textRect(0, m_icon.size().height(), rect.width(), rect.height() - m_icon.size().height());
            painter->drawText(textRect, Qt::AlignCenter, m_text);
        }
    }
}
QRectF ShowButton::boundingRect()
{
    m_size = m_pixmap.size();
    qreal widthText;
    qreal heightText;
    QSize iconSize;
    qreal totalWidth;
    qreal totalHeight;
    //獲取文本信息的寬高
    if (m_textOn)
    {
        QFontMetrics metrics(m_font);
        widthText = metrics.width(m_text);
        heightText = metrics.height();
        //return QRectF(0, 0, widthText, heightText);
    }
    //獲取圖標的寬高
    if (m_iconOn)
    {
        iconSize = m_icon.size();
    }
    if (2 == m_style)
    {
        totalWidth = widthText + iconSize.width();
        totalHeight = heightText > iconSize.height() ? heightText : iconSize.height();
    }
    else if (3 == m_style)
    {
        totalWidth = widthText > iconSize.width() ? widthText : iconSize.width();
        totalHeight = heightText + iconSize.height();
    }
    else
    {
        totalWidth = widthText + iconSize.width();
        totalHeight = heightText + iconSize.height();
    }
    return QRectF(0, 0, totalWidth, totalHeight);
}
void ShowButton::setPixmap( State state)
{
    switch (state)
    {
    case NormalState: m_pixmap = m_normalPixmap;
        break;
    case HoverState: m_pixmap = m_hoverPixmap;
        break;
    case PressedState:  m_pixmap = m_pressedPixmap;
        break;
    }
}
void ShowButton::mousePressEvent( QGraphicsSceneMouseEvent *e )
{
    if (e->button() == Qt::LeftButton)
    {
        m_isPressed = true;
        setPixmap(PressedState);
        update();
    }
                                                                                                                                 
}
void ShowButton::mouseReleaseEvent( QGraphicsSceneMouseEvent *e )
{
    if (e->button() == Qt::LeftButton)
    {
        if (m_isPressed)
            {
                m_cnt++;
                m_isPressed = false;
                setPixmap(NormalState);
                update();
                emit clicked();
            }
    }
                                                                                                                                     
}
void ShowButton::hoverEnterEvent( QGraphicsSceneHoverEvent * )
{
    if (!m_isPressed)
    {
        setPixmap(HoverState);
        update();
    }
                                                                                                                                 
}
void ShowButton::hoverLeaveEvent(QGraphicsSceneHoverEvent *)
{
    if (!m_isPressed)
    {
        setPixmap(NormalState);
        update();
    }
                                                                                                                                 
}
QString ShowButton::getText()
{
    return m_text;
}

需要引起注意的是ShowButton::mouseReleaseEvent這個函數,這個函數本身並不實現響應,只是發送一個clicked()的信號,而有關消息的響應,也就是信號對應的槽將單獨封裝在一個類中,這樣有利於實現不同的消息響應,這個處理消息響應的槽所構成的類的實現如下

clickhandler.h

#include <QUrl>
class ClickHandler : public QObject
{
    Q_OBJECT;
public:
    ClickHandler(QObject* parent);
private slots:
    void on_linkOpen();
    void on_messageBox();
};

clickhandler.cpp

#include <QDesktopServices>
#include <QMessageBox>
#include "showbutton.h"
#include "clickhandler.h"
void ClickHandler::on_linkOpen()
{
    ShowButton* button = qobject_cast<ShowButton*>(sender());
    QString text = button->getText();
    text = "www.hao123.com";
    QDesktopServices::openUrl(text);
}
void ClickHandler::on_messageBox()
{
    ShowButton* button = qobject_cast<ShowButton*>(sender());
    QString text = button->getText();
    QMessageBox::about(NULL, "msg box", text);
}
ClickHandler::ClickHandler( QObject* parent )
: QObject(parent)
{
}

這個請注意ClickHandler::on_linkOpen()這個函數,這個函數式能夠自動獲取button中的文本信息的,並將文本轉化成URL地址然後打開,這裡為了方便沒有寫有關文本信息不實地址的代碼,有興趣的讀者可以自行加上,最後程序的源代碼將放在附件中。這裡同時用到了之前提到的自定義控件布局的實現,有關問題請參考之前的文章。

main.cpp

ShowButton *showbutton1 = new ShowButton(normalPixmap, hoverPixmap, pressedPixmap);
    showbutton1->setStyle(ShowButton::IconOnly);
    QPixmap icon = ("images/yyboy16.ico");
    showbutton1->setIcon(icon);
    showbutton1->setMaximumSize(icon.size());
    ShowButton *showbutton2 = new ShowButton(normalPixmap, hoverPixmap, pressedPixmap);
    showbutton2->setStyle(ShowButton::TextOnly);
    QFont font("times", 20, QFont::Bold, true);
    QColor color(255, 0, 0);
    QString str("YY");
    showbutton2->setText(str, font, color);
    QFontMetrics metrics(font);
    qreal wid = metrics.width(str);
    qreal hei = metrics.height(); 
    showbutton2->setMaximumSize(wid, hei);
    ShowButton *showbutton3 = new ShowButton(normalPixmap, hoverPixmap, pressedPixmap);
    showbutton3->setStyle(ShowButton::TextUnderIcon);
    showbutton3->setText(str, font, color);
    showbutton3->setIcon(icon);
               
    showbutton3->setMaximumSize(wid + icon.size().width(), hei + icon.size().height());
               
    ClickHandler *clickHandler = new ClickHandler(view);
    QObject::connect(showbutton1, SIGNAL(clicked()), clickHandler, SLOT(on_linkOpen()));
    QObject::connect(showbutton2, SIGNAL(clicked()), clickHandler, SLOT(on_messageBox()));
    QGraphicsWidget *widget = new QGraphicsWidget;
    QGraphicsLinearLayout *linearLayout = new QGraphicsLinearLayout(Qt::Vertical);
    linearLayout->addItem(showbutton1);
    linearLayout->addItem(showbutton2);
    linearLayout->addItem(showbutton3);
    widget->setLayout(linearLayout);
    scene->addItem(widget);
    view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    view->resize(300, 300);
    view->setWindowTitle(QObject::tr("My hao123 Button"));
    view->show();
    app.exec();
}


本文出自 “賣萌程序員” 博客,請務必保留此出處http://7677869.blog.51cto.com/7667869/1265278

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved