C++ 显示不对焦的Qt窗口

C++ 显示不对焦的Qt窗口,c++,qt,C++,Qt,我如何使用Qt创建一个用户可以交互的窗口(即,单击窗口中的按钮),但不会改变或聚焦 用例:我有一个QLineEdit,我想在QLineEdit获得焦点时显示一个额外的“操纵器”弹出窗口。此操纵器弹出窗口可能包括用于转换为大写/小写等任务的按钮 如果我将操纵器的所有子窗口小部件的焦点策略设置为Qt::NoFocus,我就可以让它工作,但这感觉有点奇怪,因为我必须对它们进行迭代 我想知道是否有一种方法可以完全禁用小部件的焦点,比如setEnabled()将禁用/启用所有子小部件 以下是迄今为止的一些

我如何使用Qt创建一个用户可以交互的窗口(即,单击窗口中的按钮),但不会改变或聚焦

用例:我有一个
QLineEdit
,我想在
QLineEdit
获得焦点时显示一个额外的“操纵器”弹出窗口。此操纵器弹出窗口可能包括用于转换为大写/小写等任务的按钮

如果我将操纵器的所有子窗口小部件的焦点策略设置为
Qt::NoFocus
,我就可以让它工作,但这感觉有点奇怪,因为我必须对它们进行迭代

我想知道是否有一种方法可以完全禁用小部件的焦点,比如
setEnabled()
将禁用/启用所有子小部件

以下是迄今为止的一些调查结果

QCompleter
QCompleter
执行与
QLineEdit
非常类似的操作,显示一个
QListView
弹出窗口。它通过将
QListView
的父项设置为0,使其成为一个窗口,并设置
Qt::Popup
窗口标志,使其无框架来实现。最后,它设置
focusPolicy(Qt::NoFocus)
以防止它从相关的
QLineEdit
中接管焦点

这很简单,因为只有一个小部件需要将其焦点策略设置为
Qt::NoFocus

QDateTimeEdit
QDateTimeEdit
中,执行类似操作。然而,那里的弹出窗口实际上会聚焦。

没有现成的小部件。但是,可以这样做:

头文件:

#include <QObject>
#include <QWidget>
#include <QLineEdit>
#include <QBoxLayout>
#include <QPushButton>
#include <QFocusEvent>

class LineEdit : public QLineEdit
{
    Q_OBJECT
public:
    LineEdit(QWidget *parent) : QLineEdit(parent)
    { }

    void focusInEvent(QFocusEvent *event) override
    {
        QLineEdit::focusInEvent(event);
        emit focusIn();
    }

    void focusOutEvent(QFocusEvent *event) override
    {
        QLineEdit::focusOutEvent(event);
        emit focusOut();
    }

signals:
    void focusIn();
    void focusOut();
};

class ExtendedLineEdit : public QWidget
{
    Q_OBJECT
public:
    explicit ExtendedLineEdit(QWidget *parent = nullptr);

protected:
    bool eventFilter(QObject *obj, QEvent *event) override;

private:
    void setupWidget();

    LineEdit *lineEdit;
    QWidget *showableWidget;
    QPushButton *toUppercaseButton;
    QPushButton *toLowercaseButton;

    QWidget *parent;

};
#include "ExtendedLineEdit.h"
#include <QPoint>

ExtendedLineEdit::ExtendedLineEdit(QWidget *parent)
    : QWidget(parent)
    , parent(parent)
{
    setupWidget();
}

bool ExtendedLineEdit::eventFilter(QObject *obj, QEvent *event)
{
    Q_UNUSED(obj)
    if (event->type() == QEvent::MouseButtonRelease ||
        event->type() == QEvent::MouseButtonPress ||
        event->type() == QEvent::MouseButtonDblClick)
    {
        lineEdit->setFocus();
    }
    return false;
}

