qt 拖拽 修改大小(二)

最近项目需要实现windows下橡皮筋的效果,所以对此做了一些了解,特此记录。

首先windows系统是支持橡皮筋效果的,需要使用win32方 法:SystemParametersInfo(SPI_SETDRAGFULLWINDOWS, showFullWindow, NULL, 0);showFullWindow是一个变量,如果需要windows默认支持橡皮筋则需要传递参数false,否则传递参数true,如果使用 windows默认的橡皮筋缩放,效果如图1所示,会产生一个矩形框,不管是窗口移动还是放大缩小,都会对该矩形框作用,然后当鼠标弹起时,真实窗口才会 移动或者放大缩小。如果不使用橡皮筋拖拽的方式,那么窗口就是实时的拖拽。

图1 windows橡皮筋

在使用Qt窗口时,如果需要支持windows系统这种方式的拖拽,不能够使用setGeometry该函数来移动或者放大缩小窗口,而需要 重写QWidget::nativeEvent这个方法,该方法是在消息进入qt事件循环之前调用的,也就是说该方法会在mouseEvent等方法之前 调用,nativeEvent方法的实现请看另一篇文章qt 拖拽 修改大小,不过在我使用的过程中,使用了HTCAPTION这个属性后,原始窗口的双击放大事件被屏蔽掉了,到现在原因未搞清。在qt 拖拽 修改大小这篇文字中提到的bug,我用迂回的方式解决了,那就是使用Qt::WindowSystemMenuHint属性,但是窗口的放大和缩小使用另一种方式解决。

下面就是我使用代理的方式来支持窗口拖拽,由于该代理代码行数过多,我只写下重点的部分,该代理代码我也是从别人那儿拷贝的,后来根据我自己的理解和项目需求添加了一些东西。

