TableWidget clicked() und doubleClicked()



  • Hallo,
    habe bei einem TableWidget folgendes (für mich) seltsames Verhalten:

    connected werden die Signals für clicked() und doubleClicked().
    connect(ui->m_tableMandanten, SIGNAL(itemClicked(QTableWidgetItem *)), this, SLOT(MandantSelected()));
    connect(ui->m_tableMandanten, SIGNAL(itemDoubleClicked(QTableWidgetItem *)), this, SLOT(MandantSelectedForEdit()));

    Folgendermaßen werden die Slots bei einem Doppleclick aufgerufen:

    1. MandantSelected() --> OK!
    2. MandantSelectedForEdit() --> OK!
    3. MandantSelected() --> NOK!

    Beide SLOTS werden jeweils nur einmal connected. Warum wird nach dem doubleClicked() nocheinmal der SLOT für clicked() aufgerufen ?

    QT Versionen() :
    Version 5.13 MSCV2017 unter Windows 8.1
    Version 5.10.1 GCC 64bit unter SuSe Linux (KDE)

    Kann mir jemand dafür eine Erklärung / Abhilfe nennen ?


  • Qt Champions 2018

    @gerhard said in TableWidget clicked() und doubleClicked():

    Warum wird nach dem doubleClicked() nocheinmal der SLOT für clicked() aufgerufen ?

    Weil ein Doppelclick aus zwei einfachen Clicks besteht.


  • Moderators

    @gerhard
    Ich habs jetzt nicht im SourceCode überprüft, aber in der Regel ist die DoubleClick Implementierung folgender maßen.

    Auf dem clicked signal wird geschaut, ob der interne QTimer bereits gestartet ist, wenn nein, dann starte den Timer. Beim nächsten click wird wieder geschaut, ist der Timer aktiv, wird er gestoppt und das double click signal emittiert.



  • @jsulm
    Hallo,
    richtig, 2 clicks ergeben einen doubleClick, aber diese sollten intern in einen click und eine doubleClick aufgelöst werden, das 2. Click Event sollte nicht erfolgen.

    @j-hilk
    Hallo,
    so habe ich es mir auch vorgestellt, aber es erfolgt ein 2. Click Signal nach dem doubleClick Signal, wie ist dies zu erklären ?c


  • Moderators

    @gerhard

    ist anders als ich gedacht habe, clicked wird jedes mal ausgelöst, wenn ein MousePressed signal anliegt

    1058 void QTabBar::mousePressEvent(QMouseEvent *event)
    1959	{
    1960	    Q_D(QTabBar);
    1961	
    1962	    const QPoint pos = event->pos();
    1963	    const bool isEventInCornerButtons = (!d->leftB->isHidden() && d->leftB->geometry().contains(pos))
    1964	                                     || (!d->rightB->isHidden() && d->rightB->geometry().contains(pos));
    1965	    if (!isEventInCornerButtons) {
    1966	        const int index = d->indexAtPos(pos);
    1967	        emit tabBarClicked(index);
    1968	    }
    1969	
    1970	    if (event->button() != Qt::LeftButton) {
    1971	        event->ignore();
    1972	        return;
    1973	    }
    1974	    // Be safe!
    1975	    if (d->pressedIndex != -1 && d->movable)
    1976	        d->moveTabFinished(d->pressedIndex);
    1977	
    1978	    d->pressedIndex = d->indexAtPos(event->pos());
    1979	#if 0 // Used to be included in Qt4 for Q_WS_MAC
    1980	    d->previousPressedIndex = d->pressedIndex;
    1981	#endif
    1982	    if (d->validIndex(d->pressedIndex)) {
    1983	        QStyleOptionTabBarBase optTabBase;
    1984	        optTabBase.init(this);
    1985	        optTabBase.documentMode = d->documentMode;
    1986	        if (event->type() == style()->styleHint(QStyle::SH_TabBar_SelectMouseType, &optTabBase, this))
    1987	            setCurrentIndex(d->pressedIndex);
    1988	        else
    1989	            repaint(tabRect(d->pressedIndex));
    1990	        if (d->movable) {
    1991	            d->dragStartPosition = event->pos();
    1992	        }
    1993	    }
    1994	}
    

    wohin gegen doubleClicked, aus dem Event system kommt:

    
    1611	bool QTabBar::event(QEvent *event)
    1612	{
    1613	    Q_D(QTabBar);
    1614	    if (event->type() == QEvent::HoverMove
    1615	        || event->type() == QEvent::HoverEnter) {
    1616	        QHoverEvent *he = static_cast<QHoverEvent *>(event);
    1617	        if (!d->hoverRect.contains(he->pos())) {
    1618	            QRect oldHoverRect = d->hoverRect;
    1619	            bool cursorOverTabs = false;
    1620	            for (int i = 0; i < d->tabList.count(); ++i) {
    1621	                QRect area = tabRect(i);
    1622	                if (area.contains(he->pos())) {
    1623	                    d->hoverIndex = i;
    1624	                    d->hoverRect = area;
    1625	                    cursorOverTabs = true;
    1626	                    break;
    1627	                }
    1628	            }
    1629	            if (!cursorOverTabs) {
    1630	                d->hoverIndex = -1;
    1631	                d->hoverRect = QRect();
    1632	            }
    1633	            if (he->oldPos() != QPoint(-1, -1))
    1634	                update(oldHoverRect);
    1635	            update(d->hoverRect);
    1636	        }
    1637	        return true;
    1638	    } else if (event->type() == QEvent::HoverLeave) {
    1639	        QRect oldHoverRect = d->hoverRect;
    1640	        d->hoverIndex = -1;
    1641	        d->hoverRect = QRect();
    1642	        update(oldHoverRect);
    1643	        return true;
    1644	#ifndef QT_NO_TOOLTIP
    1645	    } else if (event->type() == QEvent::ToolTip) {
    1646	        if (const QTabBarPrivate::Tab *tab = d->at(tabAt(static_cast<QHelpEvent*>(event)->pos()))) {
    1647	            if (!tab->toolTip.isEmpty()) {
    1648	                QToolTip::showText(static_cast<QHelpEvent*>(event)->globalPos(), tab->toolTip, this);
    1649	                return true;
    1650	            }
    1651	        }
    1652	#endif // QT_NO_TOOLTIP
    1653	#if QT_CONFIG(whatsthis)
    1654	    } else if (event->type() == QEvent::QueryWhatsThis) {
    1655	        const QTabBarPrivate::Tab *tab = d->at(d->indexAtPos(static_cast<QHelpEvent*>(event)->pos()));
    1656	        if (!tab || tab->whatsThis.isEmpty())
    1657	            event->ignore();
    1658	        return true;
    1659	    } else if (event->type() == QEvent::WhatsThis) {
    1660	        if (const QTabBarPrivate::Tab *tab = d->at(d->indexAtPos(static_cast<QHelpEvent*>(event)->pos()))) {
    1661	            if (!tab->whatsThis.isEmpty()) {
    1662	                QWhatsThis::showText(static_cast<QHelpEvent*>(event)->globalPos(),
    1663	                                     tab->whatsThis, this);
    1664	                return true;
    1665	            }
    1666	        }
    1667	#endif // QT_CONFIG(whatsthis)
    1668	#ifndef QT_NO_SHORTCUT
    1669	    } else if (event->type() == QEvent::Shortcut) {
    1670	        QShortcutEvent *se = static_cast<QShortcutEvent *>(event);
    1671	        for (int i = 0; i < d->tabList.count(); ++i) {
    1672	            const QTabBarPrivate::Tab *tab = &d->tabList.at(i);
    1673	            if (tab->shortcutId == se->shortcutId()) {
    1674	                setCurrentIndex(i);
    1675	                return true;
    1676	            }
    1677	        }
    1678	#endif
    1679	    } else if (event->type() == QEvent::MouseButtonDblClick) { // ### fixme Qt 6: move to mouseDoubleClickEvent(), here for BC reasons.
    1680	        const QPoint pos = static_cast<const QMouseEvent *>(event)->pos();
    1681	        const bool isEventInCornerButtons = (!d->leftB->isHidden() && d->leftB->geometry().contains(pos))
    1682	                                            || (!d->rightB->isHidden() && d->rightB->geometry().contains(pos));
    1683	        if (!isEventInCornerButtons)
    1684	            emit tabBarDoubleClicked(tabAt(pos));
    1685	    } else if (event->type() == QEvent::Move) {
    1686	        d->updateMacBorderMetrics();
    1687	        return QWidget::event(event);
    1688	
    1689	#if QT_CONFIG(draganddrop)
    1690	    } else if (event->type() == QEvent::DragEnter) {
    1691	        if (d->changeCurrentOnDrag)
    1692	            event->accept();
    1693	    } else if (event->type() == QEvent::DragMove) {
    1694	        if (d->changeCurrentOnDrag) {
    1695	            const int tabIndex = tabAt(static_cast<QDragMoveEvent *>(event)->pos());
    1696	            if (isTabEnabled(tabIndex) && d->switchTabCurrentIndex != tabIndex) {
    1697	                d->switchTabCurrentIndex = tabIndex;
    1698	                if (d->switchTabTimerId)
    1699	                    killTimer(d->switchTabTimerId);
    1700	                d->switchTabTimerId = startTimer(style()->styleHint(QStyle::SH_TabBar_ChangeCurrentDelay));
    1701	            }
    1702	            event->ignore();
    1703	        }
    1704	    } else if (event->type() == QEvent::DragLeave || event->type() == QEvent::Drop) {
    1705	        d->killSwitchTabTimer();
    1706	        event->ignore();
    1707	#endif
    1708	    }
    1709	    return QWidget::event(event);
    1710	}
    

    clicked ist also total unabhängig von double clicked -> clicked signal -> double clicked ->clicked



  • @j-hilk
    Hallo,
    wir sind beim TableWidget, nicht beim TabBar!


  • Moderators

    @gerhard Richtig, mein Fehler



  • Hallo,

    das Problem hat sich gelöst.
    Augenscheinlich wurde innerhalb der Abarbeitung der Signals etwas am Zustand des TableWidgets geändert, wodurch das clicked() zusätzlich ausgelöst wurde.



  • Hallo,
    hier nochmals kurz eine Darstellung des Sachverhaltes:
    Tatsächlich wird das doubleClicked Signal in eine Abfolge von clicked() - doubleClicked() - clicked() Signal aufglöst, sofern innerhalb der entsprechenden Slots nichts am Zustand des TableWidgets geändert wird.
    Wird jedoch wie in meinem Fall innerhalb der Abarbeitung des doubleClicked() das entsprechende TableWidget disabled, so entfällt das letzte clicked() Signal.


Log in to reply