對於普通的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_HshoShowLabel.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