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

QT中自定義控件的布局問題

編輯:關於C語言

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

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