void ExtendedLineEdit::setupWidget()
{
    auto mainLayout = new QBoxLayout(QBoxLayout::Direction::TopToBottom, this);
    this->setLayout(mainLayout);

    lineEdit = new LineEdit(this);
    mainLayout->addWidget(lineEdit);

    showableWidget = new QWidget(parent);
    showableWidget->setAutoFillBackground(true);
    showableWidget->setPalette(QPalette(QPalette::Background, Qt::white));
    showableWidget->hide();

    auto bottomLayout = new QBoxLayout(QBoxLayout::Direction::LeftToRight, showableWidget);
    showableWidget->setLayout(bottomLayout);

    toUppercaseButton = new QPushButton("to uppercase", this);
    toUppercaseButton->installEventFilter(this);
    connect(toUppercaseButton, &QPushButton::clicked,
            this, [&]{
       lineEdit->setText(lineEdit->text().toUpper());
    });

    toLowercaseButton = new QPushButton("to lowercase", this);
    toLowercaseButton->installEventFilter(this);
    connect(toLowercaseButton, &QPushButton::clicked,
            this, [&]{
       lineEdit->setText(lineEdit->text().toLower());
    });

    bottomLayout->addWidget(toUppercaseButton);
    bottomLayout->addWidget(toLowercaseButton);

    connect(lineEdit, &LineEdit::focusIn,
            this, [&]{
            auto size = lineEdit->size();
            auto position = QWidget::mapTo(parent, lineEdit->pos());

            showableWidget->setGeometry(position.x(),
                                        position.y() + size.height(),
                                        size.width(),
                                        40);
            showableWidget->show();

    });

    connect(lineEdit, &LineEdit::focusOut,
            showableWidget, &QWidget::hide);
}
#包括
#包括
#包括
#包括
#包括
#包括
类LineEdit:公共QLineEdit
{
Q_对象
公众:
LineEdit(QWidget*父项):QLineEdit(父项)
{ }
无效焦点事件(QFocusEvent*事件)覆盖
{
QLineEdit::focusInEvent(事件);
发射聚焦素();
}
无效focusOutEvent(QFocusEvent*事件)覆盖
{
QLineEdit::focusOutEvent(事件);
发射focusOut();
}
信号:
无效聚焦素();
void focusOut();
};
类ExtendedLineEdit:publicqwidget
{
Q_对象
公众:
显式ExtendedLineEdit(QWidget*parent=nullptr);
受保护的:
布尔事件过滤器(QObject*obj,QEvent*event)覆盖;
私人:
void setupWidget();
LineEdit*LineEdit;
QWidget*showableWidget;
QPushButton*ToupperCase按钮;
QPushButton*toLowercaseButton;
QWidget*父母;
};
源文件:

#include <QObject>
#include <QWidget>
#include <QLineEdit>
#include <QBoxLayout>
#include <QPushButton>
#include <QFocusEvent>

class LineEdit : public QLineEdit
{
    Q_OBJECT
public:
    LineEdit(QWidget *parent) : QLineEdit(parent)
    { }

    void focusInEvent(QFocusEvent *event) override
    {
        QLineEdit::focusInEvent(event);
        emit focusIn();
    }

    void focusOutEvent(QFocusEvent *event) override
    {
        QLineEdit::focusOutEvent(event);
        emit focusOut();
    }

signals:
    void focusIn();
    void focusOut();
};

class ExtendedLineEdit : public QWidget
{
    Q_OBJECT
public:
    explicit ExtendedLineEdit(QWidget *parent = nullptr);

protected:
    bool eventFilter(QObject *obj, QEvent *event) override;

private:
    void setupWidget();

    LineEdit *lineEdit;
    QWidget *showableWidget;
    QPushButton *toUppercaseButton;
    QPushButton *toLowercaseButton;

    QWidget *parent;

};
#include "ExtendedLineEdit.h"
#include <QPoint>

ExtendedLineEdit::ExtendedLineEdit(QWidget *parent)
    : QWidget(parent)
    , parent(parent)
{
    setupWidget();
}

bool ExtendedLineEdit::eventFilter(QObject *obj, QEvent *event)
{
    Q_UNUSED(obj)
    if (event->type() == QEvent::MouseButtonRelease ||
        event->type() == QEvent::MouseButtonPress ||
        event->type() == QEvent::MouseButtonDblClick)
    {
        lineEdit->setFocus();
    }
    return false;
}

