又到周末了,尝试实现一个图标拖拽的小程序;主要实现的功能有:
1.两个部件的图标拖动转移
2.可以切换图标查看模式,有大图标和小图标模式两种
3.可以删除图标,添加也应该不难,所以就没实现。
4.可以框选多个图标
5.改变部件大小可以自动重新布局图标
这里初始化左边有十几个图标,右边的部件是空的。
主窗口
- class MainWindow:public QMainWindow
- {
- Q_OBJECT
- public:
- MainWindow(QWidget *parent = NULL);
- ~MainWindow();
- private:
- Splitter *m_pSplitter;
- MainWidget *m_pLeftWidget;
- MainWidget *m_pRightWidget;
- QScrollArea *m_pSplitterArea;
- };
- MainWindow::MainWindow( QWidget *parent /*= NULL*/ ):QMainWindow(parent)
- {
- this->setWindowTitle("IconDemo");
- m_pSplitter = new Splitter(this);
- m_pLeftWidget = new MainWidget(this);
- m_pLeftWidget->init();
- m_pRightWidget = new MainWidget(this);
- QSize size = m_pRightWidget->size();
- m_pSplitterArea = new QScrollArea(this);
- m_pSplitterArea->setWidget(m_pSplitter);
- m_pSplitter->addWidget(m_pLeftWidget);
- m_pSplitter->addWidget(m_pRightWidget);
- m_pSplitter->setMinimumSize(QSize(700,700));
- m_pSplitterArea->setMinimumSize(QSize(700,600));
- m_pSplitter->setCollapsible(0,false);
- m_pSplitter->setCollapsible(1,false);
- this->setStyleSheet(" QFrame{background-image: url(:/DragIcon/Resources/51.jpg) }");
- this->setFixedSize(QSize(700,550));
- connect(m_pLeftWidget,SIGNAL(heightChangeSignal(int)),m_pSplitter,SLOT(heightChangeSlot(int )));
- connect(m_pRightWidget,SIGNAL(heightChangeSignal(int)),m_pSplitter,SLOT(heightChangeSlot(int )));
- }
- MainWindow::~MainWindow()
- {
- }
分割器
自定义分割器主要是为了在调节的时候可以改变其高度
- class Splitter:public QSplitter
- {
- Q_OBJECT
- public:
- Splitter(QWidget *parent = NULL);
- ~Splitter();
- protected slots:
- void heightChangeSlot(int height);
- private:
- };
- Splitter::Splitter( QWidget *parent /*= NULL*/ ):QSplitter(parent)
- {
- }
- Splitter::~Splitter()
- {
- }
- void Splitter::heightChangeSlot( int height )
- {
- this->setMinimumHeight(height);
- }
控制器和数据结构
Controller主要用于控制数据结构,添加和删除图标等。这里还自定义了一个ItemMimeData用于拖拽图标
- enum {BigIcon_Mode = 0, SmallIcon_Mode};
- struct IconItemData
- {
- QImage image;
- QString name;
- int mode ;
- IconItemData()
- {
- mode = SmallIcon_Mode;
- }
- };
- class Controller:public QObject
- {
- Q_OBJECT
- public:
- Controller(QObject *parent = NULL);
- ~Controller();
- void init();
- void addItem(IconItemData* pItem);
- void deleteItem(int index);
- void deleteItem(IconItemData* pItem);
- void changeIconMode(int mode);
- size_t getSize()
- {
- return m_IconDataVec.size();
- }
- IconItemData* getItem(int index);
- protected:
- private:
- vector<IconItemData*> m_IconDataVec;
- };
- class ItemMimeData:public QMimeData
- {
- Q_OBJECT
- public:
- ItemMimeData():QMimeData()
- {
- m_pDragItemList = NULL;
- }
- ~ItemMimeData()
- {
- if (m_pDragItemList)
- {
- delete m_pDragItemList;
- }
- }
- void SetDragDatas(QString mimeType , QList<IconItemData*> *pItemList)
- {
- m_format<<mimeType;
- m_pDragItemList = pItemList;
- }
- QStringList formats() const
- {
- return m_format;
- }
- const QList<IconItemData*>* DragItemData() const
- {
- return m_pDragItemList;
- }
- protected:
- QVariant retrieveData(const QString &mimetype, QVariant::Type preferredType) const
- {
- if (mimetype == "ItemMimeData")
- {
- return m_pDragItemList;
- }
- else
- {
- return QMimeData::retrieveData(mimetype, preferredType);
- }
- }
- private:
- QStringList m_format;
- const QList<IconItemData*> *m_pDragItemList;
- };
- void Controller::addItem( IconItemData* pItem )
- {
- if (pItem)
- {
- m_IconDataVec.push_back(pItem);
- }
- }
- void Controller::deleteItem( int index )
- {
- if ((index > 0) && (index < m_IconDataVec.size()))
- {
- vector<IconItemData*>::iterator it = m_IconDataVec.begin();
- it = it + index;
- m_IconDataVec.erase(it);
- }
- }
- void Controller::deleteItem( IconItemData* pItem )
- {
- if (pItem)
- {
- vector<IconItemData*>::iterator it = m_IconDataVec.begin();
- for (it; it != m_IconDataVec.end(); ++it)
- {
- if (pItem == *it)
- {
- m_IconDataVec.erase(it);
- break;
- }
- }
- }
- }
- IconItemData* Controller::getItem( int index )
- {
- if ((index >= 0) && (index < m_IconDataVec.size()))
- {
- return m_IconDataVec[index];
- }
- }
- void Controller::init()
- {
- for (int i = 0; i < 20; ++i)
- {
- IconItemData *pItem = new IconItemData;
- pItem->name = QString::number(i);
- QString iconPath = QString(":/DragIcon/Resources/%1.jpg").arg(i);
- QFile Iconfile(iconPath);
- if (Iconfile.exists())
- {
- pItem->image = QImage(iconPath);
- m_IconDataVec.push_back(pItem);
- }
- else
- {
- delete pItem;
- }
- }
- }
- Controller::Controller( QObject *parent /*= NULL*/ ):QObject(parent)
- {
- //init();
- }
- Controller::~Controller()
- {
- }
- void Controller::changeIconMode( int mode )
- {
- for (int i = 0; i < m_IconDataVec.size(); ++i)
- {
- m_IconDataVec[i]->mode = mode;
- }
- }
图标部件
IconItemWidget主要由一个label显示图标,lineEdit来显示名称
- class ItemNameLineEdit:public QLineEdit
- {
- Q_OBJECT
- public:
- ItemNameLineEdit(QWidget *parent = NULL);
- ~ItemNameLineEdit();
- protected:
- void mouseDoubleClickEvent ( QMouseEvent * event );
- private slots:
- void finishEditSlot();
- };
- class IconItemWidget:public QWidget
- {
- Q_OBJECT
- public:
- IconItemWidget(IconItemData *pData,QWidget *parent = NULL);
- ~IconItemWidget();
- void unSelectedItem()
- {
- m_selected = false;
- }
- void SelectItem()
- {
- m_selected = true;
- }
- IconItemData *getData()
- {
- return m_pItemData;
- }
- protected:
- void resizeEvent ( QResizeEvent * event ) ;
- void paintEvent ( QPaintEvent * event ) ;
- private:
- QLabel *m_pImage;
- ItemNameLineEdit *m_pNameLEdit;
- IconItemData *m_pItemData;
- bool m_selected;
- QPoint m_mousePressPos;
- };
- IconItemWidget::IconItemWidget( IconItemData *pData,QWidget *parent /*= NULL*/ ):QWidget(parent),m_pItemData(pData)
- {
- m_selected = false;
- m_pImage = new QLabel(this);
- m_pNameLEdit = new ItemNameLineEdit(this);
- m_pNameLEdit->setAlignment(Qt::AlignCenter);
- QSize imageSize;
- QPixmap pixmap ;
- if (m_pItemData->mode == BigIcon_Mode)
- {
- pixmap = QPixmap::fromImage(m_pItemData->image).scaled(QSize(100,100),Qt::KeepAspectRatio);
- imageSize = pixmap.size();
- m_pImage->setPixmap(pixmap);
- m_pNameLEdit->setText(m_pItemData->name);
- const int spacing = 5;
- int nameheight = 15;
- m_pImage->setGeometry(spacing,spacing,imageSize.width(),imageSize.height());
- m_pNameLEdit->setGeometry(spacing,spacing + imageSize.height(),imageSize.width(),nameheight);
- this->setFixedSize(QSize(imageSize.width() + 10,imageSize.height() + 25));
- }
- else if (m_pItemData->mode == SmallIcon_Mode)
- {
- pixmap = QPixmap::fromImage(m_pItemData->image).scaled(QSize(80,80),Qt::KeepAspectRatio);
- imageSize = pixmap.size();
- m_pImage->setPixmap(pixmap);
- m_pNameLEdit->setText(m_pItemData->name);
- const int spacing = 5;
- int nameheight = 15;
- m_pImage->setGeometry(spacing,spacing,imageSize.width(),imageSize.height());
- m_pNameLEdit->setGeometry(spacing,spacing + imageSize.height(),imageSize.width(),nameheight);
- this->setFixedSize(QSize(imageSize.width() + 10,imageSize.height() + 25));
- }
- }
- IconItemWidget::~IconItemWidget()
- {
- }
- void IconItemWidget::resizeEvent( QResizeEvent * event )
- {
- QWidget::resizeEvent(event);
- }
- void IconItemWidget::paintEvent( QPaintEvent * event )
- {
- if (m_selected)
- {
- //添加选中样式边框
- this->setStyleSheet("QLabel{border- 2px;border-style: solid;border-color: blue;}");
- }
- else
- {
- //取消选中样式
- this->setStyleSheet("");
- }
- QWidget::paintEvent(event);
- }
- void ItemNameLineEdit::mouseDoubleClickEvent( QMouseEvent * event )
- {
- this->setReadOnly(false);
- }
- ItemNameLineEdit::ItemNameLineEdit( QWidget *parent /*= NULL*/ ):QLineEdit(parent)
- {
- this->setContextMenuPolicy(Qt::NoContextMenu); //禁用默认右键菜单
- this->setReadOnly(true);
- connect(this ,SIGNAL(editingFinished ()),this,SLOT(finishEditSlot()));
- }
- ItemNameLineEdit::~ItemNameLineEdit()
- {
- }
- void ItemNameLineEdit::finishEditSlot()
- {
- this->setReadOnly(true);
- }
布局部件
- class MainWidget:public QWidget
- {
- Q_OBJECT
- public:
- MainWidget(QWidget *parent = NULL);
- ~MainWidget();
- void init();
- private slots:
- void bigModeSlot();
- void smallModeSlot();
- void reLayoutIconSlot();
- void deleteItemSlot();
- protected:
- void mousePressEvent ( QMouseEvent * event );
- void mouseMoveEvent ( QMouseEvent * event );
- void mouseReleaseEvent(QMouseEvent *event);
- void dragEnterEvent ( QDragEnterEvent * event );
- void dragLeaveEvent ( QDragLeaveEvent * event );
- void dragMoveEvent ( QDragMoveEvent * event ) ;
- void dropEvent(QDropEvent *event);
- void resizeEvent ( QResizeEvent * event );
- void paintEvent ( QPaintEvent * event );
- QRect GetItemRect( int index);
- void clear();
- void performDrag();
- void SelectItem();
- bool HitTest(QMouseEvent * event);
- bool isInVector(IconItemWidget* pItem);
- signals:
- void heightChangeSignal(int height);
- private:
- int iconMode;
- Controller *m_pController;
- vector<IconItemWidget*> m_ItemVec;
- QPushButton *m_pAddButton;
- QPoint m_mousePressPos;
- vector<IconItemWidget*> m_selectItemVec;
- QPoint m_mousePos;
- };
- MainWidget::MainWidget( QWidget *parent /*= NULL*/ ):QWidget(parent),iconMode(SmallIcon_Mode)
- {
- this->setAcceptDrops(true);
- m_pController = new Controller(this);
- //init();
- this->setMinimumWidth(100);
- }
- MainWidget::~MainWidget()
- {
- }
- void MainWidget::init()
- {
- m_pController->init();
- for (int i = 0; i < m_pController->getSize(); ++i)
- {
- IconItemWidget *pItemWidget = new IconItemWidget(m_pController->getItem(i),this);
- m_ItemVec.push_back(pItemWidget);
- }
- }
- //获取每个图标应该布局的位置
- QRect MainWidget::GetItemRect( int index )
- {
- if (index < 0 || index > m_ItemVec.size())
- {
- return QRect();
- }
- const int spacing = 5;
- int width = this->width();
- int height = this->height();
- int itemWidth = m_ItemVec[index]->width();
- int itemHeight = m_ItemVec[index]->height();
- int colCount = width / (itemWidth + spacing );
- int rowCount = height / (itemHeight + spacing);
- int row = index / colCount;
- int col = index % colCount;
- int xPos = col * (itemWidth + spacing );
- int yPos = row * (itemHeight + spacing);
- return QRect(xPos,yPos,itemWidth,itemHeight);
- }
- void MainWidget::resizeEvent( QResizeEvent * event )
- {
- //改变大小了要重新布局
- for (int i = 0; i < m_ItemVec.size(); ++i)
- {
- QRect rect = GetItemRect(i);
- if (i == m_ItemVec.size() - 1)
- {
- this->setMinimumHeight(rect.y() + 20);
- emit heightChangeSignal(this->height());
- }
- m_ItemVec[i]->setGeometry(rect);
- }
- QWidget::resizeEvent(event);
- }
- void MainWidget::paintEvent( QPaintEvent * event )
- {
- if (m_mousePos.x() == 0 && m_mousePos.y() == 0)
- {
- return;
- }
- //画红色选框
- QRect rect(m_mousePressPos,m_mousePos);
- QPainter painter(this);
- painter.setPen(Qt::red);
- painter.drawRect(rect);
- update();
- QWidget::paintEvent(event);
- }
- void MainWidget::mousePressEvent( QMouseEvent * event )
- {
- m_mousePressPos = event->pos();
- //点击空白处则情况选中,
- //如果m_selectItemVec大小为1,则也要清空下面再另外选中
- //右键单击也要清空m_selectItemVec
- if (!HitTest(event) || (m_selectItemVec.size() == 1) ||Qt::RightButton == event->button())
- {
- for (int i = 0; i < m_selectItemVec.size(); ++i)
- {
- m_selectItemVec[i]->unSelectedItem();
- }
- m_selectItemVec.clear();
- }
- for (int i = 0; i < m_ItemVec.size(); ++i)
- {
- QRect rect = GetItemRect(i);
- if (rect.contains(event->pos()) && (!isInVector(m_ItemVec[i]))) //图标尚未被选中则添加到m_selectItemVec
- {
- m_selectItemVec.push_back(m_ItemVec[i]);
- m_ItemVec[i]->SelectItem();
- }
- }
- QWidget *pWidget = QApplication::focusWidget(); //如果正在编辑名称,点击别的地方可以结束编辑
- if (pWidget)
- {
- pWidget->clearFocus();
- }
- //右键菜单
- if (Qt::RightButton == event->button())
- {
- QMenu *pMenu = new QMenu(this);
- QAction *pBigModeAct = new QAction(tr("大图标"),pMenu);
- QAction *pSmallModeAct = new QAction(tr("小图标"),pMenu);
- QAction *pDeleteAct = new QAction(tr("删除"),pMenu);
- if (m_selectItemVec.size() > 0) //有选中的则弹出删除菜单
- {
- pMenu->addAction(pDeleteAct);
- connect(pDeleteAct,SIGNAL(triggered()),this,SLOT(deleteItemSlot()));
- }
- else
- {
- //点击空白处则可切换图标模式
- pMenu->addAction(pBigModeAct);
- pMenu->addAction(pSmallModeAct);
- connect(pBigModeAct,SIGNAL(triggered()),this,SLOT(bigModeSlot()));
- connect(pSmallModeAct,SIGNAL(triggered()),this,SLOT(smallModeSlot()));
- }
- pMenu->exec(event->globalPos());
- delete pMenu;
- }
- QWidget::mousePressEvent(event);
- }
- //大图标模式
- void MainWidget::bigModeSlot()
- {
- m_pController->changeIconMode(BigIcon_Mode);
- reLayoutIconSlot();
- this->update();
- }
- //小图标模式
- void MainWidget::smallModeSlot()
- {
- m_pController->changeIconMode(SmallIcon_Mode);
- reLayoutIconSlot();
- this->update();
- }
- void MainWidget::reLayoutIconSlot()
- {
- clear(); //先清除
- for (int i = 0; i < m_pController->getSize(); ++i)
- {
- //重新生成图标
- IconItemWidget *pItemWidget = new IconItemWidget(m_pController->getItem(i),this);
- m_ItemVec.push_back(pItemWidget);
- }
- for (int i = 0; i < m_ItemVec.size(); ++i)
- {
- QRect rect = GetItemRect(i);
- m_ItemVec[i]->setGeometry(rect);
- m_ItemVec[i]->show(); //重新生成,布局图标必须show才能显示
- }
- this->repaint();
- }
- void MainWidget::clear()
- {
- qDeleteAll(m_ItemVec);
- m_ItemVec.clear();
- }
- void MainWidget::mouseMoveEvent( QMouseEvent * event )
- {
- if (event->buttons() & Qt::LeftButton && (m_selectItemVec.size() > 0))
- {
- if (( m_mousePressPos - event->pos()).manhattanLength() > QApplication::startDragDistance())
- {
- performDrag();
- }
- }
- else
- {
- m_mousePos = event->pos();
- }
- QWidget::mouseMoveEvent(event);
- }
- void MainWidget::mouseReleaseEvent( QMouseEvent *event )
- {
- if (m_mousePos.x() == 0 && m_mousePos.y() == 0)
- {
- return;
- }
- else
- {
- //release鼠标再进行选择
- SelectItem();
- }
- m_mousePos = QPoint();
- QWidget::mouseReleaseEvent(event);
- }
- void MainWidget::dragEnterEvent( QDragEnterEvent * event )
- {
- const ItemMimeData *pMimeData = (const ItemMimeData*)event->mimeData();
- const QList<IconItemData*>* plist = pMimeData->DragItemData();
- if (plist)
- {
- event->accept();
- }
- }
- void MainWidget::dragLeaveEvent( QDragLeaveEvent * event )
- {
- }
- void MainWidget::dragMoveEvent( QDragMoveEvent * event )
- {
- event->accept();
- }
- void MainWidget::performDrag()
- {
- QDrag *pDrag = new QDrag(this);
- ItemMimeData *pData = new ItemMimeData;
- QList<IconItemData*> *plist = new QList<IconItemData*>;
- for (int i = 0; i < m_selectItemVec.size(); ++i)
- {
- plist->append(m_selectItemVec[i]->getData());
- }
- pData->SetDragDatas("ItemMimeData",plist);
- pDrag->setMimeData(pData);
- QPixmap pixmap = QPixmap::fromImage(m_selectItemVec[0]->getData()->image).scaled(50,50,Qt::KeepAspectRatio);
- pDrag->setPixmap(pixmap);
- pDrag->exec(Qt::CopyAction);
- //delete m_selectItemVec[0];
- }
- void MainWidget::dropEvent( QDropEvent *event )
- {
- const ItemMimeData *pMimeData = (const ItemMimeData*)event->mimeData();
- const QList<IconItemData*>* plist = pMimeData->DragItemData();
- if (plist)
- {
- for (int i = 0; i < plist->size(); ++i)
- {
- m_pController->addItem(plist->at(i));
- }
- reLayoutIconSlot();
- event->accept();
- }
- }
- void MainWidget::deleteItemSlot()
- {
- //删除再重新布局
- for (int i = 0; i < m_selectItemVec.size(); ++i)
- {
- m_pController->deleteItem(m_selectItemVec[i]->getData());
- }
- reLayoutIconSlot();
- }
- //框选多个图标
- void MainWidget::SelectItem()
- {
- QRect rect(m_mousePressPos,m_mousePos);
- for (int i = 0; i < m_ItemVec.size(); ++i)
- {
- QPoint centerPos = GetItemRect(i).center();
- if (rect.contains(centerPos))
- {
- m_ItemVec[i]->SelectItem();
- m_selectItemVec.push_back(m_ItemVec[i]);
- }
- }
- }
- //有点击图标则返回true,否则返回false
- bool MainWidget::HitTest( QMouseEvent * event )
- {
- for (int i = 0; i < m_ItemVec.size(); ++i)
- {
- QRect rect = GetItemRect(i);
- if (rect.contains(event->pos()))
- {
- return true;
- }
- }
- return false;
- }
- //检查图标是否已经被选中
- bool MainWidget::isInVector(IconItemWidget* pItem )
- {
- for (int i = 0; i < m_selectItemVec.size(); ++i)
- {
- if (m_selectItemVec[i] == pItem)
- {
- return true;
- }
- }
- return false;
- }
结果截图;
http://blog.csdn.net/hai200501019/article/details/11704343