代理头文件

  1 #ifndef NC_FRAMELESS_HELPER_H
  2
  3 #define NC_FRAMELESS_HELPER_H
  4
  5 #include
  6
  7 #include
  8
  9 #include
 10
 11 #include "commonControls/include/commoncontrols_global.h"
 12
 13 class WidgetResizeHandlerImpl;
 14
 15 class CRubberBand : public QRubberBand
 16
 17 {
 18
 19 public:
 20
 21     CRubberBand(QRubberBand::Shape s, QWidget * parent = nullptr);
 22
 23     ~CRubberBand();
 24
 25 protected:
 26
 27     virtual void paintEvent(QPaintEvent *) Q_DECL_OVERRIDE;
 28
 29     virtual void resizeEvent(QResizeEvent *) Q_DECL_OVERRIDE;
 30
 31     void changeEvent(QEvent *) Q_DECL_OVERRIDE;
 32
 33     void showEvent(QShowEvent *) Q_DECL_OVERRIDE;
 34
 35     void moveEvent(QMoveEvent *) Q_DECL_OVERRIDE;
 36
 37 private:
 38
 39 };
 40
 41 //鼠标状态,可以获取鼠标当前和目标窗口的关系
 42
 43 class CursorPosCalculator
 44
 45 {
 46
 47 public:
 48
 49     CursorPosCalculator(){ reset(); }
 50
 51     void reset();
 52
 53     void recalculate(const QPoint& globalMousePos, const QRect& frameRect);
 54
 55 public:
 56
 57     bool onEdges;
 58
 59     bool onLeftEdge;
 60
 61     bool onRightEdge;
 62
 63     bool onTopEdge;
 64
 65     bool onBottomEdge;
 66
 67     bool onTopLeftEdge;
 68
 69     bool onBottomLeftEdge;
 70
 71     bool onTopRightEdge;
 72
 73     bool onBottomRightEdge;
 74
 75     static int mBorderWidth;
 76
 77 };
 78
 79 //真正的处理操作类
 80
 81 class WidgetData
 82
 83 {
 84
 85 public:
 86
 87     WidgetData(WidgetResizeHandlerImpl * d, QWidget* topLevelWidget);
 88
 89     ~WidgetData();
 90
 91     QWidget * widget();
 92
 93     void handleWidgetEvent(QEvent * event);//处理指定窗口事件入口函数
 94
 95     void updateRubberBandStatus();
 96
 97 private:
 98
 99     void updateCursorShape(const QPoint& globalMousePos);
100
101     void resizeWidget(const QPoint& globalMousePos);
102
103     void moveWidget(const QPoint& globalMousePos);
104
105     void handleMousePressEvent(QMouseEvent* event);
106
107     void handleMouseReleaseEvent(QMouseEvent* event);
108
109     void handleMouseMoveEvent(QMouseEvent* event);
110
111     void handleLeaveEvent(QEvent* event);
112
113     void handleHoverMoveEvent(QHoverEvent* event);
114
115 private:
116
117     bool mLeftButtonPressed = false;
118
119     bool mCursorShapeChanged = false;
120
121     Qt::WindowFlags mWindowFlags;
122
123     QPoint mDragPos;//拖拽位置起点
124
125     QWidget * mWidget = nullptr;//被代理的窗口指针
126
127     CRubberBand * mRubberBand = nullptr;//橡胶类,支持橡胶操作
128
129     CursorPosCalculator mPressedMousePos;//鼠标按下时光标信息
130
131     CursorPosCalculator mMoveMousePos;//鼠标移动时光标信息
132
133     WidgetResizeHandlerImpl * d_ptr;
134
135 };
136
137 ///说明:当QWidget设置了Qt::FramelessWindowHint属性时,可以借助该类完成:拖拽+窗口大小更改
138
139 class COMMONCONTROLS_EXPORT WidgetResizeHandler : public QObject
140
141 {
142
143 public:
144
145     explicit WidgetResizeHandler(QObject* parent = 0);
146
147     ~WidgetResizeHandler();
148
149 public:
150
151     void activateOn(QWidget * topLevelWidget);//添加topLevelWidget事件代理
152
153     void removeFrom(QWidget * topLevelWidget);//移除topLevelWidget事件代理
154
155     Qt::CursorShape CursorShape(QWidget * widget);
156
157     //窗口移动 default:true
158
159     void setWidgetMovable(bool movable);
160
161     bool isWidgetMovable();
162
163     //大小可变 default:true
164
165     void setWidgetResizable(bool resizable);
166
167     bool isWidgetResizable();
168
169     // 橡胶式窗口移动 default:false
170
171     void useRubberBandOnMove(bool use);
172
173     bool isUsingRubberBandOnMove();
174
175     //橡胶式修改大小 default:false
176
177     void useRubberBandOnResize(bool use);
178
179     bool isUsingRubberBandOnResisze();
180
181     void setBorderWidth(int newBorderWidth);
182
183     int borderWidth();
184
185     //局部可移动
186
187     void useLocalMoveabled(bool use);
188
189     void addLocalWidget(QWidget *);
190
191 protected:
192
193     virtual bool eventFilter(QObject * obj, QEvent * event) Q_DECL_OVERRIDE;//?????????????????????????????????????
194
195 private:
196
197     WidgetResizeHandlerImpl * d_ptr;
198
199 };
200
201 #endif // NC_FRAMELESS_HELPER_H

上边头文件中都有基本的注释,我就不过多解释了,下边我主要说下原理

在需要代理的类中声明WidgetResizeHandler对象,然后使用activateOn方法把需要代理的窗口添加到代理,注意被代 理的窗口需要含有Qt::Window属性明也就是需要时顶层窗口,如果对于一个复杂的窗口进行代理时,可能会出现一些意向不到的问题,比如:1、 QLabel接受富文本时,代理拿不到鼠标弹起事件,QToolButton对象不放到布局时,代理也拿不到鼠标弹起事件,这会导致代理不能正常使用,因 此我对该代理进行了修改,添加了useLocalMoveabled接口,允许代理只对局部窗口进行移动,这样是解决了我前边提到的两个问题。如果仔细看 应该也能看到我的代理也是使用setGeometry方法来拖拽窗口的,那么和我之前谈论的橡皮筋方式就有出入了,这个时候重点才来了,哈哈哈,继续往下 看,头文件中有个类CRubberBand,他是继承自QRubberBand,该类就模拟了一个橡皮筋的过程,只是qt提供的类接口有限,有一些写过很 难达到,比如说我要实现一些复杂的代理界面,那么我们就只能自己绘制了,我通过重新实现paintEvent函数,对该类画了一个灰色的矩形框,代码如 下:

QPainter p(this);

p.setPen(QPen(QColor(102, 102, 102), 4));

QRect rect = this->rect().adjusted(2, 2, -3, -3);

p.drawRect(rect);

