Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

QWidget once lose focus, it cannt get the focus again



  • I defined a Widget.
    It is like this.

    TopLevel::TopLevel(QWidget* parent) : QWidget(parent,
    Qt::Tool | Qt::WindowStaysOnTopHint
    | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint)
    {
    setAttribute(Qt::WA_TranslucentBackground, true);
    QVBoxLayout *lay = new QVBoxLayout(this);
    lay->setMargin(0);
    lay->setSpacing(0);
    setLayout(lay);

    setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
    

    }

    void TopLevel::setCenterWidget(QWidget* widget)
    {
    if (m_widget) {
    m_widget->removeEventFilter(this);
    layout()->removeWidget(m_widget);
    }
    m_widget = widget;
    widget->installEventFilter(this);
    widget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
    layout()->addWidget(widget);
    }

    And I defined a QDeclarativeView.
    Then a call the function setCenterWidget(QDeclarativeView).
    after I open a application, the application full of the screen. The Widget that I defined can't get the focus.
    There was no response to my dragging or clicking.


  • Lifetime Qt Champion

    Hi,

    @chris_rookie said in QWidget once lose focus, it cannt get the focus again:

    widget->installEventFilter(this);

    Are you sure your event filter isn't breaking things ?
    In any case, you should try first without it.

    By the way, after your call to removeWidget, shouldn't you delete the widget pointed to by m_widget ? Because otherwise you are just going to use memory for nothing unless you manage that widget lifetime somewhere else.



  • @SGaist
    Hi.
    I tried as this.

    void TopLevel::setCenterWidget(QWidget* widget)
    {
    if (m_widget) {
    m_widget->removeEventFilter(this);
    layout()->removeWidget(m_widget);
    delete m_widget;
    m_widget = NULL;
    }
    m_widget = widget;
    //widget->installEventFilter(this);
    widget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
    layout()->addWidget(widget);
    layout()->activate();//?
    }

    but The problem still there.

    I put a QDeclarativeView in it, Does it matter?


  • Lifetime Qt Champion

    My main point was: what do you do in your event filter ?



  • @SGaist
    TopLevel::TopLevel(QWidget* parent) : QWidget(parent,
    Qt::Tool | Qt::WindowStaysOnTopHint
    | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint)
    {
    setAttribute(Qt::WA_TranslucentBackground, true);
    QVBoxLayout *lay = new QVBoxLayout(this);
    lay->setMargin(0);
    lay->setSpacing(0);
    setLayout(lay);

    setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
    

    }

    void TopLevel::setCenterWidget(QWidget* widget)
    {
    if (m_widget) {
    m_widget->removeEventFilter(this);
    layout()->removeWidget(m_widget);
    }
    m_widget = widget;
    widget->installEventFilter(this);
    widget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
    layout()->addWidget(widget);
    layout()->activate();//?
    }

    void TopLevel::showEvent(QShowEvent* event)
    {
    QWidget::showEvent(event);
    setMask(rect());
    updateLocation();
    }

    bool TopLevel::eventFilter(QObject object, QEvent event)
    {
    if (object == m_widget.data() &&
    event->type() == QEvent::Resize) {
    setMinimumSize(m_widget->sizeHint());
    setMaximumSize(m_widget->sizeHint());
    }
    return QObject::eventFilter(object, event);
    }**

    void TopLevel::resizeEvent(QResizeEvent* resize)
    {
    QWidget::resizeEvent(resize);
    setMask(rect());
    updateLocation();
    }

    void TopLevel::setSpotRect(const QRect& rect)
    {
    m_spotRect = rect;
    updateLocation();
    }

    void TopLevel::updateLocation()
    {
    if (this->isVisible() == false)
    return;

    QRect screenRect = QApplication::desktop()->screenGeometry(QPoint(m_spotRect.x(), m_spotRect.y()));
    int x;
    x = qMin(m_spotRect.x(), screenRect.x() + screenRect.width() - width());
    x = qMax(x, screenRect.x());
    int oy = m_spotRect.y() + m_spotRect.height();
    int y = oy + 10;
    if (y < screenRect.y()) {
        y = screenRect.y();
    }
    
    if (y > screenRect.y() + screenRect.height()) {
        y = screenRect.height();
    }
    
    if (y + height() > screenRect.y() + screenRect.height()) {
        /// minus 20 to make preedit bar never overlap the input context
        y = oy - (height() + ((m_spotRect.height() == 0)?20:(m_spotRect.height() + 10)));
    }
    
    QPoint p(x, y);
    if (p != pos())
        move(p);
    

    }

    I put whole class here.
    The eventFilter function didn't do much work. just filter QEvent::Resize.


  • Lifetime Qt Champion

    @chris_rookie said in QWidget once lose focus, it cannt get the focus again:

    bool TopLevel::eventFilter(QObject object, QEvent event)
    {
    if (object == m_widget.data() &&
    event->type() == QEvent::Resize) {
    setMinimumSize(m_widget->sizeHint());
    setMaximumSize(m_widget->sizeHint());
    }
    return QObject::eventFilter(object, event);
    }

    That last line has one issue: you are not calling the base class (which is QWidget in your case) implementation thus bypassing everything that it might be handling in there.



  • @SGaist
    Before I put my whole class here.
    I also had try

    return object->eventFilter(event);

    or

    return false;

    I got the same result.
    .....

    It behaves like this.
    cfdda17e-3f44-48e6-a367-2e914873e614-image.png
    This is my widget. when it on the desktop, I can drag it or click it.
    After I open a folder, like this.
    2f32196c-f3ce-46f6-9982-97ac40bd6691-image.png
    The folder below my widget. I cannt drag it or click it.


  • Lifetime Qt Champion

    That's not what I meant. You should call QWidget::eventFilter and not QObject::eventFilter.

    In any case, why are you implementing it like that ? It seems you should rather call setFixedSize when you call setCenterWidget.



  • @SGaist

    if (object == m_widget.data() &&
    event->type() == QEvent::Resize) {
    setMinimumSize(m_widget->sizeHint());
    setMaximumSize(m_widget->sizeHint());
    }

    Because I used it in other place.
    In that case, I put a QDeclarativeView in it.
    The QDeclarativeView's size would be changed.

    As you said, I tried
    return QWidget::eventFilter(object, event);

    and

    remove the function eventFilter and installEventFilter.

    but it still does not work.
    When I opened the folder, the folder under my widget. The folder get the focus.
    Even I clicked my Widget, The focus still on the folder.
    After I closed the folder or made the folder smaller(doesnt under my widget), my widget can get focus again.


  • Lifetime Qt Champion

    Sorry but your explanation are not really clear.

    You should:

    • Provide a minimal compilable example that shows the issue
    • Explain your setup exactly (Qt version, Linux distribution, Desktop Environment, etc.)
    • Explain how you are using your application
    • Explain what you are doing to trigger the bug

    You might think you did but with there's a lack of details that makes it so we don't know whether you are all doing that within your application or doing some other stuff with your file manager.



  • @SGaist
    Hi.
    I execute my program on a little-known linux os.
    Then I let my program executed on ubuntu 17.
    The qt's version all 4.8.7.
    On ubuntu 17 is ok.
    I would find out the differnce of the two systems.
    Thanks for your answer very much and Happy Chinese New Year.


Log in to reply