void ExtendedLineEdit::setupWidget()
{
    auto mainLayout = new QBoxLayout(QBoxLayout::Direction::TopToBottom, this);
    this->setLayout(mainLayout);

    lineEdit = new LineEdit(this);
    mainLayout->addWidget(lineEdit);

    showableWidget = new QWidget(parent);
    showableWidget->setAutoFillBackground(true);
    showableWidget->setPalette(QPalette(QPalette::Background, Qt::white));
    showableWidget->hide();

    auto bottomLayout = new QBoxLayout(QBoxLayout::Direction::LeftToRight, showableWidget);
    showableWidget->setLayout(bottomLayout);

    toUppercaseButton = new QPushButton("to uppercase", this);
    toUppercaseButton->installEventFilter(this);
    connect(toUppercaseButton, &QPushButton::clicked,
            this, [&]{
       lineEdit->setText(lineEdit->text().toUpper());
    });

    toLowercaseButton = new QPushButton("to lowercase", this);
    toLowercaseButton->installEventFilter(this);
    connect(toLowercaseButton, &QPushButton::clicked,
            this, [&]{
       lineEdit->setText(lineEdit->text().toLower());
    });

    bottomLayout->addWidget(toUppercaseButton);
    bottomLayout->addWidget(toLowercaseButton);

    connect(lineEdit, &LineEdit::focusIn,
            this, [&]{
            auto size = lineEdit->size();
            auto position = QWidget::mapTo(parent, lineEdit->pos());

            showableWidget->setGeometry(position.x(),
                                        position.y() + size.height(),
                                        size.width(),
                                        40);
            showableWidget->show();

    });

    connect(lineEdit, &LineEdit::focusOut,
            showableWidget, &QWidget::hide);
}
#包括“ExtendedLineEdit.h”
#包括
ExtendedLineEdit::ExtendedLineEdit(QWidget*父项)
:QWidget(父项)
,家长(家长)
{
setupWidget();
}
bool ExtendedLineEdit::eventFilter(QObject*obj,QEvent*event)
{
Q_未使用(obj)
如果(事件->类型()==QEvent::MouseButtonRelease||
事件->类型()==QEvent::MouseButtonPress||
事件->类型()==QEvent::MouseButtonDblClick)
{
lineEdit->setFocus();
}
返回false;
}
void ExtendedLineEdit::setupWidget()
{
auto Main布局=新的QBoxLayout(QBoxLayout::Direction::TopToBottom,this);
此->设置布局(主布局);
lineEdit=新建lineEdit(此);
mainLayout->addWidget(lineEdit);
showableWidget=新的QWidget(父项);
showableWidget->setAutoFillBackground(真);
showableWidget->setPalette(Qpalete(Qpalete::Background,Qt::white));
showableWidget->hide();
自动底部布局=新的QBoxLayout(QBoxLayout::Direction::LeftToRight,showableWidget);
showableWidget->setLayout(底部布局);
toUppercaseButton=新的QPushButton(“到大写”,this);
toUppercaseButton->installEventFilter(此);
连接(toUppercaseButton,&QPushButton::单击,
这个,[&]{
lineEdit->setText(lineEdit->text().toUpper());
});
toLowercaseButton=新的QPushButton(“to lowercase”,this);
toLowercaseButton->installEventFilter(此选项);
连接(toLowercaseButton,&QPushButton::单击,
这个,[&]{
lineEdit->setText(lineEdit->text().toLower());
});
bottomLayout->addWidget(toUppercaseButton);
底部布局->添加小部件(toLowercaseButton);
连接(lineEdit,&lineEdit::focusIn,
这个,[&]{
自动大小=行编辑->大小();
auto position=QWidget::mapTo(父级,lineEdit->pos());
showableWidget->setGeometry(position.x(),
position.y()+size.height(),
size.width(),
40);
showableWidget->show();
});
连接(lineEdit,&lineEdit::focusOut,
showableWidget,&QWidget::hide);
}
结果:

