成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

QT 上下文菜單內存泄露之QMainWindow

移動開發
本文介紹的是QT 上下文菜單內存泄露之QMainWindow,根據不同版本進行測試,并解決問題。先來看內容。

QT 上下文菜單內存泄露之QMainWindow 是本人要介紹的內容,先來看內容。創建Qt工程,基于QMainwindow,什么也不做,程序會自帶一個上下文菜單。

不斷點擊鼠標右鍵,菜單將反復出現,此時我用任務管理器查看其內存變化,發現每次不斷增加,請問大家這是Qt內存泄漏嗎???我用MFC,CB均沒有發現類此錯誤。

Qt 4.7.0 和 4.7.3下可以重現該問題,在Qt 4.6.3下不存在該問題。可以確定是Qt的一個bug。

問題重現

在工具欄或停靠窗口中點擊右鍵(彈出上下文菜單),多點擊幾次,然后點擊按鈕。觀察控制臺輸出,可以看到很多個 QMenu 對象。

  1. #include <QtGui> 
  2. class MainWindow : public QMainWindow  
  3. {  
  4.     Q_OBJECT  
  5. public:  
  6.     explicit MainWindow(QWidget *parent = 0);  
  7. private slots:  
  8.     void onButtonClicked();  
  9. };  
  10. MainWindow::MainWindow(QWidget *parent)  
  11. {  
  12.     addToolBar("ToolBar");  
  13.     addDockWidget(Qt::LeftDockWidgetArea, new QDockWidget("DockWidget"));  
  14.     QPushButton * btn = new QPushButton("dump object tree");  
  15.     setCentralWidget(btn);  
  16.     connect(btn, SIGNAL(clicked()), SLOT(onButtonClicked()));  
  17. }  
  18. void MainWindow::onButtonClicked()  
  19. {  
  20.     dumpObjectTree();  
  21. }  
  22. #include "main.moc"  
  23. int main(int argc, char *argv[])  
  24. {  
  25.     QApplication a(argc, argv);  
  26.     MainWindow w;  
  27.     w.show();  
  28.  
  29.     return a.exec();  

原因

既然是QMainWindow的上下文菜單問題,直接看 contextMenuEvent 事件處理函數吧。

  1. void QMainWindow::contextMenuEvent(QContextMenuEvent *event)  
  2. {  
  3.     event->ignore();  
  4. ...  
  5.     QMenu *popup = createPopupMenu();  
  6.     if (popup) {  
  7.         if (!popup->isEmpty()) {  
  8.             popup->setAttribute(Qt::WA_DeleteOnClose);  
  9.             popup->popup(event->globalPos());  
  10.             event->accept();  
  11.         } else {  
  12.             delete popup;  
  13.         }  
  14.     }  

看仔細嘍,這兒設置了 Qt::WA_DeleteOnClose 屬性。

有什么用?設置該屬性后,當我們調用該對象的 close() 成員時,隱藏(hide)窗口同時會刪除(delete)該對象

有什么問題?問題出在,實際上隱藏菜單時沒有 調用菜單的close(),而是 調用的hide()的成員。

調用hide()而不是close(),是的該屬性不能發揮任何作用,進而導致內存泄露(Qt 之 show,hide,setVisible,setHidden,close 等小結 )。

為了對比,我們看看Qt4.6.3的源碼部分:

  1. void QMainWindow::contextMenuEvent(QContextMenuEvent *event)  
  2. {  
  3.     event->ignore();  
  4. ...  
  5.     QMenu *popup = createPopupMenu();  
  6.     if (popup && !popup->isEmpty()) {  
  7.         popup->exec(event->globalPos());  
  8.         event->accept();  
  9.     }  
  10.     delete popup;  

而這個,也就是我們的比較理想的答案了。

進一步學習

前面說了,菜單隱藏時調用的是hide() 成員,而不是close() 成員。有神馬依據??

想想?如何讓菜單隱藏

鼠標:點擊菜單外區域

鍵盤:按下Esc鍵等

這樣就比較明朗了,對吧,直接看這兩個事件處理函數

鍵盤的按鍵事件(調用了hideMenu)

  1. void QMenu::keyPressEvent(QKeyEvent *e)  
  2. {  
  3.     Q_D(QMenu);  
  4.     d->updateActionRects();  
  5.     int key = e->key();  
  6. ...  
  7.     bool key_consumed = false;  
  8.     switch(key) {  
  9.     case Qt::Key_Escape:  
  10.         key_consumed = true;  
  11.         {  
  12.             QPointer<QWidget> caused = d->causedPopup.widget;  
  13.             d->hideMenu(this); // hide after getting causedPopup  
  14.             if (QMenuBar *mb = qobject_cast<QMenuBar*>(caused)) {  
  15.                 mb->d_func()->setCurrentAction(d->menuAction);  
  16.                 mb->d_func()->setKeyboardMode(true);  
  17.             }  
  18.         }  
  19.         break;鼠標在菜單區域外按鍵,調用了hideUpToMenuBar(進而調用hideMenu)   
  20. void QMenu::mousePressEvent(QMouseEvent *e)  
  21. {  
  22.     Q_D(QMenu);  
  23. ...  
  24.     if (!rect().contains(e->pos())) {  
  25.          if (d->noReplayFor  
  26.              && QRect(d->noReplayFor->mapToGlobal(QPoint()), d->noReplayFor->size()).contains(e->globalPos()))  
  27.              setAttribute(Qt::WA_NoMouseReplay);  
  28.          if (d->eventLoop) // synchronous operation  
  29.              d->syncAction = 0;  
  30.         d->hideUpToMenuBar();  
  31.         return;  
  32.     }  

前面都調用了hideMenu,從名字也能猜猜它想干什么:

  1. void QMenuPrivate::hideMenu(QMenu *menu, bool justRegister)  
  2. {  
  3. ...  
  4.         menu->hide();  

小結:QT 上下文菜單內存泄露QMainWindow 的內容介紹完了,希望本文對你有所幫助!

責任編輯:zhaolei 來源: 互聯網
相關推薦

2012-08-01 09:58:12

Mountain Li操作系統

2017-05-11 14:00:02

Flask請求上下文應用上下文

2022-09-14 13:13:51

JavaScript上下文

2018-06-17 08:38:17

微軟Windows應用程序

2012-12-31 10:01:34

SELinuxSELinux安全

2022-09-15 08:01:14

繼承基礎設施基礎服務

2021-07-26 07:47:36

Cpu上下文進程

2025-06-06 08:00:00

上下文管理器Python開發

2020-07-24 10:00:00

JavaScript執行上下文前端

2023-07-11 10:02:23

2017-12-17 17:01:23

限界上下文系統模型

2022-10-28 16:24:33

Context上下文鴻蒙

2024-09-30 14:10:00

2025-03-18 08:14:05

2021-05-09 21:50:48

項目實踐上下文

2022-10-31 15:34:30

python裝飾器內存泄漏

2021-07-20 19:30:05

微軟Windows 11Windows

2023-12-10 13:37:23

Python編程上下文管理

2024-03-14 08:11:45

模型RoPELlama

2023-06-15 15:45:42

自然語言語言模型
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产精品国产a级 | 亚洲精品二区 | 伊人焦久影院 | 黄色国产区 | 欧美区日韩区 | 亚洲国产高清免费 | 91av免费版 | 美女激情av | 国产精品久久一区 | 精品美女视频在线观看免费软件 | 欧美日韩网站 | 超碰人人插 | 中文字幕一区二区三区四区 | 99影视| 久久久69 | 理论片午午伦夜理片影院 | 国产高清一区二区三区 | 欧美精品在线一区二区三区 | 日韩国产在线观看 | 亚洲综合国产 | 韩日一区 | 国产成人亚洲精品 | 亚洲精品免费视频 | 羞羞网站免费 | av在线伊人 | 一级黄色片网站 | 亚洲精品在线免费观看视频 | 国产精品中文字幕一区二区三区 | 日本三级在线网站 | 日韩中文字幕视频 | 亚洲天堂av网 | 一区二区三区四区在线视频 | 国产福利视频 | 国产精品久久久久久中文字 | 久久久蜜桃一区二区人 | 欧美精品在欧美一区二区 | 91精品国产色综合久久不卡98 | 国内精品在线视频 | 视频一区二区国产 | 日本又色又爽又黄又高潮 | 自拍偷拍在线视频 |