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:
- MandantSelected() --> OK!
- MandantSelectedForEdit() --> OK!
- 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 ?
-
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:
- MandantSelected() --> OK!
- MandantSelectedForEdit() --> OK!
- 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 ?
@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.
-
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:
- MandantSelected() --> OK!
- MandantSelectedForEdit() --> OK!
- 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 ?
@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.
-
@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 -
@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 ?cist 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
-
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
-
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.