實現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