過qq的同學都知道,qq主窗口在靠近界面邊緣時會自動隱藏,而當鼠標再一次進入的時候會自動彈出,接下來我將記錄下自己實現(xiàn)的類似同樣的功能,支持多屏幕靠邊隱藏。文章末尾我提供了demo的下載地址,這個樣例我是從網(wǎng)上下載下來,并自己進行了優(yōu)化,主要針對邊界判斷和多屏幕支持。
下面是我做的效果展示,由于錄屏軟件錄制屏幕頂端不好錄制,所以錄制了屏幕左側(cè),我自己測試的結(jié)果是:屏幕左、屏幕上和屏幕右都沒有問題。如果發(fā)現(xiàn)問題的同學可以聯(lián)系我。
效果預覽
接下來我將每一步的實現(xiàn)代碼分別做以解釋:
一、窗口移動
做windows桌面程序的同學,應該都會這個功能,不過我還是貼一下代碼吧,雖然不是特別復雜。要實現(xiàn)這個功能只需要重寫3個方法,分別是:mousePressEvent、mouseMoveEvent和mouseReleaseEvent。
1、mousePressEvent
1 void FloatingWidget::mousePressEvent(QMouseEvent *e)
2 {
3 if (e->button()==Qt::LeftButton)
4 {
5 m_dragPosition=e->globalPos() - frameGeometry().topLeft();
6 e->accept();
7 }
8 }
2、mouseMoveEvent
1 void FloatingWidget::mouseMoveEvent(QMouseEvent * event)
2 {
3 if (event->buttons() & Qt::LeftButton)
4 {
5 QPoint pos=event->globalPos() - m_dragPosition;
6
7 QDesktopWidget * desktop=qApp->desktop();
8 QRect rect=desktop->screenGeometry(QCursor::pos());
9 QRect frameRect=frameGeometry();
10 if (rect.top() >=pos.y())//修正頂端位置
11 {
12 pos.setY(rect.top());
13 }
14
15 if (rect.left()>=pos.x())//修正左側(cè)位置
16 {
17 int leftScreenNumber=desktop->screenNumber(pos - QPoint(width(), 0));
18 if (desktop->screenGeometry(leftScreenNumber).contains((pos - QPoint(width(), 0)))==false)
19 {
20 pos.setX(rect.left());
21 }
22 }
23
24 if (rect.right() <=pos.x() + frameRect.width())//修正右側(cè)位置
25 {
26 int rightScreenNumber=desktop->screenNumber(pos + QPoint(width(), 0));
27 if (desktop->screenGeometry(rightScreenNumber).contains((pos + QPoint(width(), 0)))==false)
28 {
29 pos.setX(rect.right() - frameRect.width());
30 }
31 }
32 move(pos);
33
34 event->accept();
35 }
36 }
這個函數(shù)里有3個位置修正判斷,主要實現(xiàn)了在鼠標拖拽時,保證窗口不移出屏幕。
3、mouseReleaseEvent
1 void FloatingWidget::mouseReleaseEvent(QMouseEvent * event)
2 {
3 QWidget::mouseReleaseEvent(event);
4 }
通過上述3個方式的重寫,就實現(xiàn)了窗口的拖拽,并且我們的窗口是不能拖拽到屏幕意外
二、屏幕邊界自動隱藏
窗口移動到屏幕邊界時,自動隱藏我們的窗口,首先我們來考慮這么幾個問題:
1、什么時候需要隱藏窗口
2、什么時候需要顯示窗口
3、檢測窗口是否需要隱藏
4、窗口顯示時怎么回到起始位置
問題1:隱藏窗口在我們鼠標移除窗口的時候,這個時候需要注意,鼠標在屏幕邊界時不能隱藏
問題2:鼠標進入到我們的窗口時
問題3:窗口的邊界和屏幕對應(比如:窗口左邊界對應屏幕左邊界)邊界如果距離小于我們制定的邊界檢測寬度則可以隱藏
問題4:記錄平路隱藏時的位置,方便回顯回去
搞清楚上述4個問題后,我們就來貼代碼吧
1、首先是窗口隱藏
1 void FloatingWidget::leaveEvent(QEvent * e)
2 {
3 QPoint mousePos=mapFromGlobal(QCursor::pos());
4 if (rect().contains(mousePos)==false
5 && mousePos.x() !=rect().width())
6 {
7 HideDockWidget();
8 }
9 else
10 {
11 if (m_timer==nullptr)
12 {
13 m_timer=new QTimer(this);
14 connect(m_timer, &QTimer::timeout, this, [this]{
15 QPoint mousePos=mapFromGlobal(QCursor::pos());
16 if (this->rect().contains(mousePos)==false
17 && mousePos.x() !=rect().width())
18 {
19 HideDockWidget();
20 }
21 });
22 }
23 m_timer->start(500);
24 }
25
26 QWidget::leaveEvent(e);
27 }
鼠標移出窗口時,需要隱藏窗口,首先判斷鼠標是否還在窗口內(nèi),包括窗口邊界,如果在窗口內(nèi),則開啟定時器,每隔500毫秒檢測鼠標是否還在屏幕內(nèi),因為leaveEvent事件和enterEvent是成對出現(xiàn)的,當leaveEvent發(fā)生一次后,除非enterEvent觸發(fā),否則不會觸發(fā);如果不在窗口內(nèi),直接去隱藏窗口。
點擊領取Qt學習資料+視頻教程~「鏈接」
2、顯示窗口
顯示窗口就比較好理解了,只需要在鼠標進入窗口時,如果窗口之前隱藏了,則把窗口恢復到之前隱藏的位置
1 void FloatingWidget::enterEvent(QEvent * e)
2 {
3 if (m_timer && m_timer->isActive())
4 {
5 m_timer->stop();
6 }
7
8 ShowDockWidget();
9
10 QWidget::enterEvent(e);
11 }
3、檢測窗口是否需要隱藏
1 void FloatingWidget::HideDockWidget()
2 {
3 if (m_IsVisible==false)
4 {
5 return;
6 }
7
8 m_IsVisible=false;
9
10 int curHeight=height();
11 int curWidth=width();
12
13 QDesktopWidget * desktop=qApp->desktop();
14 QRect rect=desktop->screenGeometry(this);
15
16 if (frameGeometry().left() - CHECK_BORDER <=rect.top()
17 && TEST_BIT(m_feature, LeftArea))
18 {
19 MoveWindow(pos(), pos() - QPoint(curWidth - HIDE_BORDER, 0));
20 }
21 else if (frameGeometry().right() + CHECK_BORDER >=rect.right()
22 && TEST_BIT(m_feature, RightArea))
23 {
24 MoveWindow(pos(), pos() + QPoint(curWidth - HIDE_BORDER, 0));
25 }
26 else if (frameGeometry().top() - CHECK_BORDER <=rect.top()
27 && TEST_BIT(m_feature, TopArea))
28 {
29 MoveWindow(pos(), pos() - QPoint(0, curHeight - HIDE_BORDER));
30 }
31 else
32 {
33 m_IsVisible=true;
34 }
35
36 if (m_IsVisible==false)
37 {
38 if (m_timer && m_timer->isActive())
39 {
40 m_timer->stop();
41 }
42 }
43 }
4、窗口回顯到起始位置
1 void FloatingWidget::ShowDockWidget()
2 {
3 if (m_IsVisible)
4 {
5 return;
6 }
7
8 m_IsVisible=true;
9
10 int curHeight=height();
11 int curWidth=width();
12
13 QDesktopWidget * desktop=qApp->desktop();
14 QRect rect=desktop->screenGeometry(this);
15 QRect frameRect=frameGeometry();
16
17 if (frameRect.left()==m_RecoverPosition.x() - (curWidth - HIDE_BORDER)
18 && TEST_BIT(m_feature, LeftArea))
19 {
20 MoveWindow(pos(), m_RecoverPosition);
21 }
22 else if (frameRect.left()==m_RecoverPosition.x() + (curWidth - HIDE_BORDER)
23 && TEST_BIT(m_feature, RightArea))
24 {
25 MoveWindow(pos(), m_RecoverPosition);
26 }
27 else if (frameRect.top()==m_RecoverPosition.y() - (curHeight - HIDE_BORDER)
28 && TEST_BIT(m_feature, TopArea))
29 {
30 MoveWindow(pos(), m_RecoverPosition);
31 }
32 else
33 {
34 m_IsVisible=false;
35 }
36 }
5、最后是窗口移動算法
1 void FloatingWidget::MoveWindow(const QPoint & start, const QPoint & end, unsigned int step)
2 {
3 QPoint distance=end - start;
4 QPoint stepPos, stepOne;
5 if (end.x()==start.x())
6 {
7 stepOne.setY(step * (distance.y() > 0 ? 1 : -1));
8 }
9 else
10 {
11 stepOne.setX(step * (distance.x() > 0 ? 1 : -1));
12 }
13 stepPos=stepOne;
14
15 int disLenght=distance.manhattanLength();
16 while (stepPos.manhattanLength() <=disLenght)
17 {
18 move(start + stepPos);
19 stepPos +=stepOne;
20 }
21
22 move(end);
23
24 m_RecoverPosition=start;
25 }
參數(shù)分別是:起始位置、終點位置和每次移動距離
轉(zhuǎn)載:https://www.cnblogs.com/swarmbees/p/5926144.html
作者:朝十晚八 or Twowords
.結(jié)構(gòu)標記:作用就是為了提升標記的語義性,每個結(jié)構(gòu)有每個不同的標記。
1.頭部標記:<header></header>,用于定義頁面的頁眉,最上面的內(nèi)容。等同于<div id="header"></div>,作用一樣。就是相當于一個容器,裝其他的元素。
2.導航標記:<nav></nav>,用于定義頁面的導航鏈接部分。等同于<div id="nav"></div>
例如可以這樣寫導航:
<nav>
<ul>
<li></li>
</ul>
</nav>
3.主體標記:<section></section>作用:定義頁面主體內(nèi)容中的小節(jié),現(xiàn)在section可以表示整個頁面的主體內(nèi)容等同于<div id="main"></div>
4.<article></article>作用:用于描述文本性較強,或者藝術氣息較強的內(nèi)容。一般情況下,論壇中的帖子信息,報紙信息,博客或微博中的條目信息。用戶回復信息,有限考慮放在article中
5.<footer></footer>定義頁面中或某個區(qū)域中的腳注信息,頁面最底部的信息。
6.邊欄:<aside></aside>定義頁面?zhèn)冗厵冢窟叺男畔?/p>
以上結(jié)構(gòu)標記為的就是獨立定義結(jié)構(gòu),替代div。
表單
表單的作用:顯示,收集信息,并且將信息提交給服務器
(在注冊,登陸的時候,網(wǎng)頁就會提供一些供用戶填寫的表單,表單元素會把填寫的信息提交服務器進行處理 )
表單包含兩組內(nèi)容
1.表單元素<form>
<form></form>
注意:使用表單控件提交數(shù)據(jù)時,表單不能省略
屬性:
1.action:后臺處理程序的地址(服務器端工程師提供),默認會提交給本頁。
2.method:方式,表單的提交方式。不同的提交方式約束的內(nèi)容不一樣。
常用取值:2個
get:
1.顯示提交數(shù)據(jù),會將提交信息顯示在地址欄上面,安全性不高,又叫顯示提交
2.大小限制,最大支持到2kb的提交。
3.如果不設置method屬性,默認就是get方式提交(顯示提交,最大2kb)
4.使用場合:向服務器索取數(shù)據(jù)時,優(yōu)先使用get
post:
1.隱式提交數(shù)據(jù),不會將提交的信息顯示在地址欄上,安全性較高,所有有關密碼的信息提交時,必須用post
2.post沒有大小限制。
3.使用場合:安全性要求較高的頁面,傳遞數(shù)據(jù)量較大的時候
3.enctype
作用:設置對表單中提交的數(shù)據(jù)的編碼方式,規(guī)范哪些數(shù)據(jù)可以提交給服務器
取值:
1.application/x-www-form-urlencoded,默認值,可以將普通的文本,特殊的字符,一起提交給服務器。
2.multipart/form-date,允許將表單中的文件,傳遞給服務器,普通文本不能直接傳遞。
3.text/plain,只能將普通文本傳遞給服務器,特殊字符不允許。
4.id
5.name
2.表單控件
什么是表單控件
包含在表單中的元素,具備可視化外觀,并且可以接受用戶輸入的數(shù)據(jù)。
分類
1.input元素
2.textare文本域
3.select和option選項框
一.input元素,主要作用就是收集用戶信息
語法:<input>
屬性:
type,根據(jù)不同的類型值可以創(chuàng)建不同的輸入控件,用戶名,密碼,按鈕形式的
value,控件的值,提交給服務器的數(shù)據(jù)。
name,控件的名稱。必須設置,否則無法提交,服務器主要根據(jù)name這個控件的名稱,來獲取value
disabled,禁用控件,該屬性可以沒有值。
1.文本框和密碼框
文本框:<input type="text">
允許用戶輸入任意字符的數(shù)據(jù),明文顯示
密碼框:<input type="password">
允許用戶輸入任意字符的數(shù)據(jù),密文顯示
屬性:
maxlength:限制輸入的字符數(shù)
readonly:只讀,無需給值
value:控件值,同時也可以設置控件
注意:input元素下,如果不寫type值,或者type值寫錯時,都默認為文本框。
單選框和復選框
1.單選框:<input type="radio">
屬性:
1.name:定義名稱并且實現(xiàn)控件分組,一組內(nèi)的元素才能實現(xiàn)單選
2.value:控件值
3.checked:設置默認被選中,不需要值
2.復選框
<input type="checkbox">
屬性:name:定義名稱并且分組,便于服務器獲取
3.按鈕
1.提交按鈕,功能固定化,負責將數(shù)據(jù)提交給服務器
<input type="submit">
2.重置按鈕,功能固定化,負責將表單控件恢復到初始化的狀態(tài)
<input type="reset">
3.普通按鈕,沒有固定功能,由開發(fā)者通過js來設置。
<input type="button">
value:顯示在按鈕上的文本
name:名稱(可寫可不寫)
4.非input標簽的按鈕
<button></button>
<button type="button">普通按鈕</button>
屬性:type
5.隱藏域和文件選擇框
1。隱藏域,不想讓用戶看見,但是又要提交到服務器的數(shù)據(jù),可以放在隱藏域中
例如:隱藏用戶id
type="hidden"
<input tpe="hidden">
屬性:
name
value
6.文件選擇框
提供一個基礎控件,允許用戶選擇本機的文件上傳到服務器
type="file"
<input type="file">
屬性:name value
注意:
表單的method(提交方式)屬性值必須為post
表單的enctype編碼必須為multipart/form-date
更多知識關注小編,或者百度網(wǎng)絡營銷師鐘震,鐘震講網(wǎng)絡營銷。會有很多相關知識,公眾號網(wǎng)絡營銷師鐘震,以后每天都會分享web前端,淘寶運營,競價,網(wǎng)站建設和優(yōu)化,社媒方面的知識。與大家共同進步。希望對您有一點點幫助,喜歡記得關注公眾號。
控制一個元素的顯示方式,我們可以使用display:block;display:inline-block;display:none;其中布局相關的還有兩個很重要的屬性:display:flex;和display:grid;flex表示彈性盒子,grid表示網(wǎng)格;
我們使用一個三例的布局為例來試一下:
display:flex;
<html>
<head>
<title>css</title>
</head>
<body>
<div style="height: 900px;">
<div style="width: 100%;height:100px;background:grey">我是頭部</div>
<div style="display: flex;height: 100%;">
<div style="width: 100px;height: 100%;background:yellow;">左側(cè)</div>
<div style="width:100%;background:burlywood">中間中間中間中間中間中間中間中間中間中間中間中間中間中間中間中間中間中間中間中間中間中間中間中間中間</div>
<div style="width: 100px;height: 100%;background:yellow;">右側(cè)</div>
</div>
</div>
</body>
</html>
<html>
<head>
<title>css</title>
</head>
<body>
<div class="container">
<div class="item">flex1</div>
<div class="item">flex2</div>
<div class="item">flex3</div>
<div class="item">flex4</div>
<div class="item">flex5</div>
<div class="item">flex6</div>
<div class="item">flex7</div>
<div class="item">flex8</div>
</div>
</body>
<style>
.container{
display: flex;
width:600px;
height: 900px;
background:grey;
flex-direction: row; /** 設置排列的方式 row 橫向 row-reverse 橫向反轉(zhuǎn) column 縱向 column-reverse*/
justify-content: flex-start; /** 設置每一個列的對齊方向 flex-start靠左排開,flex-end靠右排列,center居中排列,space-between左右靠邊平均對齊,space-around */
flex-wrap: wrap;/***是否換行 wrap換行,nowrap不換行,wrap-reverse倒序換行*/
align-content: flex-start; /**用于設置各行之間如何對齊*/
align-items:flex-start; /**設置縱向的排列方式*/
}
.item{
width: 100px;
height: 100px;
margin: 10px;
background:yellow;
}
</style>
</html>
注:以下的屬性設置大家可以去嘗試一下。
flex-direction: row; /** 設置排列的方式 row 橫向 row-reverse 橫向反轉(zhuǎn) column 縱向 column-reverse*/
justify-content: flex-start; /** 設置每一個列的對齊方向 flex-start靠左排開,flex-end靠右排列,center居中排列,space-between左右靠邊平均對齊,space-around */
flex-wrap: wrap;/***是否換行 wrap換行,nowrap不換行,wrap-reverse倒序換行*/
align-content: flex-start; /**用于設置各行之間如何對齊*/
align-items:flex-start; /**設置縱向的排列方式*/
display:grid:
<html>
<head>
<title>css</title>
</head>
<body>
<div style="height: 900px;">
<div style="width: 100%;height:100px;background:grey">我是頭部</div>
<div style="display: grid;height: 100%;grid-template-columns: 100px auto 100px;">
<div style="background:yellow">左側(cè)</div>
<div style="background:burlywood">中間中間中間中間中間中間中間中間中間中間中間中間中間中間中間中間中間中間中間中間中間中間中間中間中間</div>
<div style="background:yellow">右側(cè)</div>
</div>
</div>
</body>
</html>
以上我們只是用一個三例布局講了一下基本的內(nèi)容,這里布局還有很多屬性,大家可以去試一下。一定得看,哪怕你不去手寫,也要看一下那些屬性的作用,因為這塊太重要了,但是屬性又太多了,要寫起來可勁得寫了,大家看不明白的,可以給我留言,我會看到給大家回復的!
浮動屬性float會使元素脫離文檔流,使其他內(nèi)容重新排列,我們常見的文字環(huán)繞效果可以使用浮動來實現(xiàn):
<html>
<head>
<title>css</title>
</head>
<body>
<div>
<div style="width: 100px;height:100px;padding:50px;border:1px solid black;float:left;left:0px;top:0px;">浮動</div>
<div>顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容
顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容
顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容
顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容顯示內(nèi)容內(nèi)容
</div>
</div>
</body>
</html>
我們縮小一下窗口就能看到效果。
注:布局屬性很重要,大家一定要去看,去寫!
*請認真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。