如果照着我我上边所说的流程走,就会发现除了一个矩形框之外还会有一个背景色填充,这个时候就奇怪了,我们paintEvent并没有画背景 啊,呵呵呵,只需要在构造函数里加上这句话即可setAttribute(Qt::WA_NoSystemBackground),效果如图2所示。

图2 定制橡皮筋

下边我添加一些代理部分代码

1、CRubberBand构造函数

 1 CRubberBand::CRubberBand(QRubberBand::Shape s, QWidget * parent) :QRubberBand(QRubberBand::Rectangle, parent)
 2
 3 {
 4
 5     setAttribute(Qt::WA_TranslucentBackground);
 6
 7 #ifndef Q_DEAD_CODE_FROM_QT4_WIN
 8
 9     setAttribute(Qt::WA_NoSystemBackground);
10
11 #endif //Q_DEAD_CODE_FROM_QT4_WIN
12
13     setWindowFlags(windowFlags() | Qt::FramelessWindowHint);
14
15 }

2、使用activateOn后,窗口存储并验证

 1 WidgetData::WidgetData(WidgetResizeHandlerImpl * d, QWidget * topLevelWidget)
 2
 3 {
 4
 5     this->d_ptr = d;
 6
 7     mWidget = topLevelWidget;
 8
 9     mWidget->setMouseTracking(true);
10
11     mWindowFlags = mWidget->windowFlags();
12
13     //mWindowFlags |= Qt::CustomizeWindowHint | Qt::FramelessWindowHint;
14
15     mWindowFlags |= Qt::FramelessWindowHint;
16
17     mWidget->setWindowFlags(mWindowFlags);
18
19     //mWidget->setWindowFlags( Qt::Popup | Qt::CustomizeWindowHint|Qt::FramelessWindowHint );
20
21     //Bug fix, mouse move events does not propagate from child widgets.
22
23     //so need the hover events.
24
25     mWidget->setAttribute(Qt::WA_Hover);
26
27     updateRubberBandStatus();
28
29     bool visible = mWidget->isVisible();//防止非widget被代理
30
31     mWidget->setVisible(visible);
32
33 }

3、当被代理的窗口有鼠标事件时,先有代理处理

 1 void WidgetData::handleWidgetEvent(QEvent * event)
 2
 3 {
 4
 5     switch (event->type())
 6
 7     {
 8
 9     case QEvent::MouseButtonPress:
10
11         handleMousePressEvent(static_cast(event));
12
13         break;
14
15     case QEvent::MouseButtonRelease:
16
17         handleMouseReleaseEvent(static_cast(event));
18
19         break;
20
21     case QEvent::MouseMove:
22
23         handleMouseMoveEvent(static_cast(event));
24
25         break;
26
27     case QEvent::Leave:
28
29         handleLeaveEvent(event);
30
31         break;
32
33     case QEvent::HoverMove:
34
35         handleHoverMoveEvent(static_cast(event));
36
37         break;
38
39     }
40
41 }

