来源:
http://blog.sina.com.cn/s/blog_a6fb6cc90101b3b8.html
在用Qt做密码输入框的时候,原本想简单实现屏蔽复制、粘贴、右键菜单等功能,但最后想实现类似QQ密码框一样文本内容不被选中,反复推敲,实在没有合适的办法,这几天也一直在研究,终于有了一些思路,在此分享一下!
password_line_edit->setCursorPosition(length); password_line_edit->setSelection(length, length);这两个方法挺有用的,设置选中个数、设置光标位置。
屏蔽文本被选中之前如下所示:
无论是全选还是部分选择,文本内容都处于选中状态!而我们要实现的是无论如何都不能让它被选中,经过反复尝试、验证,文本被选中状态有以下几种情况:
1、全选(Ctrl+A)
2、鼠标双击(频繁点击)
3、Shift + Home 组合键
4、Shift + End 组合键
5、Shift + 鼠标点击
6、Tab键切换
7、左、右键
。。。
其实大概就这几种情况,根据分析要实现文本内容不被选中就必须重写几个方法!
void PwdLineEdit::keyPressEvent(QKeyEvent *event)
{
//屏蔽全选,这里最好不要使用Ctrl+A,因为不一点全选都被设置为它,所以使用系统的比较好
if(event->matches(QKeySequence::SelectAll))
{
return ;
}
//屏蔽复制,和全选一样,这里最好不要使用Ctrl+A
else if(event->matches(QKeySequence::Copy))
{
return ;
}
//屏蔽粘贴
else if(event->matches(QKeySequence::Paste))
{
return ;
}
//设置Home、End键直接将光标位置设到最前、最后,而不被选中
else if(event->key() == Qt::Key_Home)
{
this->setCursorPosition(0);
}
else if(event->key() == Qt::Key_End)
{
this->setCursorPosition(this->text().length());
}
else
{
QLineEdit::keyPressEvent(event);
}
}
//鼠标移动时,什么都不干,因为一般情况下当鼠标移动文本都会被选中
void PwdLineEdit::mouseMoveEvent(QMouseEvent *event)
{
return ;
}
//同上,鼠标双击什么也不干
void PwdLineEdit::mouseDoubleClickEvent(QMouseEvent *event)
{
return ;
}
//这个事件比较重要,当按下Shift键时,点击文本是会被选中的,所以需要重新定义
void PwdLineEdit::mousePressEvent(QMouseEvent *event)
{
//获得当前鼠标位置
int cursor_pos = cursorPositionAt(event->pos());
//获取光标位置
int current_pos = this->cursorPosition();
//鼠标点击位置在光标位置之前,则设置光标前移一格
if(cursor_pos < current_pos)
{
this->setCursorPosition(current_pos - 1);
}
//鼠标点击位置在光标位置之后,则设置光标后移一格
else if(cursor_pos > current_pos)
{
this->setCursorPosition(current_pos + 1);
}
else if(cursor_pos == current_pos)
{
this->setCursorPosition(current_pos);
}
else
{
QLineEdit::mousePressEvent(event);
}
}
完工之后,全选、Home、End...都被屏蔽掉了,这样文本就在不被选中了!
但是如果存在其他组件的时候,上、下键还是会选中,所以再添加如下代码就行了!
bool LoginDialog::eventFilter(QObject *obj, QEvent *event)
{
if(obj == domain_line_edit || obj == user_line_edit || obj == password_line_edit || obj == check_box ||
obj == login_button || obj == forgot_pwd_button || obj == regist_button || obj == set_button || obj == min_button || obj == close_button)
{
if(event->type() == QEvent::KeyPress)
{
//将事件转化为键盘事件
QKeyEvent *key_event = static_cast<QKeyEvent *>(event);
bool domain_edit_focus = domain_line_edit->hasFocus();
bool user_edit_focus = user_line_edit->hasFocus();
bool password_edit_focus = password_line_edit->hasFocus();
bool check_box_focus = check_box->hasFocus();
bool set_btn_focus = set_button->hasFocus();
bool login_btn_focus = login_button->hasFocus();
bool get_pwd_btn_focus = forgot_pwd_button->hasFocus();
bool register_btn_focus = regist_button->hasFocus();
bool min_btn_focus = min_button->hasFocus();
bool close_btn_focus = close_button->hasFocus();
//按下Tab键执行焦点切换事件
if(key_event->key() == Qt::Key_Tab)
{
if(domain_edit_focus)
{
focusNextChild();
user_line_edit->setFocus();
}
else if(user_edit_focus)
{
focusNextChild();
//获取密码框输入内容长度,并设置光标位置
int length = password_line_edit->text().length();
password_line_edit->setSelection(length, length);
password_line_edit->setFocus();
}
else if(password_edit_focus)
{
focusNextChild();
check_box->setFocus();
}
else if(check_box_focus)
{
focusNextChild();
login_button->setFocus();
}
else if(login_btn_focus)
{
focusNextChild();
forgot_pwd_button->setFocus();
}
else if(get_pwd_btn_focus)
{
focusNextChild();
regist_button->setFocus();
}
else if(register_btn_focus)
{
focusNextChild();
set_button->setFocus();
}
else if(set_btn_focus)
{
focusNextChild();
min_button->setFocus();
}
else if(min_btn_focus)
{
focusNextChild();
close_button->setFocus();
}
else if(close_btn_focus)
{
focusNextChild();
domain_line_edit->setFocus();
}
else
{
focusNextChild();
}
return true;
}
//主要禁用上、下按键
else if(key_event->key() == Qt::Key_Up)
{
return true;
}
else if(key_event->key() == Qt::Key_Down)
{
return true;
}
//左右键功能,若为密码框则前进、后退一位,若为普通输入框,则设为默认操作,其他按钮,复选框则不起作用
else if(key_event->key() == Qt::Key_Left)
{
if(domain_edit_focus || user_edit_focus)
{
return QDialog::eventFilter(obj, event);
}
else if(password_edit_focus)
{
if(password_line_edit->cursorPosition() > 0)
{
password_line_edit->setCursorPosition(password_line_edit->cursorPosition() - 1);
}
return true;
}
else
{
return true;
}
}
else if(key_event->key() == Qt::Key_Right)
{
if(domain_edit_focus || user_edit_focus)
{
return QDialog::eventFilter(obj, event);
}
else if(password_edit_focus)
{
if(password_line_edit->cursorPosition() < password_line_edit->text().length())
{
password_line_edit->setCursorPosition(password_line_edit->cursorPosition() + 1);
}
return true;
}
else
{
return true;
}
}
}
return QDialog::eventFilter(obj, event);
}
return QDialog::eventFilter(obj, event);
}
这些就可以屏蔽掉文本内容被选中了,当然在多个控件切换的时候还有可能其他控件的切换会聚焦到密码框中,只需要像上面那样屏蔽掉就行了!