對於普通的QWidget控件,我們可以很容易的通過QLayout, QBoxLayout, QHBoxLayout之間的嵌套完成對眾多系統控件的很漂亮的布局,但是對於自定義控件,我們會感覺很糾結,因為QGraphicsLayoutItem, QGraphicsLayout都不能夠添加自定義控件,只有QGraphicsLinearLayout的addItem可以添加QGraphicsLayoutItem類型的元素可能是布局,也可能是控件),我們發現存在如下的繼承關系
這樣我們就可以通過QGraphicsWidget在場景中間接地添加控件,使用這種方法之後不需要再向scene中添加控件,只需要一次將含有layout的控件widget直接加到布局中scene中即可。
QGraphicsLinearLayout *linearLayout = new QGraphicsLinearLayout(Qt::Vertical); QGraphicsWidget *widget = new QGraphicsWidget; linearLayout->addItem(linkLabel); linearLayout->addItem(appLabel); widget->setLayout(linearLayout); scene->addItem(widget);
這裡的linkLabel和appLabel是我們自定義的兩個控件,scene就是場景了,但是這種方式添加的控件會存在一定的問題,這裡為了說明方便,給出主函數的全部代碼
#include <QtGui> #include <QGraphicsLayoutItem> #include "showlabel.h" #include "clickhandler.h" int main(int argc, char *argv[]) { QApplication app(argc, argv); QGraphicsScene *scene = new QGraphicsScene; QGraphicsView *view = new QGraphicsView(scene); ShowLabel *linkLabel = new ShowLabel("www.hao123.com"); //設置字體 QFont linkFont("Arial", 20, QFont::Bold, true); linkLabel->setFont(linkFont); //設置下劃線 linkLabel->setUnderline(true); //設置顏色 QColor linkColor(255, 0, 0); linkLabel->setColor(linkColor); ShowLabel *appLabel = new ShowLabel("open app"); //設置字體 QFont appFont("times", 20, QFont::Bold, true); appLabel->setFont(appFont); //設置下劃線 appLabel->setUnderline(true); //設置顏色 QColor appColor(0, 255, 0); appLabel->setColor(appColor); //設置控件的大小 linkLabel->setPreferredSize(rectLink.width(), rectLink.height()); ClickHandler *clickHandler = new ClickHandler(view); QObject::connect(linkLabel, SIGNAL(clicked()), clickHandler, SLOT(on_linkOpen())); QObject::connect(appLabel, SIGNAL(clicked()), clickHandler, SLOT(on_messageBox())); QRectF rectApp = appLabel->getRect(); //appLabel->setMaximumSize(rectApp.width(), rectApp.height()); //設置場景的大小 scene->setSceneRect(0, 0, 300, 300); QGraphicsLinearLayout *linearLayout = new QGraphicsLinearLayout(Qt::Vertical); QGraphicsWidget *widget = new QGraphicsWidget; linearLayout->addItem(linkLabel); linearLayout->addItem(appLabel); widget->setLayout(linearLayout); scene->addItem(widget); QRect rt = linkLabel->getRect(); QRect lt = appLabel->getRect(); //設置視口的大小 view->resize(300, 300); view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); view->setWindowTitle(QObject::tr("My hao123 Label")); view->show(); return app.exec(); }
如果這樣做將會產生如下的錯誤
大家可能看到了,下面的一行雖然控件只有字符“open app”寬度的大小,但是卻被拉伸了,原因是在使用Qt::Vertical方式布局的時候,系統會自動只關注組件的高度,而組件的寬度將會對齊上一個控件,我想水平方式布局情況也應該是類似的,因此需要增加如下的代碼來控制下面的控件的大小
appLabel->setMaximumSize(rectApp.width(), rectApp.height());
這樣就正確了,
這裡給出其他的代碼
ShowLabel.h
#pragma once #ifndef SHOWLABEL_H #define SHOWLABEL_H #include <QGraphicsWidget> class QGraphicsSceneMouseEvent; class QGraphicsSceneHoverEvent; class ShowLabel: public QGraphicsWidget { Q_OBJECT public: ShowLabel(const QString &string); void setText(const QString &string); QString text(); void setFont(const QFont& font); void setColor(const QColor& color); void setUnderline(bool isUnderLine); QRect getRect(); signals: void clicked(); protected: void mousePressEvent(QGraphicsSceneMouseEvent *e); void mouseReleaseEvent(QGraphicsSceneMouseEvent *e); void hoverEnterEvent(QGraphicsSceneHoverEvent *e); void hoverLeaveEvent(); protected: virtual QRectF boundingRect(); virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); private: QString m_text; bool m_isPressed; bool m_isUnderLine; QFont m_font; QColor m_penstyle; }; #endif //SHOWLABEL_Hsho
ShowLabel.cpp
#include <QDesktopServices> #include <QUrl> #include <QGraphicsSceneMouseEvent> #include <QGraphicsSceneHoverEvent> #include <QPainter> #include <QStyleOptionGraphicsItem> #include "showlabel.h" #include "clickhandler.h" ShowLabel::ShowLabel(const QString &string) : m_isPressed(false), m_isUnderLine(false) { m_text = string; setFlag(QGraphicsItem::ItemIsMovable, true); setFlag(QGraphicsItem::ItemIsSelectable, true); setFlag(QGraphicsItem::ItemSendsGeometryChanges, true); setAcceptHoverEvents(true); } void ShowLabel::setText(const QString &string) { if ( m_text != string) { m_text = string; update(); } } void ShowLabel::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { Q_UNUSED(option); Q_UNUSED(widget); setUnderline(m_isUnderLine); painter->setFont(m_font); painter->setPen(m_penstyle); QRect textRect = boundingRect().toRect(); painter->fillRect(rect(), (0, 0, 255)); painter->drawText(textRect, Qt::AlignLeft, m_text); } void ShowLabel::setFont(const QFont& ft) { m_font = ft; } void ShowLabel::setColor(const QColor& color) { m_penstyle = color; } void ShowLabel::mousePressEvent(QGraphicsSceneMouseEvent *e) { if (e->button() == Qt::LeftButton) { m_isPressed = true; setCursor(Qt::ArrowCursor); } } void ShowLabel::mouseReleaseEvent(QGraphicsSceneMouseEvent *e) { if (e->button() == Qt::LeftButton && m_isPressed && m_isUnderLine) { emit clicked(); setCursor(Qt::PointingHandCursor); m_isPressed = false; } } void ShowLabel::hoverEnterEvent(QGraphicsSceneHoverEvent *) { setCursor(Qt::PointingHandCursor); } void ShowLabel::hoverLeaveEvent() { setCursor(Qt::ArrowCursor); } QRectF ShowLabel::boundingRect() { QFontMetrics metrics(m_font); qreal width = metrics.width(m_text); qreal height = metrics.height(); return QRectF(0,0,width,height); } void ShowLabel::setUnderline( bool isUnderLine ) { m_isUnderLine = isUnderLine; m_font.setUnderline(true); } QRect ShowLabel::getRect() { return boundingRect().toRect(); } QString ShowLabel::text() { return m_text; }
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 "showlabel.h" #include "clickhandler.h" void ClickHandler::on_linkOpen() { ShowLabel* label = qobject_cast<ShowLabel*>(sender()); QString text = label->text(); QDesktopServices::openUrl(text); } void ClickHandler::on_messageBox() { ShowLabel* label = qobject_cast<ShowLabel*>(sender()); QString text = label->text(); QMessageBox::about(NULL, "msg box", text); } ClickHandler::ClickHandler( QObject* parent ) : QObject(parent) { }
本文出自 “賣萌程序員” 博客,請務必保留此出處http://7677869.blog.51cto.com/7667869/1264729