Qt官方示例:Fridge Magnets Example(冰箱贴)

冰箱贴类:

#include "draglabel.h"
#include <QtWidgets>

DragLabel::DragLabel(const QString &text, QWidget *parent)
    : QLabel(parent)
{
    QFontMetrics metric(font());
    QSize size = metric.size(Qt::TextSingleLine, text);

    QImage image(size.width() + 12, size.height() + 12, QImage::Format_ARGB32_Premultiplied);
    image.fill(qRgba(0, 0, 0, 0));

    QLinearGradient gradient(0, 0, 0, image.height()-1);
    gradient.setColorAt(0.0, Qt::white);
    gradient.setColorAt(0.2, QColor(200, 200, 255));
    gradient.setColorAt(0.8, QColor(200, 200, 255));
    gradient.setColorAt(1.0, QColor(127, 127, 200));

    QPainter painter(&image);
    painter.setRenderHint(QPainter::Antialiasing);
    painter.setBrush(gradient);
    painter.drawRoundedRect(QRectF(0.5, 0.5, image.width()-1, image.height()-1),25, 25, Qt::RelativeSize);
    painter.setFont(font());
    painter.setBrush(Qt::black);
    painter.drawText(QRect(QPoint(6, 6), size), Qt::AlignCenter, text);

    setPixmap(QPixmap::fromImage(image));
    m_labelText = text;
}

QString DragLabel::labelText() const
{
    return m_labelText;
}

一个自定义的 QLabel,根据创建时传入的文本设确定一个图片的尺寸,使用渐变的画刷在图片绘制一个圆角矩形和文本,然后设置标签显示此图片。

然后是一个白色的窗口:

DragWidget::DragWidget(QWidget *parent)
    : QWidget(parent)
{
    QFile dictionaryFile(QStringLiteral(":/dictionary/words.txt"));
    dictionaryFile.open(QFile::ReadOnly);
    QTextStream inputStream(&dictionaryFile);

    int x = 5;
    int y = 5;

    while (!inputStream.atEnd())
    {
        QString word;
        inputStream >> word;
        if (!word.isEmpty())
        {
            DragLabel *wordLabel = new DragLabel(word, this);
            wordLabel->move(x, y);
            wordLabel->show();
            wordLabel->setAttribute(Qt::WA_DeleteOnClose);
            x += wordLabel->width() + 2;
            if (x >= 245)
            {
                x = 5;
                y += wordLabel->height() + 2;
            }
        }
    }

    QPalette newPalette = palette();
    newPalette.setColor(QPalette::Window, Qt::white);
    setPalette(newPalette);

    setMinimumSize(400, qMax(200, y));
    setWindowTitle(tr("Fridge Magnets"));

    setAcceptDrops(true);
}

从一个文本文件中读取内容:

每次读取一行,读取一行就创建一个冰箱贴并移动到相应的位置。最后设置窗口支持拖放。

鼠标按下的操作:

void DragWidget::mousePressEvent(QMouseEvent *event)
{
    DragLabel *child = static_cast<DragLabel*>(childAt(event->position().toPoint()));
    if (!child)
        return;

    QPoint hotSpot = event->position().toPoint() - child->pos();//鼠标按在child上的位置

    QByteArray itemData;
    QDataStream dataStream(&itemData, QIODevice::WriteOnly);
    dataStream << child->labelText() << QPoint(hotSpot);

    QMimeData *mimeData = new QMimeData;
    mimeData->setData(fridgetMagnetsMimeType(), itemData);
    mimeData->setText(child->labelText());

    QDrag *drag = new QDrag(this);
    drag->setMimeData(mimeData);
    drag->setPixmap(child->pixmap());
    drag->setHotSpot(hotSpot);

    child->hide();

    if (drag->exec(Qt::MoveAction | Qt::CopyAction, Qt::CopyAction) == Qt::MoveAction)
        child->close();
    else
        child->show();
}

这里定义了一种自定义MIME类型:

static inline QString fridgetMagnetsMimeType() { return QStringLiteral("application/x-fridgemagnet"); }

内联的非成员函数,这种写法值得学习。

其中包含了了冰箱贴的文本和鼠标按下的位置。

开始拖放操作后,如果是拖放移到那么冰箱贴就隐藏了,拖动过程中显示的只是 QDrag::pixmap()。

拖动进入事件和拖动移到事件:

void DragWidget::dragEnterEvent(QDragEnterEvent *event)
{
    if (event->mimeData()->hasFormat(fridgetMagnetsMimeType()))
    {
        if (children().contains(event->source()))
        {
            event->setDropAction(Qt::MoveAction);
            event->accept();
        }
        else
        {
            event->acceptProposedAction();
        }
    }
    else if (event->mimeData()->hasText())
    {
        event->acceptProposedAction();
    }
    else
    {
        event->ignore();
    }
}

