Qt 拖拽 动态 垃圾箱

前些天看了Qt的拖拽,觉得Qt的拖拽还是蛮灵活;但widgets在移动端类似的app应用场景下,确实显得有一些笨拙;但同时它功能强大,灵活性非常高。

我在这里实现的是一个类似于android手机卸载软件时的动态垃圾箱。先看下效果是这样的。


支持自动缩放,自适应啰。



被拖动的目标显然用QListWidget来存放最方便,这也是拖拽的一个典型应用。垃圾箱的动画使用了QPropertyAnimation,其它的就是拖拽的事件监听了;下面请看代码

#include "widget.h"
#include <QApplication>
#include <QListWidget>
#include <QPropertyAnimation>
#include <QVBoxLayout>
#include <QPushButton>
#include <QBitmap>
#include <QPainter>
#include <QResizeEvent>
#include <QDebug>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    QVBoxLayout *lay = new QVBoxLayout(this);
    listWidget = new QListWidget;
    listWidget->setViewMode(QListWidget::IconMode); //设置显示方式
    listWidget->addItem(new QListWidgetItem(QIcon(":/img/test.png"),QStringLiteral("test"))); //放一个item到ListWidget
    listWidget->addItem(new QListWidgetItem(QIcon(":/img/trash.png"),QStringLiteral("trash")));//放一个item到ListWidget
    listWidget->installEventFilter(this); //为ListWidget添加事件监听,用于检测item项是否被拖动
    lay->addWidget(listWidget); //主布局

    reRect = new QLabel(this);            //顶上垃圾箱背景label
    reRect->setAutoFillBackground(true);
    QPalette pal = reRect->palette();
    pal.setBrush(QPalette::Background,Qt::lightGray); //设置背景色
    reRect->setPalette(pal);
    QPixmap pix(":/img/trash.png");
    reRect->resize(width(),pix.height() + 20);  //重设label尺寸
    reRect->setMinimumHeight(pix.height() + 20); 

    reLabel = new QLabel;                //垃圾桶
    reLabel->resize(pix.size());        //重调垃圾桶label尺寸
    reLabel->setPixmap(pix);
    reLabel->setMask(pix.mask());
    reLabel->setAcceptDrops(true);     //使能够接受拖拽的落下
    reLabel->installEventFilter(this); //添加事件监听
    QHBoxLayout *hlay = new QHBoxLayout(reRect);
    hlay->addWidget(reLabel,0,Qt::AlignCenter); //在背景label中居中

    ani = new QPropertyAnimation(reRect, "geometry"); //新建动画,绑定属性为背景label的geometry
    ani->setEasingCurve(QEasingCurve::InCurve);       //设置动画插值方式
    ani->setDuration(150);                            //动画持续时间
    connect(ani,&QPropertyAnimation::finished,[&]{ani->setDirection(QAbstractAnimation::Direction(!ani->direction()));}); //改变方向
}

void Widget::resizeEvent(QResizeEvent *event)
{
    reRect->resize(event->size().width(),reRect->height()); //当窗口发生变化时,重调背景label尺寸
    if(initFlag){      //当第一次初始化时,移动到窗体外面
        initFlag = false;
        reRect->move(reRect->x(),-reRect->height());
    }
    ani->setStartValue(QRect(reRect->x(),-reRect->height(),reRect->width(),reRect->height())); //设置动画起点值
    ani->setEndValue(reRect->rect());   //设置动画终点值
    return QWidget::resizeEvent(event);
}

Widget::~Widget()
{

}

bool Widget::eventFilter(QObject *watched, QEvent *event)
{
    if(reLabel = qobject_cast<QLabel*>(watched)){
        if(event->type() == QEvent::DragEnter){
            QDragEnterEvent *drageEnterE{nullptr};
            try{
                drageEnterE = dynamic_cast<QDragEnterEvent*>(event);
            }catch(std::bad_cast &e){
                qDebug() << e.what();
            }
            if(drageEnterE){
                trashPainted = false;
                drageEnterE->acceptProposedAction(); //当拖拽事件进入时,启用接收拖拽
            }
            return true;
        }else if(event->type() == QEvent::Drop){
            QDropEvent *dropE{nullptr};
            try{
                dropE = dynamic_cast<QDropEvent*>(event);
            }catch(std::bad_cast &e){
                qDebug() << e.what();
            }
            if(dropE){
                listWidget->takeItem(listWidget->row(listWidget->currentItem())); //当在垃圾箱落下时,从ListWidget中删除当前项,并恢复垃圾箱颜色
                QPixmap *pix = const_cast<QPixmap*>(reLabel->pixmap());
                *pix = QPixmap(":/img/trash.png");
                reLabel->repaint();
            }
            return true;
        }else if(event->type() == QEvent::DragMove){
            QDragMoveEvent *mvEvent{nullptr};
            try{
                mvEvent = dynamic_cast<QDragMoveEvent*>(event);
            }catch(std::bad_cast &e){
                qDebug() << e.what();
            }
            if(mvEvent && !trashPainted){   //当item项在垃圾箱上漂荡时,改变垃圾箱颜色
                QPixmap *pix = const_cast<QPixmap*>(reLabel->pixmap());
                QPainter p(pix);
                p.initFrom(pix);
                p.fillRect(pix->rect(),QColor(200,0,0,50));
                reLabel->repaint();
                trashPainted = !trashPainted;
            }
            return true;
        }else if(event->type() == QEvent::DragLeave){
            QDragLeaveEvent *leEvent{nullptr};
            try{
                leEvent = dynamic_cast<QDragLeaveEvent*>(event);
            }catch(std::bad_cast &e){
                qDebug() << e.what();
            }
            if(leEvent){
                QPixmap *pix = const_cast<QPixmap*>(reLabel->pixmap()); //当拖拽事件离开时,恢复垃圾箱颜色
                *pix = QPixmap(":/img/trash.png");
                reLabel->repaint();
            }
            return true;
        }
    }else if(listWidget == qobject_cast<QListWidget*>(watched)){
        QChildEvent *childEvent{nullptr};
        switch (event->type()) {
        case QEvent::ChildAdded:
            try{
                childEvent = dynamic_cast<QChildEvent*>(event);
            }catch(std::bad_cast &e){
                qDebug() << e.what();
            }
            if(childEvent){  //当item项被视为拖动时,启动动画
                ani->start();
            }
            break;
        case QEvent::ChildRemoved:
            try{
                childEvent = dynamic_cast<QChildEvent*>(event);
            }catch(std::bad_cast &e){
                qDebug() << e.what();
            }
            if(childEvent){  //当item拖动结束时,启动动画
                ani->start();
            }
            break;
        }
    }
    return QWidget::eventFilter(watched,event);
}

