亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Qt中如何實現自選股列表拖拽、右鍵常用菜單功能

發布時間:2021-08-07 09:21:53 來源:億速云 閱讀:155 作者:小新 欄目:編程語言

小編給大家分享一下Qt中如何實現自選股列表拖拽、右鍵常用菜單功能,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

效果展示

如下效果圖所示,是自選股使用上的一個展示效果,具有如下功能

1.搜索編輯框,支持股票代碼和股票名稱搜索
2.搜索預覽框支持鼠標hover,并且可以使用鍵盤上下鍵進行當前項切換,單機時支持切換自選股
3.自選股列表,支持拖拽,拖拽時會有拖拽項映像,并示意將要拖拽到哪個位置
4.支持右鍵菜單,可以對某一項進行移動,刪除等操作

Qt中如何實現自選股列表拖拽、右鍵常用菜單功能

如果覺著demo比較丑的話,可以看財聯社-產品展示這篇文章中的效果圖

自選股列表

接下來就是我們這篇文章的重頭戲了,也是比較復雜的一個內容。

自選股列表我選擇的是使用QListWidget來實現,然后每一個item上在放一個Widget即可,Widget就是我們定制窗體內容,這里我們主要講解幾個比較重要的核心內容

1、列表初始化

初始化StockList,實際上自選股列表應該從服務器拉取,我們這里作為demo測試,因此就自己模擬了5條數據進行插入。

//已選個股列表
d_ptr->m_pStockList = new StockList;
connect(d_ptr->m_pStockList, &StockList::RowClicked, this, [this](const QString & symbol){
 emit RowClicked(symbol);
});

//測試數據 正常情況下 應該是列表自己拉取
OptionalMarketItem item;
for (int i = 1; i <= 5; ++i)
{
 item.wstrSymbol = QString("0h000%1").arg(i).toStdWString();
 item.wstrName = QString("%1%1%1").arg(i).toStdWString();
 item.wstrIndustryName = QString("pingyin%1").arg(i).toStdWString();

 d_ptr->m_pStockList->AddItem(item);
}

2、添加Item

往StockList中添加item項時,我們首先需要構造一個標準的QListWidgetItem結構,然后把我們自己定制的ListItem放到這個標準item結構上。

QListWidgetItem * StockList::AddItem(const OptionalMarketItem & data)
{
 ListItem * itemWidget = new ListItem;
 itemWidget->SetData(data);
 QListWidgetItem * item = new QListWidgetItem;
 addItem(item);
 item->setSizeHint(QSize(0, 50));
 setItemWidget(item, itemWidget);
 return item;
}

ListItem就是一個普通的QWidget,上邊排列了一些QLabel,用于顯示我們的股票數據。

ListItem界面構造就不過多解釋了,唯一需要說明的就是,我們股票數據發送變化時,界面上會有紅綠色框的動畫提示,這里需要調用兩行代碼來實現重新獲取控件qss代碼,并刷洗界面。

this->style()->unpolish(this);
this->style()->polish(this);

3、右鍵菜單

本篇文章和上一篇文章的右鍵菜單實現方式一樣,都是參考我很早以前寫的Qt之自定義QLineEdit右鍵菜單這篇文章,實現默認的contextMenuEvent函數即可。

右鍵菜單已經說的很多了,這里就一筆帶過了,需要的同學可以自己快速的瞅一眼,應該比較容易理解。

void StockList::contextMenuEvent(QContextMenuEvent * event)
{
 if (d_ptr->m_AllowMenu == false)
 {
 return;
 }
 if (d_ptr->m_ContextMenu == nullptr)
 {
 d_ptr->m_ContextMenu = new QMenu(this);
 d_ptr->m_ContextMenu->setObjectName(QStringLiteral("StockListMenu"));
 d_ptr->m_ContextMenu->setFixedWidth(100);
 QAction * delAct = new QAction(QStringLiteral("刪除自選股"), d_ptr->m_ContextMenu);
 QAction * topAct = new QAction(QStringLiteral("置頂"), d_ptr->m_ContextMenu);
 QAction * bottomAct = new QAction(QStringLiteral("置底"), d_ptr->m_ContextMenu);
 QAction * upAct = new QAction(QStringLiteral("上移一位"), d_ptr->m_ContextMenu);
 QAction * downAct = new QAction(QStringLiteral("下移一位"), d_ptr->m_ContextMenu);
 connect(delAct, &QAction::triggered, this, &StockList::DeleteSotck);
 connect(topAct, &QAction::triggered, this, &StockList::TopSotck);
 connect(bottomAct, &QAction::triggered, this, &StockList::BottomSotck);
 connect(upAct, &QAction::triggered, this, &StockList::UpSotck);
 connect(downAct, &QAction::triggered, this, &StockList::DownSotck);
 d_ptr->m_ContextMenu->addAction(delAct);
 d_ptr->m_ContextMenu->addAction(topAct);
 d_ptr->m_ContextMenu->addAction(bottomAct);
 d_ptr->m_ContextMenu->addAction(upAct);
 d_ptr->m_ContextMenu->addAction(downAct);
 }
 d_ptr->m_ContextMenu->exec(mapToGlobal(event->pos()));
 QListWidget::contextMenuEvent(event);
}

以上5個菜單,雖然看起來功能相差很多,但是其實處理邏輯基本都是一樣的,先是一個內容結構排序,然后進行刷新數據到界面上。

為了節省篇幅,我這里就只介紹置頂一只股票的操作

置頂的邏輯看起來是這樣的

1.移除當前項
2.并且把當前項item插入到新位置
3.構造一個新的Widget,設置給item
4.把新位置的item設置為當前選中項
5.上傳最新列表到數據中心,或者服務器

