查找对话框需求分析:
附加需求:
#ifndef _FINDDIALOG_H_
#define _FINDDIALOG_H_
#include
#include
#include
#include
#include
#include
#include
#include
#include
class FindDialog : public QDialog
{
Q_OBJECT
protected:
/*
* 必须注意,这里的初始化顺序很重要,m_radioGrpBx必须在m_hbLayout之前声明,如果在其后m_radioGrpBx析构时会将m_hbLayout进行析构,但是m_hbLayout是栈对象,被delete就会出问题,一定要注意!!!
*/
QGroupBox m_radioGrpBx;
QGridLayout m_layout;
QHBoxLayout m_hbLayout;
QLabel m_findLbl;
QLineEdit m_findEdit;
QPushButton m_findBtn;
QPushButton m_closeBtn;
QCheckBox m_matchChkBx;
QRadioButton m_forwardBtn;
QRadioButton m_backwardBtn;
public:
explicit FindDialog(QWidget* parent = 0);
bool event(QEvent* evt);
signals:
public slots:
};
#endif // _FINDDIALOG_H_
FindDialog.cpp:
#include "FindDialog.h"
#include
FindDialog::FindDialog(QWidget *parent) : QDialog(parent, Qt::WindowCloseButtonHint | Qt::Drawer)
{
m_findLbl.setText("Find What:");
m_findBtn.setText("Find Next");
m_closeBtn.setText("Close");
m_matchChkBx.setText("Match Case");
m_backwardBtn.setText("Backward");
m_forwardBtn.setText("Forward");
m_forwardBtn.setChecked(true);
m_radioGrpBx.setTitle("Direction");
m_hbLayout.addWidget(&m_forwardBtn);
m_hbLayout.addWidget(&m_backwardBtn);
m_radioGrpBx.setLayout(&m_hbLayout);
m_layout.setSpacing(10);
m_layout.addWidget(&m_findLbl, 0, 0);
m_layout.addWidget(&m_findEdit, 0, 1);
m_layout.addWidget(&m_findBtn, 0, 2);
m_layout.addWidget(&m_matchChkBx, 1, 0);
m_layout.addWidget(&m_radioGrpBx, 1, 1);
m_layout.addWidget(&m_closeBtn, 1, 2);
setLayout(&m_layout);
setWindowTitle("Find");
}
bool FindDialog::event(QEvent* evt)
{
if( evt->type() == QEvent::Close )
{
hide();
return true;
}
return QDialog::event(evt);
}
文本查找功能的核心思想:
QString类中提供了子串查找的相关函数:
QS同日那个类中查找函数所使用的下标位置:
Qt中的光标信息类QTextCursor:
最终版本的实现如下:
FindDialog.h:
#ifndef _FINDDIALOG_H_
#define _FINDDIALOG_H_
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
class FindDialog : public QDialog
{
Q_OBJECT
protected:
QGroupBox m_radioGrpBx;
QGridLayout m_layout;
QHBoxLayout m_hbLayout;
QLabel m_findLbl;
QLineEdit m_findEdit;
QPushButton m_findBtn;
QPushButton m_closeBtn;
QCheckBox m_matchChkBx;
QRadioButton m_forwardBtn;
QRadioButton m_backwardBtn;
QPointer<QPlainTextEdit> m_pText;
void initControl();
void connectSlot();
protected slots:
void onFindClicked();
void onCloseClicked();
public:
explicit FindDialog(QWidget* parent = 0, QPlainTextEdit* pText = 0);
void setPlainTextEdit(QPlainTextEdit* pText);
QPlainTextEdit* getPlainTextEdit();
bool event(QEvent* evt);
};
#endif // _FINDDIALOG_H_
FindDialog.cpp:
#include "FindDialog.h"
#include
#include
#include
FindDialog::FindDialog(QWidget *parent, QPlainTextEdit* pText)
: QDialog(parent, Qt::WindowCloseButtonHint | Qt::Drawer)
{
initControl();
connectSlot();
setLayout(&m_layout);
setWindowTitle("Find");
setPlainTextEdit(pText);
}
void FindDialog::initControl()
{
m_findLbl.setText("Find What:");
m_findBtn.setText("Find Next");
m_closeBtn.setText("Close");
m_matchChkBx.setText("Match Case");
m_backwardBtn.setText("Backward");
m_forwardBtn.setText("Forward");
m_forwardBtn.setChecked(true);
m_radioGrpBx.setTitle("Direction");
m_hbLayout.addWidget(&m_forwardBtn);
m_hbLayout.addWidget(&m_backwardBtn);
m_radioGrpBx.setLayout(&m_hbLayout);
m_layout.setSpacing(10);
m_layout.addWidget(&m_findLbl, 0, 0);
m_layout.addWidget(&m_findEdit, 0, 1);
m_layout.addWidget(&m_findBtn, 0, 2);
m_layout.addWidget(&m_matchChkBx, 1, 0);
m_layout.addWidget(&m_radioGrpBx, 1, 1);
m_layout.addWidget(&m_closeBtn, 1, 2);
}
void FindDialog::connectSlot()
{
connect(&m_findBtn, SIGNAL(clicked()), this, SLOT(onFindClicked()));
connect(&m_closeBtn, SIGNAL(clicked()), this, SLOT(onCloseClicked()));
}
void FindDialog::setPlainTextEdit(QPlainTextEdit* pText)
{
m_pText = pText;
}
QPlainTextEdit* FindDialog::getPlainTextEdit()
{
return m_pText;
}
bool FindDialog::event(QEvent* evt)
{
if( evt->type() == QEvent::Close )
{
hide();
return true;
}
return QDialog::event(evt);
}
void FindDialog::onFindClicked()
{
QString target = m_findEdit.text();
if( (m_pText != NULL) && (target != "") )
{
QString text = m_pText->toPlainText();
QTextCursor c = m_pText->textCursor();
int index = -1;
if( m_forwardBtn.isChecked() )
{
index = text.indexOf(target, c.position(), m_matchChkBx.isChecked() ? Qt::CaseSensitive : Qt::CaseInsensitive);
if( index >= 0 )
{
c.setPosition(index);
c.setPosition(index + target.length(), QTextCursor::KeepAnchor);
m_pText->setTextCursor(c);
}
}
if( m_backwardBtn.isChecked() )
{
index = text.lastIndexOf(target, c.position() - text.length() - 1, m_matchChkBx.isChecked() ? Qt::CaseSensitive : Qt::CaseInsensitive);
if( index >= 0 )
{
c.setPosition(index + target.length());
c.setPosition(index, QTextCursor::KeepAnchor);
m_pText->setTextCursor(c);
}
}
if( index < 0 )
{
QMessageBox msg(this);
msg.setWindowTitle("Find");
msg.setText("Can not find \"" + target + "\" any more...");
msg.setIcon(QMessageBox::Information);
msg.setStandardButtons(QMessageBox::Ok);
msg.exec();
}
}
}
void FindDialog::onCloseClicked()
{
close();
}
MainWindow的构造函数需要修改:
为了解决文本框得到焦点和失去焦点被选择文本的样式保持一致,我们需要使用调色板对mainEditor进行设置,设置如下:
bool MainWindow::initMainEditor()
{
bool ret = true;
QPalette p = mainEditor.palette();
p.setColor(QPalette::Inactive, QPalette::Highlight, p.color(QPalette::Active, QPalette::Highlight));
p.setColor(QPalette::Inactive, QPalette::HighlightedText, p.color(QPalette::Active, QPalette::HighlightedText));
mainEditor.setPalette(p);
mainEditor.setParent(this);
connect(&mainEditor, SIGNAL(textChanged()), this, SLOT(onTextChanged()));
connect(&mainEditor, SIGNAL(copyAvailable(bool)), this, SLOT(onCopyAvailable(bool)));
connect(&mainEditor, SIGNAL(redoAvailable(bool)), this, SLOT(onRedoAvailable(bool)));
connect(&mainEditor, SIGNAL(undoAvailable(bool)), this, SLOT(onUndoAvailable(bool)));
connect(&mainEditor, SIGNAL(cursorPositionChanged()), this, SLOT(onCursorPositionChanged()));
setCentralWidget(&mainEditor);
return ret;
}
参考资料: