带拖动效果的ListWidget

本文介绍了一款音视频效果编辑器的设计与实现,重点讨论了如何通过自定义QWidget类来创建音视频效果项,包括效果项的鼠标事件处理、样式设置及与QListWidget的交互。此外,还详细阐述了编辑器的拖放功能、效果删除操作以及按钮组的使用。

audio_effect_item_widget.h

#ifndef _XXQ_AUDIO_EFFECT_ITEM_WIDGET_H_
#define _XXQ_AUDIO_EFFECT_ITEM_WIDGET_H_

#include <QPushButton>

class QPushButton;
class QListWidgetItem;

class AudioEffectItemWidget : public QPushButton
{
    Q_OBJECT
public:
    AudioEffectItemWidget(QWidget* parent = nullptr);
    ~AudioEffectItemWidget();

    void BindItem(QListWidgetItem* item);
    QListWidgetItem* Item();
    QPushButton* DeleteButton();

    Q_SIGNAL void EffectClicked();

    virtual void mousePressEvent(QMouseEvent *event) override;
    virtual void mouseReleaseEvent(QMouseEvent *event) override;
    virtual void mouseMoveEvent(QMouseEvent *event) override;

private:
    void InitWidget();

private:
    QPushButton* setting_btn_;
    QPushButton* delete_btn_;
    QListWidgetItem* item_;
};

#endif // _XXQ_AUDIO_EFFECT_ITEM_WIDGET_H_

audio_effect_item_widget.cpp

#include "audio_effect_item_widget.h"
#include <QPushButton>
#include <QMouseEvent>
#include "audio_effect_widget.h"

AudioEffectItemWidget::AudioEffectItemWidget(QWidget* parent)
    : QPushButton(parent)
    , item_(nullptr)
{
    setFixedSize(60, 60);
    InitWidget();
    setStyleSheet("QPushButton{\
	                    border:none;\
	                    background-color:#232527;\
	                    border-radius: 4px;\
	                    color:#4A90E2;\
                        font:600 12px 'Microsoft YaHei';\
                    }\
                    QPushButton:hover {\
	                    background-color:#364A90E2;\
                    }\
                    QPushButton:pressed {\
	                    background-color:blue;\
                    }");
    setMouseTracking(true);

    connect(this, &AudioEffectItemWidget::EffectClicked, this, [=]() {
        setting_btn_->setVisible(!setting_btn_->isVisible());
        delete_btn_->setVisible(!delete_btn_->isVisible());
    });

    /*connect(delete_btn_, &QPushButton::clicked, this, [=]() {
        AudioEffectWidget* widget = reinterpret_cast<AudioEffectWidget*>(parentWidget());
        for (int i = 0; i < widget->count(); ++i)
        {
            QListWidgetItem* item = widget->item(i);
            if (widget->itemWidget(item) == this)
            {
                widget->EffectDelete(item);
                break;
            }
        }
    });*/
}

AudioEffectItemWidget::~AudioEffectItemWidget()
{
}

void AudioEffectItemWidget::BindItem(QListWidgetItem* item)
{
    item_ = item;
}

QListWidgetItem* AudioEffectItemWidget::Item()
{
    return item_;
}

QPushButton* AudioEffectItemWidget::DeleteButton()
{
    return delete_btn_;
}

void AudioEffectItemWidget::mousePressEvent(QMouseEvent *event)
{
    event->ignore();
}

void AudioEffectItemWidget::mouseReleaseEvent(QMouseEvent *event)
{
    event->ignore();
}

void AudioEffectItemWidget::mouseMoveEvent(QMouseEvent *event)
{
    event->ignore();
}

void AudioEffectItemWidget::InitWidget()
{
    setting_btn_ = new QPushButton(this);
    setting_btn_->setFixedSize(60, 16);
    setting_btn_->setVisible(false);
    setting_btn_->move(0, 44);

    delete_btn_ = new QPushButton(this);
    delete_btn_->setFixedSize(10, 10);
    delete_btn_->setVisible(false);
    delete_btn_->move(45, 5);
}

audio_effect_widget.h

#ifndef _XXQ_AUDIO_EFFECT_WIDGET_H_
#define _XXQ_AUDIO_EFFECT_WIDGET_H_

#include <QListWidget>

class QAbstractButton;
class QPushButton;
class QButtonGroup;

class AudioEffectWidget : public QListWidget
{
    Q_OBJECT

public:
    AudioEffectWidget(QWidget* parent = nullptr);
    ~AudioEffectWidget();

public slots:
    void EffectDelete(QListWidgetItem *item);
    void DeleteButtonClicked(QAbstractButton* button);

protected:
    virtual void mousePressEvent(QMouseEvent *event) override;
    virtual void mouseReleaseEvent(QMouseEvent *event) override;
    virtual void mouseMoveEvent(QMouseEvent *event) override;
    virtual void dragEnterEvent(QDragEnterEvent *event) override;
    virtual void dragMoveEvent(QDragMoveEvent *event);
    virtual void dropEvent(QDropEvent *event) override;
    virtual void startDrag(Qt::DropActions supportedActions) override;
    
//    virtual void enterEvent(QEvent *event) override;
//    virtual void leaveEvent(QEvent *event) override;
//    virtual void wheelEvent(QWheelEvent *event) override;

private:
    void InitAudioEffect();
    void InsertDragedEffect(int index);

private:
    QPoint start_pos_;
    QListWidgetItem* drag_item_;
    QButtonGroup* group_;
};

#endif // _XXQ_AUDIO_EFFECT_WIDGET_H_