void DragWidget::dragMoveEvent(QDragMoveEvent *event)
{
    if (event->mimeData()->hasFormat(fridgetMagnetsMimeType()))
    {
        if (children().contains(event->source()))
        {
            event->setDropAction(Qt::MoveAction);
            event->accept();
        }
        else
        {
            event->acceptProposedAction();
        }
    }
    else if (event->mimeData()->hasText())
    {
        event->acceptProposedAction();
    }
    else
    {
        event->ignore();
    }
}

这两个没啥好说的,主要是拖动放下事件:

void DragWidget::dropEvent(QDropEvent *event)
{
    if (event->mimeData()->hasFormat(fridgetMagnetsMimeType()))
    {
        const QMimeData *mime = event->mimeData();
        QByteArray itemData = mime->data(fridgetMagnetsMimeType());
        QDataStream dataStream(&itemData, QIODevice::ReadOnly);

        QString text;
        QPoint offset;
        dataStream >> text >> offset;

        DragLabel *newLabel = new DragLabel(text, this);
        newLabel->move(event->position().toPoint() - offset);
        newLabel->show();
        newLabel->setAttribute(Qt::WA_DeleteOnClose);

        if (event->source() == this)
        {
            event->setDropAction(Qt::MoveAction);
            event->accept();
        }
        else
        {
            event->acceptProposedAction();
        }
    }
    else if (event->mimeData()->hasText())
    {
        QStringList pieces = event->mimeData()->text().split(QRegularExpression(QStringLiteral("\\s+")), Qt::SkipEmptyParts);
        QPoint position = event->position().toPoint();

        for (const QString &piece : pieces)
        {
            DragLabel *newLabel = new DragLabel(piece, this);
            newLabel->move(position);
            newLabel->show();
            newLabel->setAttribute(Qt::WA_DeleteOnClose);

            position += QPoint(newLabel->width(), 0);
        }

        event->acceptProposedAction();
    }
    else
    {
        event->ignore();
    }
}

第一个分支在拖动放下的位置新建冰箱贴,从 QMimeData 取出数据设置其文本和位置。

第二个分支指示拖动能用空白符分割的文本到当前窗口,则使用其文本创建冰箱贴。

涉及到的类:

This directory contains the Qt3D project for Qt5: * Qt3D QML bindings and * Qt3D C++ APIs Building Qt3D ================== Qt5 is a rapidly changing bleeding edge environment. This branch is our initial support for it and thus is also rapidly changing and bleeding edge. This branch is experimental, and unsupported. This information is provided for advanced use only. No guarantees about API stability or even if this works at all are supplied, use at your own risk. First fetch the Qt5 source tree and Qt3D master branch: cd ~/depot git clone ssh://codereview.qt-project.org:29418/qt/qt5.git cd qt5 ./init-repository --codereview-username \ --module-subset=qtbase,qtsvg,qtdeclarative,qttools,qtxmlpatterns,qtdoc,qlalr,qtrepotools,qtqa,qtlocation,qt3d git submodule foreach "git fetch gerrit && git reset --hard gerrit/master" cd qt3d scp -p -P 29418 codereview.qt-project.org:hooks/commit-msg .git/hooks/ git fetch gerrit git checkout --track -b master gerrit/master If you are reading this file then somehow you probably already got this far anyway. Now build Qt5, which will also build Qt3D as a module: cd ~/build mkdir qt5 cd qt5 ~/depot/qt5/configure -developer-build -opensource -confirm-license -no-webkit -no-phonon -nomake tests \ -nomake examples -declarative -opengl -svg && make -j 4 What's in Qt3D ================== Directory structure: src/threed/ This is the main library of the Qt3D project, containing abstractions for cross-platform GL, shaders, lighting models, and so on. src/plugins/ Scene format loading plugins. src/imports/ QML import plugins. util/ Various utilities that are useful when working with Qt3D. examples/ Some examples of using Qt3D QML bindings and Qt3D C++ API. demos/ Some more complex demos of using Qt3D QML bindings and Qt3D C++ API. tests/auto/qml3d/ Unit tests for the QML bindings. tests/auto/threed/ Unit tests for the C++ API doc/ Documentation. devices/symbian/ Symbian deployment file Documentation ============= The documentation can be generated with "make docs". It will be placed into "doc/html" in the build directory. Packages ======== This section is only for those developing Qt3D. Read on to discover how the building of packages works. This section is also important if you want to change how the structure of the Qt3D pro files work. To build Qt3D, run: qmake && make The .pro files will cause the toolchain to place the libraries, QML files and meshes of Qt3D directly into place, as part of the compile process. The files go into the bin/ directory, and the executables can be run directly from there. If you are doing a developer build, plugins will be installed in such a way that Qt will find them. After building the tree the install step is invoked using the INSTALL_ROOT environment export to cause the installation rules to place all the files into a sandboxed install tree, ready for packaging: INSTALL_ROOT=tmp make install Examples ======== Some examples require assimp library to parse the content. Go to http://assimp.sourceforge.net/ and build and install the assimp library. Then configure Qt3D to include assimp and run qmake && make.
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值