new出一个QToolButton,设置关闭按钮图标。按钮图片一般都以4种状态提供,将4张图片拼成1张png。所以每次只需取出图片中的1/4就行,然后将关闭按钮移动到右上角。
想在Qt中实现这3种效果,很简单,只需在窗体中安装事件过滤器即可。enum EButtonMouseState { EButtonMouseDefault = 0, EButtonMouseEnter, EButtonMousePress, EButtonMouseNone }; void Preview360::createEventFilter() { //安装事件过滤器 m_pButtonClose->installEventFilter(this); } //设置按钮图标 void Preview360::setButtonIcon(QToolButton *btn, EButtonMouseState state) { QPixmap pixmap(":/images/btn_close.png"); int nWidth = pixmap.width()/4; int nHeight = pixmap.height(); btn->setIcon(QIcon(pixmap.copy(QRect(state * nWidth, 0, nWidth, nHeight)))); btn->setIconSize(QSize(nWidth, nHeight)); } bool Preview360::eventFilter(QObject *target, QEvent *event) { EButtonMouseState state = EButtonMouseNone; //对几种事件进行处理,这下载对Qt的事件过滤器,很清楚了,实践结合理论=... if (target == m_pButtonClose) { if (event->type() == QEvent::Enter) { state = EButtonMouseEnter; } else if (event->type() == QEvent::Leave) { state = EButtonMouseDefault; } else if (((QMouseEvent *)event)->button() == Qt::LeftButton) { if (event->type() == QEvent::MouseButtonPress) { state = EButtonMousePress; //若点击在关闭按钮上,不拖动图像 m_mousePressFlag = false; } else if (event->type() == QEvent::MouseButtonRelease) { state = EButtonMouseDefault; } } if (state != EButtonMouseNone) { setButtonIcon((QToolButton *)target, state); } } //处理完自定义拦截的事件,还要调用一次QWidget默认的事件过滤函数 return QWidget::eventFilter(target, event); }
窗体和图片的移动涉及到鼠标事件,只需事件鼠标的一些事件就可以达到预期的效果,主要的事件是:
void mousePressEvent(QMouseEvent *); void mouseReleaseEvent(QMouseEvent *); void mouseMoveEvent(QMouseEvent *);
void Preview360::mousePressEvent(QMouseEvent *e) { if (e->button() == Qt::LeftButton) { m_mouseSrcPos = e->pos(); //在y坐标小于40的区域,鼠标拖动使窗体移动 if (m_mouseSrcPos.y() <= 40) { m_mouseMoveWindowFlag = true; } else { //大于40的区域,鼠标拖动使图片移动 m_currentFgXpos = m_pLabelFgTotal->x(); m_mousePressFlag = true; } } //右键鼠标,右移图片 else if (e->button() == Qt::RightButton) { if (getLabelMove()) { if (m_currentFgIndex > 0) { m_currentFgIndex--; moveCurrentPage(false); //右移 } } } } void Preview360::mouseReleaseEvent(QMouseEvent *e) { int xpos = 0; if (m_mousePressFlag) { if (getLabelMove()) { m_mouseDstPos = e->pos(); xpos = m_mouseDstPos.x() - m_mouseSrcPos.x(); if (xpos > 0)//右移 { if (xpos >= WINDOW_ONEBUTTON_WIDTH) { if (m_currentFgIndex > 0) { m_currentFgIndex--; moveCurrentPage(false); //右移 } else { moveCurrentPage(true); //左移 } } else { moveCurrentPage(true); //左移 } } else //左移 { if (xpos <= -WINDOW_ONEBUTTON_WIDTH) { if (m_currentFgIndex < WINDOW_PAGE_COUNT-1) { m_currentFgIndex++; moveCurrentPage(true); //左移 } else { moveCurrentPage(false); //右移 } } else { moveCurrentPage(false); //右移 } } m_mousePressFlag = false; } } else if (m_mouseMoveWindowFlag) { m_mouseMoveWindowFlag = false; } } void Preview360::mouseMoveEvent(QMouseEvent *e) { int x = 0; if (m_mousePressFlag) { if (getLabelMove()) { m_mouseDstPos = e->pos(); x = m_mouseDstPos.x() - m_mouseSrcPos.x(); setLabelMove(false); m_pLabelFgTotal->move(m_currentFgXpos + x, WINDOW_START_Y); setLabelMove(true); } } else if (m_mouseMoveWindowFlag) { m_mouseDstPos = e->pos(); this->move(this->pos() + m_mouseDstPos - m_mouseSrcPos); } }
void Preview360::slotChangeCurrentPage(CLabel *label) { int index = 0; for (int i = 0; i < WINDOW_PAGE_COUNT; i++) { if (label == m_pLabelBtnArray[i]) { //找出当前按钮的序号 index = i; break; } } //移动的几种可能性,对于x坐标 //index=0, 将label移动到-680*0 //index=1, 将label移动到-680*1 //index=2, 将label移动到-680*2 //index=3, 将label移动到-680*3 //点击左边的按钮 右移 if (index < m_currentFgIndex) { while(index != m_currentFgIndex) { m_currentFgIndex--; moveCurrentPage(false); } } else if (index > m_currentFgIndex) //点击右边的按钮 左移 { while(index != m_currentFgIndex) { m_currentFgIndex++; moveCurrentPage(true); } } else { //... } }
void Preview360::keyPressEvent(QKeyEvent *e) { if (getLabelMove()) { switch(e->key()) { case Qt::Key_Left: case Qt::Key_Up: if (m_currentFgIndex > 0) { m_currentFgIndex--; moveCurrentPage(false); //右移 } break; case Qt::Key_Right: case Qt::Key_Down: if (m_currentFgIndex < WINDOW_PAGE_COUNT-1) { m_currentFgIndex++; moveCurrentPage(true); //左移 } break; default: break; } } }
void Preview360::moveCurrentPage(bool direction) { int currentXpos = 0;//当前label的x坐标 int destXpos = 0;//目标x坐标 //改变当前页面对应的按钮 changeCurrentButton(); //图片的几个分割点 //0-680, 680-1360, 1360-2040, 2040-2720 //真:向左移; 假:向右移 if (direction) { //左移的几种可能性,对于x坐标 //index=0, 将label移动到-680*0 //index=1, 将label移动到-680*1 //index=2, 将label移动到-680*2 //index=3, 将label移动到-680*3 setLabelMove(false); currentXpos = m_pLabelFgTotal->x(); destXpos = -WINDOW_WIDTH * m_currentFgIndex; while(currentXpos > destXpos) { m_pLabelFgTotal->move(currentXpos-WINDOW_PAGE_MOVE, WINDOW_START_Y); currentXpos = m_pLabelFgTotal->x(); qApp->processEvents(QEventLoop::AllEvents); } m_pLabelFgTotal->move(destXpos, WINDOW_START_Y); setLabelMove(true); } else { //右移的几种可能性,对于x坐标,与左移一致 //index=0, 将label移动到-680*0 //index=1, 将label移动到-680*1 //index=2, 将label移动到-680*2 //index=3, 将label移动到-680*3 setLabelMove(false); currentXpos = m_pLabelFgTotal->x(); destXpos = -WINDOW_WIDTH * m_currentFgIndex; while(currentXpos < destXpos) { m_pLabelFgTotal->move(currentXpos+WINDOW_PAGE_MOVE, WINDOW_START_Y); currentXpos = m_pLabelFgTotal->x(); qApp->processEvents(QEventLoop::AllEvents); } m_pLabelFgTotal->move(destXpos, WINDOW_START_Y); setLabelMove(true); } }防止界面冻结:
8.将控件置顶
在最后补充下,要将需要的控件raise到栈顶:
//raise these widget m_pLabelBg1->raise(); m_pButtonClose->raise(); for (int i = 0; i < WINDOW_BUTTON_COUNT; i++) { m_pLabelBtnArray[i]->raise(); }多个控件涉及到重叠的问题,只有这样重新调整栈顺序才能达到需要的效果。