我做得比较简单,如果完美一点,应该在最后那段代码中;当item被拖动时应该判断动画执行方向,如果此时动画还是离开窗体中,就应该先停止动画,然后改变方向,再启动动画;当拖动结束时也是一样的。不过我这里设置的动画持续时间比较短,这个现象问题不大。

需要源码可到处下载



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: QT工具箱中的拖放工具TableWidget是一种用于在窗口中创建和管理表格的工具。使用TableWidget可以轻松地创建一个表格视图,并且可以通过拖放操作方便地向表格中添加数据。 在QT工具箱中,我们可以拖拽TableWidget工具到窗口界面中。拖拽操作非常简单,只需点击并按住TableWidget工具,然后将其拖动到窗口中的指定位置松开即可。一旦拖拽完成,TableWidget将被添加到窗口中,并且可以随时进行进一步的定制和编辑。 使用TableWidget工具,我们可以通过添加行和列来创建表格。可以在表格中插入或删除行列,并设置每个单元格的内容。此外,TableWidget还提供了丰富的样式和布局选项,可以帮助我们自定义表格的外观和交互方式。 通过拖放操作,我们可以方便地将数据拖拽到TableWidget中。例如,我们可以从其他控件或外部数据源中拖拽数据到表格的特定单元格中。拖放操作可以实现数据的快速导入和交换。 总而言之,QT工具箱中的拖放工具TableWidget是一种实用工具,它能够帮助我们轻松创建和管理表格,并通过拖放操作方便地添加和操作数据。无论是开发桌面应用程序还是实现特定的数据处理功能,TableWidget都是一个非常有用的工具。 ### 回答2: Qt工具箱是Qt开发环境中的一个重要功能,用于选择和添加Qt控件。拖拽工具是其中的一个功能,可以帮助开发者快速创建控件。 在Qt工具箱中,有一个名为TableWidget的控件。TableWidget是一个用于显示和编辑二维数据的表格控件。开发者可以通过拖拽工具将TableWidget控件添加到他们的应用程序界面中。 要使用拖拽工具添加TableWidget控件,首先需要打开Qt工具箱窗口。在工具箱中,可以看到各种Qt控件的图标,包括TableWidget。单击TableWidget图标,然后将鼠标拖拽到应用程序的窗口中,释放鼠标按钮。这样,一个TableWidget控件就被添加到了窗口中。 添加TableWidget控件后,开发者可以通过设置属性和调用方法来自定义控件的外观和行为。例如,可以设置TableWidget的行数和列数,设置表头文本,设置单元格的内容,设置单元格的背景颜色等等。开发者还可以通过连接信号和槽来处理TableWidget中的用户交互事件。 TableWidget控件是一个非常强大和灵活的工具,可以用于在应用程序中创建各种表格和数据展示界面。开发者可以根据自己的需求,使用TableWidget控件来展示数据、编辑数据,甚至提供丰富的交互功能。 总的来说,Qt工具箱中的拖拽工具是一个方便的功能,可以帮助开发者快速添加TableWidget控件到他们的Qt应用程序中,从而实现强大的表格和数据展示功能。 ### 回答3: Qt工具箱是用于开发Qt应用程序的集成开发环境(IDE),拖拽工具是其中一个非常重要的功能之一。在Qt工具箱中,我们可以找到各种用于构建用户界面的控件和工具。 其中,TableWidget(表格控件)是Qt中常用的一个控件,它可以用于显示数据项的表格。这个控件可以非常方便地进行拖拽操作。 在Qt工具箱中,我们可以找到一个TableWidget控件,将其拖拽到应用程序的设计界面上。一旦拖拽完成,我们就可以在属性编辑器中对这个TableWidget进行各种属性的设置,例如表格的行数、列数、表头等。 在运行程序时,我们可以使用TableWidget控件中提供的接口函数,通过代码的方式操作表格中的数据,例如添加新的数据行、删除数据行、更新数据等。同时,通过设置表格的样式,我们还可以对表格的外观进行定制化。 拖拽工具的使用,为我们改善了开发效率和开发体验。我们不再需要手动编写复杂的代码来创建和配置各种界面控件,只需在Qt工具箱中找到相应的控件,拖拽到设计界面上,并进行适当设置即可。这大大缩短了开发时间,提高了开发效率。 总之,Qt工具箱提供了丰富的拖拽工具,其中包括了强大的TableWidget控件,它为我们开发Qt应用程序提供了便捷的方式。通过使用这些工具,我们能够轻松地创建和定制化各种界面控件,提供更好的用户体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值