網站首頁 編程語言 正文
首先,我們來看以下實現的最終效果吧!
我覺得這并不是一個很難得問題,最近新招了一個應屆生,發現在實現上述效果時,被困擾住了,是不是剛剛接觸Qt的這種稍微有難度的界面時,都會有些無頭緒呢?
所以,我打算分享給大家實現的思路,以及會出現的問題,就我一個開發5年C++的員工而言,針對新手會遇到哪些不懂的問題。
當前的開發環境:win10 VS2017 + Qt5.14.2 x64
在實現過程中新手會出現的難點,如下
1:如何在QListWidget中添加帶有按鈕、文本等其它控件的一條數據?
2:選中每一條之后如何響應?QListWidget自帶的item響應為什么不生效?
3:如何選中刪除按鈕并通知QListWidget做出具體的響應?
就根據上述三個問題,邊講述問題邊實現帶有自定義控件的Item內容吧!
在使用QListWidget插入一條數據時,默認的方式,如下:
ui.listWidget->insertItem(0, "Text Content"); //方法1
ui.listWidget->addItem("Text Content"); //方法2
使用上述代碼是無法實現的,因為參數中只能添加QString類型的字符串,那么該如何實現添加自定義項呢?
在QListWidget類中提供了叫做QListWidgetItem的子類,用于實現自定義的item。
這時,我們就需要重新定義一個類,并且將該類與ListWidgetItem進行綁定,就可以實現每一行的item上展示屬于我們自定義的格式了。
例子中展示的item中顯示了一個選擇框、文件名稱以及刪除按鈕。
在這里,采用了QCheckBox以及QPushButton兩個按鈕實現的。
有人會詢問:文件名稱不應該使用QLabel控件表示嗎?
回答是:當前可以使用QLabel控件顯示文件名稱,這里采用QCheck主要是想要展示文件的圖標,根據不同的文件名后綴顯示不同的圖標。
自定義Widget
該類繼承自QWidget。假設叫做:CustomItem
有些新手會直接創建一個純的C++類,這樣做肯定是有問題的,當我們在外部使用當前自定義類時,你會發現,為什么新創建的類會單獨分出來呢?
如果直接使用純C++類,還有另一個至關重要的問題,當前類需要進行消息交互時,你該如何傳遞給外部調用者呢?回調嗎?是不是有點大材小用呢?
class CustomItem : public QWidget
{
Q_OBJECT
public:
CustomItem(QWidget *parent);
~CustomItem();
private:
QCheckBox* m_checkName; //文件名
QCheckBox* m_checkSelect; //選擇
QPushButton* m_btnDelete; //刪除
};
自定義類CustomItem中創建了三個控件變量,分別表示了:選擇框、文件名稱以及刪除按鈕。
就是文章開始顯示效果圖的三個控件了。
接下來,需要定義一個外部調用接口,插入一條有效數據,假設接口名稱是:AddINewtemData
class CustomItem : public QWidget
{
Q_OBJECT
public:
CustomItem(QWidget *parent);
~CustomItem();
public: //對外開放接口
void AddINewtemData(int nRow, QString qsFileName); //添加一條新數據
private:
int m_nRow;
QCheckBox* m_checkName; //附件名
QCheckBox* m_checkSelect; //選擇
QPushButton* m_btnDelete; //刪除
};
AddINewtemData 參數
參數1:代表的是當前自定義widget屬于QListWidget的行編號,用于后續消息傳遞使用。
參數2:需要展示的文件名稱
根據用戶傳入的文件名稱,根據文件后綴展示不同的圖標。
void CustomItem::AddINewtemData(int nRow, QString qPath)
{
m_nRow = nRow; //記錄當前自定義widget對應的QListWidget的行號
//根據路徑名,獲取文件名稱,并設置
QFileInfo info(qPath);
QString qsFileName = info.fileName();
m_checkName->setText(qsFileName);
//獲取文件后綴
QString qsCheckStyle = "";
if (info.suffix() == "mp4") //視頻文件
{
//自定義QCheckBox風格
}
else if (info.suffix() == "png") //圖片文件
{
//自定義QCheckBox風格
}
else if (info.suffix() == "xlsx") //表格文件
{
//自定義QCheckBox風格
}
else if (info.suffix() == "pdf")
{
//自定義QCheckBox風格
}
else //文檔文件
{
//自定義QCheckBox風格
}
m_checkName->setStyleSheet(qsCheckStyle);
}
構造完自定義widget類之后,接下來就需要將該類與QListWidgetItem進行綁定,顯示到QListWidget上去。
外部調用方法,如下:
int nCount = ui.listWidget->count();
CustomItem* widget = new CustomItem(this);
widget->AddINewtemData(nCount, qsFileName);
widget->show();
QListWidgetItem* item = new QListWidgetItem;
item->setSizeHint(QSize(48, 48));
ui.listWidget->addItem(item);
ui.listWidget->setItemWidget(item, widget);
自定義CustomItem響應
上述功能可以實現QListWidget中展示自定義的widget之后,該如何點擊QListWidget中的每一條做出不同的響應呢?
此時,我們對每一行的QListWigetItem綁定自定義類之后,是無法響應QListWidget自身的選擇消息的!這一點需要大家記清楚了。
那么,該怎么觸發呢?
針對于每一個QWidget類,只要是繼承自QWidget,都會有鼠標的四大響應:
virtual void mousePressEvent(QMouseEvent *event);
virtual void mouseReleaseEvent(QMouseEvent *event);
virtual void mouseDoubleClickEvent(QMouseEvent *event);
virtual void mouseMoveEvent(QMouseEvent *event);
當鼠標在自定義類做了點擊效果后,肯定可以在鼠標按下事件中獲取點擊響應的。
所以,在自定義類CustomItem中需要重寫QWidget的系統消息:mousePressEvent
void CustomItem::mousePressEvent(QMouseEvent *event)
{
QWidget::mousePressEvent(event);
}
斷點設在該響應函數中時,肯定是會觸發的,如果不可以肯定是當前widget處于禁用狀態,或者是被遮蓋住了。
這里還有一個隱藏問題:有些同學在點擊自定義窗口時會發現這樣一個奇怪的現象,為什么點擊有些區域是響應mousePressEvent消息的,而點擊有些區域是不響應呢?
以下是重中之重了?。?/p>
這就是前一段話提到的內容了,當前widget不觸發時,肯定是禁用或者是被遮擋住了。
在我們這個自定義Widget中有三個活躍的控件,兩個QCheck,一個QPushButton,當我們的鼠標在任意控件上點擊時,此時的點擊響應應該是響應到子控件上,而不是自定義的Widget(CustomItem)上。
為了讓鼠標點擊任何控件時,所有的響應都響應到父類Widget,也就是CustomItem上時,我們應該對支持鼠標響應操作的控件做特殊處理
setAttribute(Qt::WA_TransparentForMouseEvents)
每個控件都要設置以上的操作,當前控件只是用來顯示,不做任何消息處理,是當前窗口做的消息處理
自定義Widget控件響應并通知外界處理
下面,來說一說第三個重點問題,如何通知外界處理。
我們使用了自定義的Widget之后就不能再使用QListWidget的內部選中消息了,為了讓外部窗口獲取內部Widget的消息時,此時我們需要采用發信號的方式,通知外界,模擬QListWidget消息。
signals:
void Msg_SendDeleteItemData
外部窗口直接操作該消息,使用方法跟普通的方法一致,這里就不再過多介紹Qt中消息機制了。
以上實現QListWidget內嵌自定義窗口的核心功能就說清楚了。
原文鏈接:https://juejin.cn/post/7085512433120313374
相關推薦
- 2022-11-18 詳解Pandas如何高效對比處理DataFrame的兩列數據_python
- 2023-01-28 C#實現XML文件操作詳解_C#教程
- 2022-06-10 SQL?Server使用導出向導功能_MsSql
- 2022-02-28 ./node_modules/taro-ui/dist/weapp/index.ts Module
- 2022-06-02 JQuery實現動態漂浮廣告_jquery
- 2023-07-25 使用線程池異步執行定時任務
- 2022-12-25 利用pycharm調試ssh遠程程序并實時同步文件的操作方法_python
- 2023-10-15 element-ui里el-progress:進度條問題的解決Invalid prop: custo
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支