4、下边5个函数分别是上边的具体实现

  1 void WidgetData::handleMousePressEvent(QMouseEvent * event)
  2
  3 {
  4
  5     if (event->button() == Qt::LeftButton)
  6
  7     {
  8
  9         mLeftButtonPressed = true;
 10
 11         QRect frameRect = mWidget->frameGeometry();
 12
 13         mPressedMousePos.recalculate(event->globalPos(), frameRect);
 14
 15         mDragPos = event->globalPos() - frameRect.topLeft();
 16
 17         if (mPressedMousePos.onEdges)
 18
 19         {
 20
 21             if (d_ptr->mUseRubberBandOnResize)
 22
 23             {
 24
 25                 mRubberBand->setGeometry(frameRect);
 26
 27                 //mRubberBand->show();
 28
 29             }
 30
 31         }
 32
 33         else if (d_ptr->mUseRubberBandOnMove)
 34
 35         {
 36
 37             mRubberBand->setGeometry(frameRect);
 38
 39             //mRubberBand->show();
 40
 41         }
 42
 43         if (d_ptr->mLocalOnMove)//启用局部拖拽功能后   需要处理不在指定范围内的拖拽,并过滤掉
 44
 45         {
 46
 47             bool canMove = false;
 48
 49             for (int i = 0; i < d_ptr->mLocalWidget.size(); ++i)
 50
 51             {
 52
 53                 if (d_ptr->mLocalWidget[i]->rect().contains(d_ptr->mLocalWidget[i]->mapFromGlobal(event->globalPos())))
 54
 55                 {
 56
 57                     canMove = true;
 58
 59                     break;
 60
 61                 }
 62
 63             }
 64
 65             if (canMove == false && mPressedMousePos.onEdges == false)
 66
 67             {
 68
 69                 mLeftButtonPressed = false;
 70
 71             }
 72
 73         }
 74
 75     }
 76
 77 }
 78
 79 void WidgetData::handleMouseReleaseEvent(QMouseEvent* event)
 80
 81 {
 82
 83     if (event->button() == Qt::LeftButton)
 84
 85     {
 86
 87         d_ptr->mCanMoveFlag = false;
 88
 89         mLeftButtonPressed = false;
 90
 91         mPressedMousePos.reset();
 92
 93         if (mRubberBand && mRubberBand->isVisible())
 94
 95         {
 96
 97             mRubberBand->hide();
 98
 99             mWidget->setGeometry(mRubberBand->geometry());
100
101         }
102
103     }
104
105 }
106
107 void WidgetData::handleMouseMoveEvent(QMouseEvent* event)
108
109 {
110
111     if (mLeftButtonPressed)
112
113     {
114
115         if (d_ptr->mWidgetResizable && mPressedMousePos.onEdges)
116
117         {
118
119             resizeWidget(event->globalPos());
120
121         }
122
123         else if (d_ptr->mWidgetMovable)
124
125         {
126
127             moveWidget(event->globalPos());
128
129         }
130
131     }
132
133     else if (d_ptr->mWidgetResizable)
134
135     {
136
137         updateCursorShape(event->globalPos());
138
139     }
140
141 }
142
143 void WidgetData::handleLeaveEvent(QEvent*)
144
145 {
146
147     if (!mLeftButtonPressed)
148
149     {
150
151         mWidget->unsetCursor();
152
153     }
154
155 }
156
157 void WidgetData::handleHoverMoveEvent(QHoverEvent* event)
158
159 {
160
161     if (mLeftButtonPressed)
162
163     {
164
165         return;
166
167     }
168
169     if (d_ptr->mWidgetResizable)
170
171     {
172
173         updateCursorShape(mWidget->mapToGlobal(event->pos()));
174
175     }
176
177 }

5、更新鼠标状态

 1 void WidgetData::updateCursorShape(const QPoint & globalMousePos)
 2
 3 {
 4
 5     if (mWidget->isFullScreen() || mWidget->isMaximized())
 6
 7     {
 8
 9         if (mCursorShapeChanged)
10
11         {
12
13             mWidget->unsetCursor();
14
15         }
16
17         return;
18
19     }
20
21     mMoveMousePos.recalculate(globalMousePos, mWidget->frameGeometry());
22
23     if (mMoveMousePos.onTopLeftEdge || mMoveMousePos.onBottomRightEdge)
24
25     {
26
27         mWidget->setCursor(Qt::SizeFDiagCursor);
28
29         mCursorShapeChanged = true;
30
31     }
32
33     else if (mMoveMousePos.onTopRightEdge || mMoveMousePos.onBottomLeftEdge)
34
35     {
36
37         mWidget->setCursor(Qt::SizeBDiagCursor);
38
39         mCursorShapeChanged = true;
40
41     }
42
43     else if (mMoveMousePos.onLeftEdge || mMoveMousePos.onRightEdge)
44
45     {
46
47         mWidget->setCursor(Qt::SizeHorCursor);
48
49         mCursorShapeChanged = true;
50
51     }
52
53     else if (mMoveMousePos.onTopEdge || mMoveMousePos.onBottomEdge)
54
55     {
56
57         mWidget->setCursor(Qt::SizeVerCursor);
58
59         mCursorShapeChanged = true;
60
61     }
62
63     else
64
65     {
66
67         if (mCursorShapeChanged)//修改鼠标状态
68
69         {
70
71             mWidget->unsetCursor();
72
73             mCursorShapeChanged = false;
74
75         }
76
77     }
78
79 }

