為了實現 QLineEdit 獲取焦點/獲取焦點后全選字符的功能,在網上先查了 QLineEdit 獲取焦點的方法,有兩種:
1 此方法只有在窗體從失去焦點到獲取焦點時有作用:即窗體失去焦點后再次獲取焦點時,將焦點置於某個 QLineEdit 中。
此功能明顯不是偶想要的!!! 但由於網上現有的文章都是一樣的,說的不是很清楚,所以只有試了才知道。
有三段代碼:
1) 在窗體初始化時增加如下代碼:
1 // QLineEdit 獲取焦點 1 - 此方法錯誤: 只有在窗體從失去焦點到獲取焦點時有作用 2 ui->ledSendStr->installEventFilter(this); 3 ui->ledSendFile->installEventFilter(this); 4 ui->ledSendPreTime->installEventFilter(this);
2) 在窗體的 .h 文件中聲明 SLOT,如下:
1 public slots: 2 bool eventFilter(QObject *,QEvent *); // QLineEdit 獲取焦點 2
3) 實現的代碼
1 // QLineEdit 獲取焦點 3 2 bool MainWindow::eventFilter(QObject *watched, QEvent *event) 3 { 4 if(watched == ledSendStr) 5 { 6 if(QEvent::FocusIn == event->type()) 7 { 8 qDebug() << "focus in"; 9 ledSendStr->selectAll(); // 不起使用,只有在窗體獲取到焦點時才有功能 10 ledSendStr->setFocus(Qt::OtherFocusReason); 11 } 12 else if(QEvent::FocusOut == event->type()) 13 { 14 qDebug() << "focus out"; 15 } 16 } 17 else if(watched == ledSendFile) 18 { 19 } 20 else if(watched == ledSendPreTime) 21 { 22 } 23 return QWidget::eventFilter(watched,event); // 最后將事件交給上層對話框 24 }
2 繼承 QLineEdit, 再實現如下兩個 SIGNAL:
virtual void focusInEvent(QFocusEvent *e);
virtual void focusOutEvent(QFocusEvent *e);
1) 繼承類的聲明:
1 #ifndef MYLINEEDIT_H 2 #define MYLINEEDIT_H 3 4 #include <QLineEdit> 5 #include <QDebug> 6 7 class MyLineEdit: public QLineEdit 8 { 9 Q_OBJECT 10 11 public: 12 MyLineEdit(QWidget *parent=0); 13 ~MyLineEdit(); 14 15 protected: 16 virtual void focusInEvent(QFocusEvent *e); 17 virtual void focusOutEvent(QFocusEvent *e); 18 }; 19 20 #endif // MYLINEEDIT_H
2) 繼承類的實現:
1 #include "myLineEdit.h" 2 3 MyLineEdit::MyLineEdit(QWidget *parent):QLineEdit(parent) 4 { 5 } 6 7 MyLineEdit::~MyLineEdit() 8 { 9 } 10 11 void MyLineEdit::focusInEvent(QFocusEvent *e) 12 { 13 // qDebug() << "*MyLineEdit::focusInEvent" << this->objectName(); 14 15 QPalette pGreen = QPalette(); 16 pGreen.setColor(QPalette::Base,Qt::gray); //QPalette::Base 對可編輯輸入框有效,還有其他類型,具體的查看文檔 17 setPalette(pGreen); 18 19 ledSendStr->selectAll(); // 不起使用,只有在窗體獲取到焦點時才有功能 20 ledSendStr->setFocus(Qt::OtherFocusReason); 21 } 22 23 void MyLineEdit::focusOutEvent(QFocusEvent *e) 24 { 25 // qDebug() << "*MyLineEdit::focusOutEvent" << this->objectName(); 26 27 QPalette pWhite = QPalette(); 28 pWhite.setColor(QPalette::Base,Qt::white); 29 setPalette(pWhite); 30 }
3) 使用 MyLineEdit 類定義控件,並完成布局。
測試運行發現,3) 中定義的控件隨着焦點的獲取/失去顏色會發生變化,但全選字符串的功能卻無效!
但如果在如下代碼:
1 ledSendStr->selectAll(); 2 ledSendStr->setFocus(Qt::OtherFocusReason);
放在一個按鍵的 Clicked 槽中就可以實現全選字符串的功能。 為什么無效呢???原因不知道,想到的區別就是同樣的代碼,一個是在 MainWindow 中、而另一個是在 myLineEdit 中。
試着將 Focus Get/Lost 動作放到 MainWindow 中響應:通過 SIGNAL/SLOT 來實現。 1) 在繼承類的聲明中增加如下代碼:
1 signals: 2 void selectAllWhenFocus(QString strCtrlName);
2) 在繼承類實現的 void MyLineEdit::focusInEvent(QFocusEvent *e) 函數中增加如下代碼:
1 emit selectAllWhenFocus(this->objectName());
3) 在 MainWindow 的 .h 文件中增加如下代碼:
1 public slots: 2 void selectAllWhenFocusSlot(QString strCtrlName);
4) 在 MainWindow 的源代碼中增加如下代碼:
1 void MainWindow::selectAllWhenFocusSlot(QString strCtrlName) 2 { 3 // qDebug() << "Main Windows: " << strCtrlName; 4 5 ledSendStr->selectAll(); 6 ledSendStr->setFocus(Qt::OtherFocusReason); 7 }
但發現一樣無法實現全選控件中字符串的功能。 無語......
最后無奈下想到延時一下,再做全選的動作。修改上述第四步的代碼如下:
1 void MainWindow::selectAllWhenFocusSlot(QString strCtrlName) 2 { 3 // qDebug() << "Main Windows: " << strCtrlName; 4 5 m_strCtrlName = strCtrlName; 6 if(NULL != m_timerDelaySelect) 7 { 8 if(m_timerDelaySelect->isActive()) 9 { 10 m_timerDelaySelect->stop(); 11 } 12 delete m_timerDelaySelect; 13 m_timerDelaySelect = NULL; 14 } 15 m_timerDelaySelect = new QTimer(this); 16 //新建定時器 17 connect(m_timerDelaySelect,SIGNAL(timeout()),this,SLOT(timerUpDateSeleceAll())); 18 m_timerDelaySelect->start(200); 19 }
和延時超時的處理函數:
1 void MainWindow::timerUpDateSeleceAll() 2 { 3 if(m_strCtrlName == "ledSendPreTime") 4 { 5 ledSendPreTime->selectAll(); 6 ledSendPreTime->setFocus(Qt::OtherFocusReason); 7 } 8 else if(m_strCtrlName == "ledSendStr") 9 { 10 ledSendStr->selectAll(); 11 ledSendStr->setFocus(Qt::OtherFocusReason); 12 } 13 else if(m_strCtrlName == "ledSendFile") 14 { 15 ledSendFile->selectAll(); 16 ledSendFile->setFocus(Qt::OtherFocusReason); 17 } 18 19 if(NULL != m_timerDelaySelect) 20 { 21 if(m_timerDelaySelect->isActive()) 22 { 23 m_timerDelaySelect->stop(); 24 } 25 delete m_timerDelaySelect; 26 m_timerDelaySelect = NULL; 27 } 28 }
發現這樣全選控件中文符串的功能竟然實現了!!!
在實現上述功能時,遇到的第一個問題其實不是代碼,而不是 Layout 的問題: 之前所有控件是“拖”出來的,然后進行了 Layout 處理。忽然發現按上述修改,使用 MyLineEdit 類定義的第個控件是在代碼中定義的,無法像之前一樣“拖”到窗體中、並完成 Layout! 還好 QT 的代碼 Layout 功能比較強大。最后兩者結合才完成了想要的窗體 Layout。