简述
根据QtDesigner的控件选中,拉伸效果,用过Qt的盆友都很熟悉Qt的Designer,这个我就不多说了,我们先看看QtDesigner中的效果
Qt Designer效果图图
模仿功能介绍
1.支持选中效果;
2.支持自由拉伸效果;
3.支持双击鼠标左键编辑功能;
4.支持键盘 ↑↓←→按键移动;
5.支持按住ctrl + 鼠标左键 多选控件功能;
6.支持键盘delete键,删除选中控件功能;
模仿效果图
代码
//用法试例
formWindowManager = new FromWindowManager(this);
formWindowManager->addControlWidget(ui.label);
formWindowManager->addControlWidget(ui.pushButton);
formWindowManager->addControlWidget(ui.toolButton);
//窗口控件管理类
CompontEditor* FromWindowManagerPrivate::getWidgetForEditor(QWidget* widget)
{
for (auto iter : editorlst){
if (widget == iter->getEditorWidget()){
return iter;
}
}
return nullptr;
}
FromWindowManager::FromWindowManager(QWidget *parent)
: QObject(parent)
, d_ptr(new FromWindowManagerPrivate(this))
{
parent->setFocus(Qt::MouseFocusReason);
parent->installEventFilter(this);
}
FromWindowManager::~FromWindowManager()
{
}
void FromWindowManager::addControlWidget(QWidget* widget)
{
Q_D(FromWindowManager);
widget->installEventFilter(this);
CompontEditor* editor = new CompontEditor(widget, widget->property("text").toString(), widget->parentWidget());
d->editorlst << editor;
}
void FromWindowManager::setSelectWidget(CompontEditor* editorWidget)
{
Q_D(FromWindowManager);
d->selecteditorlst << editorWidget;
}
void FromWindowManager::clearSelectWidget(CompontEditor* editorWidget)
{
Q_D(FromWindowManager);
d->selecteditorlst.removeAll(editorWidget);
}
void FromWindowManager::removeControlWidget(CompontEditor* editorWidget)
{
Q_D(FromWindowManager);
editorWidget->getEditorWidget()->removeEventFilter(this);
d->editorlst.removeAll(editorWidget);
}
bool FromWindowManager::eventFilter(QObject *watched, QEvent *event)
{
switch (event->type()){
case QEvent::KeyPress:{
QKeyEvent* keyevent = dynamic_cast(event);
Q_D(FromWindowManager);
auto tmpselecteditorlst = d->selecteditorlst;
for (auto iter : tmpselecteditorlst){
QWidget* selectWidget = iter->getSelectWidget();
if (keyevent->key() == Qt::Key_Left){
selectWidget->move(selectWidget->pos() - QPoint(1, 0));
}
else if (keyevent->key() == Qt::Key_Right){
selectWidget->move(selectWidget->pos() + QPoint(1, 0));
}
else if (keyevent->key() == Qt::Key_Up){
selectWidget->move(selectWidget->pos() - QPoint(0, 1));
}
else if (keyevent->key() == Qt::Key_Down){
selectWidget->move(selectWidget->pos() + QPoint(0, 1));
}
else if (keyevent->key() == Qt::Key_Delete){
clearSelectWidget(iter);
removeControlWidget(iter);
delete iter->getEditorWidget();
delete iter;
}
}
return true;
}
break;
case QEvent::MouseButtonPress:{
Q_D(FromWindowManager);
auto editor =d->getWidgetForEditor(dynamic_cast(watched));
if (editor){
if (editor->isSelect()){
return false;
}
if (QApplication::keyboardModifiers() == Qt::ControlModifier){
QMouseEvent* mouseevent = dynamic_cast(event);
if (mouseevent->button() == Qt::LeftButton){
editor->setSelect();
}
}
else{
for (auto iter : d->selecteditorlst){
iter->clearSelect();
}
editor->setSelect();
d->selecteditorlst.clear();
}
d->selecteditorlst << editor;
}
else {
auto posWidget = qApp->widgetAt(QCursor::pos());
Q_D(FromWindowManager);
for (auto iter : d->editorlst){
if (iter->getEditorWidget() == posWidget ||
iter->getSelectWidget() == posWidget ||
iter == posWidget){
return false;
}
}
for (auto iter : d->selecteditorlst){
iter->clearSelect();
}
d->selecteditorlst.clear();
}
}
break;
default:
break;
}
return QObject::eventFilter(watched, event);
}
//选中控件类
SelectWidget::SelectWidget(QWidget *parent)
: QWidget(parent)
, d_ptr(new SelectWidgetPrivate(this))
{
this->setMouseTracking(true);
setObjectName("q_selectwidget");
}
SelectWidget::~SelectWidget()
{
}
void SelectWidget::paintEvent(QPaintEvent *event)
{
QWidget::paintEvent(event);
QPainter painter(this);
painerPathRect(&painter);
}
void SelectWidget::painerPathRect(QPainter* painter)
{
painter->setPen(Qt::NoPen);
painter->setBrush(Qt::blue);
painter->drawRect(0, 0, BACKRECT, BACKRECT);
painter->drawRect(width() / 2 - BACKRECT / 2, 0, BACKRECT, BACKRECT);
painter->drawRect(width() - BACKRECT, 0, BACKRECT, BACKRECT);
painter->drawRect(0, height() / 2 - BACKRECT / 2, BACKRECT, BACKRECT);
painter->drawRect(width() - BACKRECT, height() / 2 - BACKRECT / 2, BACKRECT, BACKRECT);
painter->drawRect(0, height() - BACKRECT, BACKRECT, BACKRECT);
painter->drawRect(width() / 2 - BACKRECT / 2, height() - BACKRECT, BACKRECT, BACKRECT);
painter->drawRect(width() - BACKRECT, height() - BACKRECT, BACKRECT, BACKRECT);
}
void SelectWidget::mousePressEvent(QMouseEvent *event)
{
Q_D(SelectWidget);
if (event->button() == Qt::LeftButton){
d->m_leftButtonPress = true;
}
d->m_mousepressPos = QCursor::pos();
QWidget::mousePressEvent(event);
}
void SelectWidget::mouseMoveEvent(QMouseEvent *event)
{
Q_D(SelectWidget);
if (d->m_leftButtonPress && d->m_type == SelectWidgetPrivate::NORMAL){
QPoint movepoint = QCursor::pos() - d->m_mousepressPos;
d->m_mousepressPos = QCursor::pos();
this->move(this->pos() + movepoint);
d->m_uiwidget->setGeometry(QRect(this->pos() + QPoint(2, 2), this->size() + QSize(-4, -4)));
}
else if (d->m_leftButtonPress && d->m_type != SelectWidgetPrivate::NORMAL){
resizeSection();
}
else{
updateCursorType();
}
QWidget::mouseMoveEvent(event);
}
void SelectWidget::mouseReleaseEvent(QMouseEvent *event)
{
Q_D(SelectWidget);
d->m_mousepressPos = event->globalPos();
d->m_leftButtonPress = false;
QWidget::mouseReleaseEvent(event);
}
void SelectWidget::updateCursor()
{
Q_D(SelectWidget);
switch (d->m_type) {
case SelectWidgetPrivate::LeftTop:
this->setCursor(Qt::SizeFDiagCursor);
break;
case SelectWidgetPrivate::Top:
this->setCursor(Qt::SizeVerCursor);
break;
case SelectWidgetPrivate::RightTop:
this->setCursor(Qt::SizeBDiagCursor);
break;
case SelectWidgetPrivate::Right:
this->setCursor(Qt::SizeHorCursor);
break;
case SelectWidgetPrivate::RightBottom:
this->setCursor(Qt::SizeFDiagCursor);
break;
case SelectWidgetPrivate::Bottom:
this->setCursor(Qt::SizeVerCursor);
break;
case SelectWidgetPrivate::LeftBottom:
this->setCursor(Qt::SizeBDiagCursor);
break;
case SelectWidgetPrivate::Left:
this->setCursor(Qt::SizeHorCursor);
break;
default:
this->setCursor(Qt::ArrowCursor);
break;
}
}
void SelectWidget::resizeSection()
{
Q_D(SelectWidget);
QPoint mousemovePos = QCursor::pos();
QPoint widgetGloabPoint(this->mapToGlobal(QPoint(0, 0)));
QPoint widgetpoint = this->mapToParent(this->mapFromGlobal(mousemovePos));
switch (d->m_type) {
case SelectWidgetPrivate::LeftTop:{
int resizeH = widgetGloabPoint.y() - mousemovePos.y() + this->height();
int resizeW = widgetGloabPoint.x() - mousemovePos.x() + this->width();
if (this->minimumHeight() <= resizeH && resizeH <= this->maximumHeight()){
this->setGeometry(this->x(), widgetpoint.y(), resizeW, resizeH);
}
if (this->minimumWidth() <= resizeW && resizeW <= this->maximumWidth()){
this->setGeometry(widgetpoint.x(), this->y(), resizeW, resizeH);
}
}
break;
case SelectWidgetPrivate::Top:{
int resizeH = widgetGloabPoint.y() - mousemovePos.y() + this->height();
if (this->minimumHeight() <= resizeH && resizeH <= this->maximumHeight()){
this->setGeometry(this->x(), widgetpoint.y(), this->width(), resizeH);
}
}
break;
case SelectWidgetPrivate::RightTop:{
int resizeH = widgetGloabPoint.y() + this->height() - mousemovePos.y();
int resizeW = mousemovePos.x() - widgetGloabPoint.x();
int pointY = widgetpoint.y();
if (this->minimumHeight() <= resizeH && resizeH <= this->maximumHeight()){
this->setGeometry(this->x(), widgetpoint.y(), resizeW, resizeH);
}
}
break;
case SelectWidgetPrivate::Right:{
int resizeW = mousemovePos.x() - widgetGloabPoint.x();
this->setGeometry(this->x(), this->y(), resizeW, this->height());
}
break;
case SelectWidgetPrivate::RightBottom:{
int resizeW = mousemovePos.x() - widgetGloabPoint.x();
int resizeH = mousemovePos.y() - widgetGloabPoint.y();
this->setGeometry(this->x(), this->y(), resizeW, resizeH);
}
break;
case SelectWidgetPrivate::Bottom:{
int resizeH = mousemovePos.y() - widgetGloabPoint.y();
this->setGeometry(this->x(), this->y(), this->width(), resizeH);
}
break;
case SelectWidgetPrivate::LeftBottom:{
int resizeH = mousemovePos.y() - widgetGloabPoint.y();
int resizeW = widgetGloabPoint.x() - mousemovePos.x() + this->width();
if (this->minimumWidth() <= resizeW && resizeW <= this->maximumWidth()){
this->setGeometry(widgetpoint.x(), this->y(), resizeW, resizeH);
}
if (this->minimumHeight() <= resizeH && resizeH <= this->maximumHeight()){
this->setGeometry(this->x(), this->y(), resizeW, resizeH);
}
}
break;
case SelectWidgetPrivate::Left:{
int resizeW = widgetGloabPoint.x() - mousemovePos.x() + this->width();
if (this->minimumWidth() <= resizeW && resizeW <= this->maximumWidth()){
this->setGeometry(widgetpoint.x(), this->y(), resizeW, this->height());
}
}
break;
default:{
}
break;
}
d->m_uiwidget->setGeometry(QRect(this->pos() + QPoint(2, 2), this->size() + QSize(-4, -4)));
}
void SelectWidget::moveEvent(QMoveEvent *event)
{
Q_D(SelectWidget);
d->m_uiwidget->move(this->pos() + QPoint(2, 2));
QWidget::moveEvent(event);
}
void SelectWidget::updateCursorType()
{
Q_D(SelectWidget);
QPoint mousemovePos = QCursor::pos();
QRect widgetGloabRect(this->mapToGlobal(QPoint(0, 0)), this->size());
if (QRect(widgetGloabRect.bottomLeft() - QPoint(DISTANCE / 2, DISTANCE / 2), widgetGloabRect.bottomLeft() + QPoint(DISTANCE / 2, DISTANCE / 2)).contains(mousemovePos)){
d->m_type = SelectWidgetPrivate::LeftBottom;
}
else if (QRect(widgetGloabRect.bottomRight() - QPoint(DISTANCE / 2, DISTANCE / 2), widgetGloabRect.bottomRight() + QPoint(DISTANCE / 2, DISTANCE / 2)).contains(mousemovePos)){
d->m_type = SelectWidgetPrivate::RightBottom;
}
else if (QRect(widgetGloabRect.topRight() - QPoint(DISTANCE / 2, DISTANCE / 2), widgetGloabRect.topRight() + QPoint(DISTANCE / 2, DISTANCE / 2)).contains(mousemovePos)){
d->m_type = SelectWidgetPrivate::RightTop;
}
else if (QRect(widgetGloabRect.topLeft() - QPoint(DISTANCE / 2, DISTANCE / 2), widgetGloabRect.topLeft() + QPoint(DISTANCE / 2, DISTANCE / 2)).contains(mousemovePos)){
d->m_type = SelectWidgetPrivate::LeftTop;
}
else if (qAbs(mousemovePos.x() - widgetGloabRect.left()) < DISTANCE){
d->m_type = SelectWidgetPrivate::Left;
}
else if (qAbs(mousemovePos.y() - widgetGloabRect.bottom()) < DISTANCE){
d->m_type = SelectWidgetPrivate::Bottom;
}
else if (qAbs(mousemovePos.x() - widgetGloabRect.right()) < DISTANCE){
d->m_type = SelectWidgetPrivate::Right;
}
else if (qAbs(mousemovePos.y() - widgetGloabRect.top()) < DISTANCE){
d->m_type = SelectWidgetPrivate::Top;
}
else{
d->m_type = SelectWidgetPrivate::NORMAL;
}
updateCursor();
}
void SelectWidget::setSelectWidget(QWidget* widget)
{
Q_D(SelectWidget);
d->m_uiwidget = widget;
}
QWidget* SelectWidget::getSelectWidget()
{
Q_D(SelectWidget);
return d->m_uiwidget;
}
void SelectWidget::setSelectWidgetMask(const QRect& rect)
{
setMask(QRegion(rect));
}
void SelectWidget::resizeEvent(QResizeEvent *event)
{
QPixmap pixmap(this->size());
pixmap.fill(Qt::transparent);
QPainter painter(&pixmap);
painerPathRect(&painter);
setMask(pixmap.mask());
QWidget::resizeEvent(event);
}
void SelectWidget::handleMouseMoveEvent(QMouseEvent* mouseevent)
{
mouseMoveEvent(mouseevent);
}
void SelectWidget::handleMousePressEvent(QMouseEvent* mouseevent)
{
mousePressEvent(mouseevent);
}
void SelectWidget::handleReleaseEvent(QMouseEvent* mouseevent)
{
mouseReleaseEvent(mouseevent);
}
//控件编辑类
TextEditor::TextEditor(QWidget* parent)
: QWidget(parent)
, m_lineEdit(new QLineEdit(this))
{
installEventFilter(this);
m_lineEdit->setObjectName("q_texteditor");
m_lineEdit->setFrame(false);
m_lineEdit->setBackgroundRole(parent->backgroundRole());
setFocusProxy(m_lineEdit);
connect(m_lineEdit, &QLineEdit::editingFinished, this, &TextEditor::editingFinished);
connect(m_lineEdit, &QLineEdit::returnPressed, this, &TextEditor::slotEditingFinished);
connect(m_lineEdit, &QLineEdit::textChanged, this, &TextEditor::slotTextChanged);
}
TextEditor::~TextEditor()
{
}
void TextEditor::slotTextChanged(const QString &text)
{
m_cachedText = text;
}
void TextEditor::slotEditingFinished()
{
emit textChanged(m_cachedText);
}
QString TextEditor::text() const{
return m_cachedText;
}
void TextEditor::setText(const QString &text){
m_cachedText = text;
m_lineEdit->setText(text);
}
void TextEditor::setAlignment(Qt::Alignment align)
{
m_lineEdit->setAlignment(align);
}
void TextEditor::selectAll() {
m_lineEdit->selectAll();
}
void TextEditor::clear() {
m_lineEdit->clear();
}
void TextEditor::resizeEvent(QResizeEvent * event) {
m_lineEdit->resize(event->size());
}
QSize TextEditor::sizeHint() const {
return m_lineEdit->sizeHint();
}
QSize TextEditor::minimumSizeHint() const {
return m_lineEdit->minimumSizeHint();
}
void TextEditor::installEventFilter(QObject *filterObject)
{
if (m_lineEdit)
m_lineEdit->installEventFilter(filterObject);
}
CompontEditor::CompontEditor(QWidget *widget, const QString& text, QWidget* parent)
: TextEditor(parent)
, m_widget(widget)
{
qApp->installEventFilter(this);
setText(text);
selectAll();
setAlignment(alignment());
QRect r = editRectangle();
setGeometry(QRect(widget->mapTo(widget->window(), r.topLeft()), r.size()));
m_selectWidget = new SelectWidget(parent);
m_selectWidget->setSelectWidget(widget);
m_selectWidget->installEventFilter(this);
m_selectWidget->setMinimumSize(m_widget->minimumSize() + QSize(4, 4));
m_selectWidget->setMaximumSize(m_widget->maximumSize() + QSize(4, 4));
m_selectWidget->setGeometry(QRect(m_widget->pos() + QPoint(-2, -2), m_widget->size() + QSize(4, 4)));
this->hide();
m_selectWidget->hide();
connect(this, &TextEditor::editingFinished, [this](){
this->hide();
m_widget->stackUnder(m_selectWidget);
m_widget->setProperty("text", this->text());
});
connect(m_widget, &QWidget::destroyed, [this](){
delete m_selectWidget;
});
}
Qt::Alignment CompontEditor::alignment() const {
if (m_widget->metaObject()->indexOfProperty("alignment") != -1)
return Qt::Alignment(m_widget->property("alignment").toInt());
if (qobject_cast(m_widget) || qobject_cast(m_widget))
return Qt::AlignHCenter;
return Qt::AlignJustify;
}
CompontEditor::~CompontEditor(){
}
QRect CompontEditor::editRectangle() const
{
QStyleOptionButton opt;
opt.init(m_widget);
if (m_widget->inherits("QPushButton")){
return m_widget->style()->subElementRect(QStyle::SE_PushButtonContents, &opt, m_widget);
}
else if (m_widget->inherits("QRadioButton")){
return m_widget->style()->subElementRect(QStyle::SE_RadioButtonContents, &opt, m_widget);
}
else if (m_widget->inherits("QCheckBox")){
return m_widget->style()->subElementRect(QStyle::SE_CheckBoxContents, &opt, m_widget);
}
else{
return opt.rect;
}
}
bool CompontEditor::eventFilter(QObject *watched, QEvent *event)
{
if (event->type() == QEvent::MouseButtonDblClick){
if (watched == m_widget){
this->selectAll();
this->setFocus();
this->show();
m_selectWidget->stackUnder(m_widget);
}
}
else if (event->type() == QEvent::MouseButtonPress){
QMouseEvent* mouse = dynamic_cast(event);
if (watched != m_widget){
QRect rect(this->mapToGlobal(QPoint(0, 0)), this->size());
if (this->isVisible() && !rect.contains(mouse->globalPos())){
emit editingFinished();
}
}
else{
m_selectWidget->handleMousePressEvent(dynamic_cast(event));
}
}
else if (event->type() == QEvent::MouseMove){
if (watched == m_widget){
m_selectWidget->handleMouseMoveEvent(dynamic_cast(event));
}
}
else if (event->type() == QEvent::MouseButtonRelease){
if (watched == m_widget){
m_selectWidget->handleReleaseEvent(dynamic_cast(event));
}
}
else if (event->type() == QEvent::Show) {
if (watched == this){
QRect r = editRectangle();
setGeometry(QRect(m_widget->mapTo(m_widget->window(), r.topLeft()), r.size()));
}
}
return TextEditor::eventFilter(watched, event);
}
QWidget* CompontEditor::getEditorWidget() const
{
return m_widget;
}
void CompontEditor::clearSelect()
{
m_selectWidget->hide();
}
void CompontEditor::setSelect()
{
m_selectWidget->show();
}
bool CompontEditor::isSelect()
{
return m_selectWidget->isVisible();
}
QWidget* CompontEditor::getSelectWidget() const
{
return m_selectWidget;
}
工程文件
Qt交流大会 853086607 免费群中
结尾
不定期上传新作品,解答群中作品相关问题。相关外,能解答则解答。欢迎大家一起探索Qt世界!