6、修改窗口大小和移动位置

  1 void WidgetData::resizeWidget(const QPoint& globalMousePos)
  2
  3 {
  4
  5     QRect origRect;
  6
  7     if (d_ptr->mUseRubberBandOnResize)
  8
  9     {
 10
 11         origRect = mRubberBand->frameGeometry();
 12
 13     }
 14
 15     else
 16
 17     {
 18
 19         origRect = mWidget->frameGeometry();
 20
 21     }
 22
 23     int left = origRect.left();
 24
 25     int top = origRect.top();
 26
 27     int right = origRect.right();
 28
 29     int bottom = origRect.bottom();
 30
 31     origRect.getCoords(&left, &top, &right, &bottom);
 32
 33     int minWidth = mWidget->minimumWidth();
 34
 35     int minHeight = mWidget->minimumHeight();
 36
 37     if (mPressedMousePos.onTopLeftEdge)
 38
 39     {
 40
 41         left = globalMousePos.x();
 42
 43         top = globalMousePos.y();
 44
 45     }
 46
 47     else if (mPressedMousePos.onBottomLeftEdge)
 48
 49     {
 50
 51         left = globalMousePos.x();
 52
 53         bottom = globalMousePos.y();
 54
 55     }
 56
 57     else if (mPressedMousePos.onTopRightEdge)
 58
 59     {
 60
 61         right = globalMousePos.x();
 62
 63         top = globalMousePos.y();
 64
 65     }
 66
 67     else if (mPressedMousePos.onBottomRightEdge)
 68
 69     {
 70
 71         right = globalMousePos.x();
 72
 73         bottom = globalMousePos.y();
 74
 75     }
 76
 77     else if (mPressedMousePos.onLeftEdge)
 78
 79     {
 80
 81         left = globalMousePos.x();
 82
 83         int max_width = mWidget->maximumWidth();
 84
 85         if (right - left > max_width)
 86
 87         {
 88
 89             return;
 90
 91         }
 92
 93     }
 94
 95     else if (mPressedMousePos.onRightEdge)
 96
 97     {
 98
 99         right = globalMousePos.x();
100
101     }
102
103     else if (mPressedMousePos.onTopEdge)
104
105     {
106
107         top = globalMousePos.y();
108
109     }
110
111     else if (mPressedMousePos.onBottomEdge)
112
113     {
114
115         bottom = globalMousePos.y();
116
117     }
118
119     QRect newRect(QPoint(left, top), QPoint(right, bottom));
120
121     if (newRect.isValid())
122
123     {
124
125         if (minWidth > newRect.width())
126
127         {
128
129             //determine what has caused the width change.
130
131             if (left != origRect.left())
132
133                 newRect.setLeft(origRect.left());
134
135             else
136
137                 newRect.setRight(origRect.right());
138
139         }
140
141         if (minHeight > newRect.height())
142
143         {
144
145             //determine what has caused the height change.
146
147             if (top != origRect.top())
148
149                 newRect.setTop(origRect.top());
150
151             else
152
153                 newRect.setBottom(origRect.bottom());
154
155         }
156
157         if (d_ptr->mUseRubberBandOnResize)
158
159         {
160
161             if (mRubberBand->isVisible() == false)
162
163             {
164
165                 mRubberBand->show();
166
167             }
168
169             mRubberBand->setGeometry(newRect);
170
171         }
172
173         else
174
175         {
176
177             //mWidget->setGeometry(newRect);
178
179             mWidget->move(newRect.topLeft());
180
181             mWidget->resize(newRect.size());
182
183         }
184
185     }
186
187     else
188
189     {
190
191         //qDebug() << "Calculated Rect is not valid" << newRect;
192
193     }
194
195 }
196
197 void WidgetData::moveWidget(const QPoint & globalMousePos)
198
199 {
200
201     bool canMove = false;
202
203     if (d_ptr->mLocalOnMove == true && d_ptr->mCanMoveFlag != true)
204
205     {
206
207         for (int i = 0; i < d_ptr->mLocalWidget.size(); ++i)
208
209         {
210
211             if (d_ptr->mLocalWidget[i]->rect().contains(d_ptr->mLocalWidget[i]->mapFromGlobal(globalMousePos)))
212
213             {
214
215                 canMove = true;
216
217                 d_ptr->mCanMoveFlag = true;
218
219                 break;
220
221             }
222
223         }
224
225     }
226
227     else
228
229     {
230
231         canMove = true;
232
233     }
234
235     if (canMove)
236
237     {
238
239         if (d_ptr->mUseRubberBandOnMove)
240
241         {
242
243             if (mRubberBand->isVisible() == false)
244
245             {
246
247                 mRubberBand->show();
248
249             }
250
251             mRubberBand->move(globalMousePos - mDragPos);
252
253         }
254
255         else
256
257         {
258
259             mWidget->move(globalMousePos - mDragPos);
260
261         }
262
263     }
264
265 }