void StockList::TopSotck()
{
 QListWidgetItem * item = currentItem();
 if (item == nullptr)
 {
  return;
 }
 if (row(item) == 0)
 {
  return;
 }
 ListItem * itemWidget = ItemWidget(item);
 QListWidgetItem * newItem = takeItem(row(item));
 insertItem(0, newItem);
 ListItem * topWidget = new ListItem;
 topWidget->SetData(itemWidget->GetData());
 setItemWidget(newItem, topWidget);
 if (itemWidget)
 {
  itemWidget->close();
  itemWidget = nullptr;
 }
 setCurrentItem(newItem);
 StorageData();
}

4、拖拽Item

拖拽Item應該算是一個比較難一點兒功能,好在Qt已經為我們實現了一套QDrag事件的回調方法,也比較好使,如下圖所示,重寫如下4個方法,基本的拖拽事件就能完成了。

但是這里我么有選擇默認的這個回調函數來實現這個功能,其中最大的原因就是,他們的可定制性太局限了。

我這里采取的是自己模擬鼠標拖拽功能,同過重寫如下幾個函數來達到我的目的

virtual void mousePressEvent(QMouseEvent * event) override;
virtual void mouseMoveEvent(QMouseEvent * event) override;
virtual void mouseReleaseEvent(QMouseEvent * event) override;
virtual void enterEvent(QEvent * event) override;
virtual void leaveEvent(QEvent * event) override;

1.鼠標按下時,主要是記錄了一些內容狀態,方便在鼠標移動時去做判斷,并決定是否啟用鼠標拖拽功能
2.鼠標移動就比較復雜了,進行了各種對比,還需要移動被拖拽項的映像位置,移動那一根水平線的位置
3.鼠標釋放時,調整整個列表的內容
4.鼠標進入窗體時,顯示水平標識線
5.鼠標離開窗體時,隱藏水平標識線

上邊只是粗略的描述了這幾個函數的功能, 因為函數實現體都比較長,因此這里我也是選擇幾個關鍵點來做以說明。

a、move函數

產生拖拽時,移動鼠標,我們需要處理很多事件,比如

1、初始化水平表示線和拖拽項映像

if (d_ptr->m_ShotLine == nullptr)
{
 InitShotLine();
}
if (d_ptr->m_ShotPicture == nullptr)
{
 InitShotLabel();
}

2、拖拽時修改鼠標狀態

根據拖拽啟動后,鼠標是否還在當前拖拽項上,設置鼠標的狀態。

if (ListItem * newWidget = ItemWidget(d_ptr->dragItem))
{
 d_ptr->m_ShotPicture->move(QCursor::pos() - d_ptr->dragItemPos);
 d_ptr->m_DragRect = visualItemRect(d_ptr->dragItem);
 if (d_ptr->m_DragRect.contains(event->pos()) || event->pos().isNull())
 {
  if ((event->pos() - d_ptr->startPos).manhattanLength() > 5)
  {
   setCursor(Qt::ForbiddenCursor);
  }
 }
 else
 {
  setCursor(Qt::ArrowCursor);
 }
 if (d_ptr->m_ShotPicture->isHidden())
 {
  d_ptr->m_ShotPicture->show();
 }
}

b、release函數

鼠標釋放時,把拖拽項移動到新的位置

if (ListItem * oldWidget = ItemWidget(d_ptr->dragItem))
{
 QListWidgetItem * newItem = new QListWidgetItem;
 ListItem * itemWidget = new ListItem;
 itemWidget->SetData(oldWidget->GetData());

 insertItem(insertPos, newItem);
 newItem->setSizeHint(QSize(0, 50));
 setItemWidget(newItem, itemWidget);

 setCurrentItem(newItem);

 oldWidget->deleteLater();
}

5、刷新數據

全量刷新數據。在原來的列表上刷新數據

當原始列表行數不夠時,構造新的行

當原始列表函數多時,移除末尾多的行

void StockList::Update_p(OptionalMarketItemVector data)
{
 d_ptr->m_bOnceLoad = true;
 disconnect(this, &QListWidget::currentItemChanged, this, &StockList::CurrentItemChanged);
 int i = 0;
 for (auto iter = data.begin(); iter != data.end(); ++iter, ++i)
 {
  bool success = false;
  if (QListWidgetItem * item = this->item(i))
  {
   if (ListItem * itemWidget = ItemWidget(item))
   {
    itemWidget->SetData(*iter);
    success = true;
   }
  }
  if (!success)
  {
   AddItem(*iter);
  }
 }
 if (i < this->count())
 {
  QListWidgetItem * item = nullptr;
  while (item = this->item(i))
  {
   if (ListItem * itemWidget = ItemWidget(item))
   {
    itemWidget->close();
    itemWidget = nullptr;
   }
   item = takeItem(i);
   delete item;
  }
 }
 if (d_ptr->m_LeftPress == false)
 {
  RecoveryCurrentItem();
 }
 connect(this, &QListWidget::currentItemChanged, this, &StockList::CurrentItemChanged);
}

以上是“Qt中如何實現自選股列表拖拽、右鍵常用菜單功能”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

qt
AI

河曲县| 桃园市| 兰溪市| 浦北县| 溆浦县| 乌拉特后旗| 东至县| 景宁| 衡东县| 乌海市| 简阳市| 漳浦县| 克拉玛依市| 麻江县| 都昌县| 竹溪县| 广元市| 磴口县| 香河县| 普陀区| 宝丰县| 高密市| 合阳县| 蓬安县| 东兴市| 丹阳市| 梅河口市| 平舆县| 城口县| 桂东县| 井陉县| 新津县| 长丰县| 工布江达县| 若尔盖县| 洛宁县| 治多县| 南平市| 保山市| 肃南| 永新县|