audio_effect_widget.cpp

#include "audio_effect_widget.h"
#include "audio_effect_item_widget.h"
#include <QListWidgetItem>
#include <QEvent>
#include <QMouseEvent>
#include <QDragMoveEvent>
#include <QDrag>
#include <QMimeData>
#include <QApplication>
#include <QButtonGroup>

AudioEffectWidget::AudioEffectWidget(QWidget* parent)
    : QListWidget(parent)
    , drag_item_(nullptr)
{
    setFixedSize(350, 300);
    setViewMode(IconMode);
    setDragEnabled(true);
    setDragDropMode(InternalMove);
    setDropIndicatorShown(true);
    setSpacing(10);
    InitAudioEffect();
    setMouseTracking(true);

    connect(group_, SIGNAL(buttonClicked(QAbstractButton*)), this, SLOT(DeleteButtonClicked(QAbstractButton*)));
}

AudioEffectWidget::~AudioEffectWidget()
{
}

void AudioEffectWidget::EffectDelete(QListWidgetItem *item)
{
    group_->removeButton(reinterpret_cast<QPushButton*>(itemWidget(item)));
    takeItem(row(item));
    delete item;
}

void AudioEffectWidget::DeleteButtonClicked(QAbstractButton* button)
{
    AudioEffectItemWidget* widget = reinterpret_cast<AudioEffectItemWidget*>(button->parentWidget());
    EffectDelete(widget->Item());
}

void AudioEffectWidget::dragEnterEvent(QDragEnterEvent *event)
{
    if (event->mimeData()->hasFormat("text/xxq-effect"))
        event->accept();
    else
        event->ignore();
}


void AudioEffectWidget::dragMoveEvent(QDragMoveEvent *event)
{
    if (event->mimeData()->hasFormat("text/xxq-effect"))
    {
        event->setDropAction(Qt::MoveAction);
        event->accept();
    } else
        event->ignore();
}

void AudioEffectWidget::dropEvent(QDropEvent *event)
{
    if (event->mimeData()->hasFormat("text/xxq-effect"))
    {
        QByteArray effect = event->mimeData()->data("text/xxq-effect");
        QByteArray filename = event->mimeData()->data("text/xxq-filename");
        QByteArray hotkey = event->mimeData()->data("text/xxq-hotkey");

        QPoint drop_pos = event->pos();
        double min;
        int drop_index;
        for (int i = 0; i < this->count(); ++i)
        {
            QListWidgetItem* temp_item = this->item(i);
            AudioEffectItemWidget* effect = reinterpret_cast<AudioEffectItemWidget*>(itemWidget(temp_item));
            QPoint center = effect->geometry().center();
            if (i == 0)
            {
                min = QLineF(drop_pos, center).length();
                drop_index = 0;
            }
            else {
                if (QLineF(drop_pos, center).length() < min)
                {
                    drop_index = i;
                    min = QLineF(drop_pos, center).length();
                }
            }
        }

        InsertDragedEffect(drop_index);

        event->setDropAction(Qt::MoveAction);
        event->accept();
    } else
        event->ignore();
}

void AudioEffectWidget::startDrag(Qt::DropActions supportedActions)
{
    if (drag_item_) {
        QMimeData *mimeData = new QMimeData;
        mimeData->setData("text/xxq-effect", "effect1");
        mimeData->setData("text/xxq-filename", "path1");
        mimeData->setData("text/xxq-hotkey", "hotkey");
        QDrag *drag = new QDrag(this);
        drag->setMimeData(mimeData);
        drag->setHotSpot(QPoint(35, 40));
        drag->setPixmap(QPixmap("C:/Users/marui/Pictures/Saved Pictures/wind-3516697_1920.jpg").scaled(60, 60));
        if (drag->exec(supportedActions) == Qt::MoveAction)
        {
            EffectDelete(drag_item_);
            drag_item_ = nullptr;
            update();
        }
    }
}

void AudioEffectWidget::InitAudioEffect()
{
    group_ = new QButtonGroup(this);
    for (int i = 0; i < 8; i++) {
        QListWidgetItem* item = new QListWidgetItem;
        AudioEffectItemWidget* effect = new AudioEffectItemWidget(this);
        effect->setText(QString::number(i));
        effect->BindItem(item);
        item->setSizeHint(effect->size());
        addItem(item);
        setItemWidget(item, effect);

        group_->addButton(effect->DeleteButton());
    }
}

void AudioEffectWidget::InsertDragedEffect(int index)
{
    AudioEffectItemWidget* effect = new AudioEffectItemWidget(this);
    effect->setText(QString::number(index));
    QListWidgetItem* item = new QListWidgetItem;
    item->setSizeHint(effect->size());
    insertItem(index, item);
    setItemWidget(item, effect);
    group_->addButton(effect->DeleteButton());
}

void AudioEffectWidget::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton)
    {
        start_pos_ = event->pos();
        drag_item_ = itemAt(start_pos_);
    }
    event->ignore();
}

void AudioEffectWidget::mouseReleaseEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton)
    {
        if (drag_item_ && (itemAt(event->pos()) == drag_item_))
        {
            reinterpret_cast<AudioEffectItemWidget*>(itemWidget(drag_item_))->EffectClicked();
        }
    }
    event->ignore();
}

void AudioEffectWidget::mouseMoveEvent(QMouseEvent *event)
{
    if ((event->buttons() & Qt::LeftButton) && (QLineF(event->pos(), start_pos_).length() >  QApplication::startDragDistance()))
    {
        startDrag(Qt::MoveAction);
    }

    event->ignore();
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值