#include <QObject>
#include <QWidget>
#include <QLineEdit>
#include <QBoxLayout>
#include <QPushButton>
#include <QFocusEvent>

class LineEdit : public QLineEdit
{
    Q_OBJECT
public:
    LineEdit(QWidget *parent) : QLineEdit(parent)
    { }

    void focusInEvent(QFocusEvent *event) override
    {
        QLineEdit::focusInEvent(event);
        emit focusIn();
    }

    void focusOutEvent(QFocusEvent *event) override
    {
        QLineEdit::focusOutEvent(event);
        emit focusOut();
    }

signals:
    void focusIn();
    void focusOut();
};

class ExtendedLineEdit : public QWidget
{
    Q_OBJECT
public:
    explicit ExtendedLineEdit(QWidget *parent = nullptr);

protected:
    bool eventFilter(QObject *obj, QEvent *event) override;

private:
    void setupWidget();

    LineEdit *lineEdit;
    QWidget *showableWidget;
    QPushButton *toUppercaseButton;
    QPushButton *toLowercaseButton;

    QWidget *parent;

};
#include "ExtendedLineEdit.h"
#include <QPoint>

ExtendedLineEdit::ExtendedLineEdit(QWidget *parent)
    : QWidget(parent)
    , parent(parent)
{
    setupWidget();
}

bool ExtendedLineEdit::eventFilter(QObject *obj, QEvent *event)
{
    Q_UNUSED(obj)
    if (event->type() == QEvent::MouseButtonRelease ||
        event->type() == QEvent::MouseButtonPress ||
        event->type() == QEvent::MouseButtonDblClick)
    {
        lineEdit->setFocus();
    }
    return false;
}

void ExtendedLineEdit::setupWidget()
{
    auto mainLayout = new QBoxLayout(QBoxLayout::Direction::TopToBottom, this);
    this->setLayout(mainLayout);

    lineEdit = new LineEdit(this);
    mainLayout->addWidget(lineEdit);

    showableWidget = new QWidget(parent);
    showableWidget->setAutoFillBackground(true);
    showableWidget->setPalette(QPalette(QPalette::Background, Qt::white));
    showableWidget->hide();

    auto bottomLayout = new QBoxLayout(QBoxLayout::Direction::LeftToRight, showableWidget);
    showableWidget->setLayout(bottomLayout);

    toUppercaseButton = new QPushButton("to uppercase", this);
    toUppercaseButton->installEventFilter(this);
    connect(toUppercaseButton, &QPushButton::clicked,
            this, [&]{
       lineEdit->setText(lineEdit->text().toUpper());
    });

    toLowercaseButton = new QPushButton("to lowercase", this);
    toLowercaseButton->installEventFilter(this);
    connect(toLowercaseButton, &QPushButton::clicked,
            this, [&]{
       lineEdit->setText(lineEdit->text().toLower());
    });

    bottomLayout->addWidget(toUppercaseButton);
    bottomLayout->addWidget(toLowercaseButton);

    connect(lineEdit, &LineEdit::focusIn,
            this, [&]{
            auto size = lineEdit->size();
            auto position = QWidget::mapTo(parent, lineEdit->pos());

            showableWidget->setGeometry(position.x(),
                                        position.y() + size.height(),
                                        size.width(),
                                        40);
            showableWidget->show();

    });

    connect(lineEdit, &LineEdit::focusOut,
            showableWidget, &QWidget::hide);
}

考虑到你在回答问题时付出的巨大努力,我真的有点难过。。。然而,距离我的初衷还有一分钟。我要找的是一个小弹出窗口,当它获得焦点时会显示在行编辑旁边(比如
QCompleter
)。例如,如果将行编辑合并到项目视图中(作为代理),也可以这样做。@Kamajii-没问题,我喜欢在这里写答案。答案略有改变。如果您仍然对解决这个问题感兴趣,您可以在任何地方使用该示例(因为它显然是“原始的”)。