更多博文

时间: 2024-12-27 06:40:44

qt 拖拽 修改大小(二)的相关文章

qt 拖拽 修改大小

写次篇文章之前,qt窗口的放大缩小和拖拽我都是通过setGeometry方法实现的,但是作为windows程序,windows支持橡 皮筋式(拖拽时有一个虚框)拖拽和拉伸.通过setGeometry方式实现功能是没有这种效果,幸好qt5中提供了一个本地事件处理接口 nativeEvent,具体功能可以看帮助文档,本文只讲述用该接口实现窗口放大.缩小和拖拽,具体实现代码如下: 1 virtual bool nativeEvent(const QByteArray &, void *, long *

解决Delphi图形化界面的TEdit、TLable等组件手动拖拽固定大小,但是编译之后显示有误的情况

经常遇到这样的情况,在我们使用Delphi的可视化工具进行UI设计的时候,我们拖拽TEdit或者Label组件,并且在可视化界面上设置它们的长.宽 但是当我们编译和运行程序的时候,却发现真正显示出来的 TEdit或者TLabel组件并不是我们在可视化界面所拖拽的长和宽(显示的“有问题”) 这个时候我们可以参考下面的具体事例解决: 当然这只是其中的一种方法,绝对还有其他的方法,而且我也不知道下面所讲的这种方法是不是很好的,所以还待补充 1.我们在Delphi的可视化界面上需要一个TEdit和TLa

简单的弹出拖拽窗口(二)

接上文 简单的弹出拖拽窗口(一) 下面开始具体分析代码部分: 首先我们先确认下结构: 悬浮窗口:初始不可见.包括标题栏和内容栏,标题栏内有标题和关闭按钮. 遮罩层:初始不可见.用于设置弹出悬浮窗口时的半透明背景, 按钮:用于点击弹出悬浮窗口. 下面进行详细解释 1.要让窗口能自由移动,那么窗口的定位(position)应该采用绝对定位(absolute): /*登录浮层组件*/ 1 .popup{ 2 display:none; /*初始隐藏*/ 3 width: 380px; 4 height

jquery 实现div边界拖拽控制大小

html <div id="container"> <!-- Left side --> <div id="left"> This is the left side's content! </div> <!-- Right side --> <div id="right"> <!-- Actual resize handle --> <div id=&quo

textarea拖拽控制

一.用处 textarea默认时允许用户以拖拽形式来改变textarea大小,但textarea的大小变化会撑大其父节点,有时会破坏整体布局,有时我们并不希望textarea随意拖拽. forklift 二.原因 通过调用 window.getComputedStyle(textarea元素, null).resize 返回both,我们可以知道原来是resize样式属性默认为both(可调整尺寸). 三.resize参数 用于设置UserAgent调整元素尺寸的机制,就是说设置用户能否和如何自

atitit.D&amp;D drag&amp;drop拖拽文件到界面功能 html5 web 跟个java swing c#.net c++ 的总结

atitit.D&D drag&drop拖拽文件到界面功能 html5 web 跟个java swing c#.net c++ 的总结 1. DND的操作流程 1 2. Html5 注解事件 document.dragover >>preventDefault 1 3. 代码(js) 1 4. C++ 实现拖曳 2 5. QT拖拽功能简介 - pcsuite的专栏 - 博客频道 - CSDN.NET.htm 2 1. DND的操作流程 Dragenter 事件::更改提示的颜色

JQuery拖拽改变元素的尺寸

"元素拖拽改变大小"其实和"元素拖拽"一个原理,只是所动态改变的对象不同而已,主要在于 top.left.width.height 的运用,相对实现起来也非常容易.以下附出源码原型,弄明白了原理再扩展其他实际应用,思路就变得简单.清晰得多了.先来看看效果:塔河县臧清机械 下面是 JavaScript Code view source print? 01 <script type="text/javascript"> 02     /*

独创轻松实现拖拽,改变层布局

通过JS实现拖拽变更层布局的代码,改变当前行的第一列,同时改变其他行的布局 <!DOCTYPE html PUBLIC"-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head>

H5拖拽事件-- 自定义创建a标签热区

有两个BUG未更正, 1.拖拽后,动态创建的div始终在鼠标的下方,导致拖拽定位不准确 2.当窗口为自适应时,定位left为百分比,窗口改变大小时会存在定位偏差 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <script src="./jquery-1