QT5.15.2 + linux + 3588下在QWidget中添加一个QDockWidget,在QDockWidget中添加QTreeWidget,使用QTreeWidget的函数setItemWidget为每一个节点添加一个关联的widget(QPushButton 用于上移下移节点),会出现widget捕获不到enter和leave事件(不是所有节点完全捕捉不到,是无序的个别的)
特别说明:如果将QTreeWidget 直接放在QWidget中不存在此现象,QDockWidget中仅有一个QTreeWidget无其他特别内容
添加树节点的代码
void Widget::initTree()
{
QString soluDispName("cesi11");
QTreeWidgetItem* parentItem = new QTreeWidgetItem(ui->treeWidgetSolution, QStringList() << soluDispName);
parentItem->setToolTip(RECENT_TREE_COL, soluDispName);
ui->treeWidgetSolution->addTopLevelItem(parentItem);
int index = 0;
int allSize = 15;
for(int k = 0; k < 15; k++)
{
QString tagName = QString::number(k);
QString sceneDispName = tagName;
QTreeWidgetItem* childItem = new QTreeWidgetItem(parentItem, QStringList() << sceneDispName);
childItem->setToolTip(RECENT_TREE_COL, sceneDispName);
// 子节点增加上移下移
CTreeItemWidget* opWidget = new CTreeItemWidget(childItem);
opWidget->setDelHide();
opWidget->setIndex(index++, allSize);
parentItem->addChild(childItem);
ui->treeWidgetSolution->setItemWidget(childItem, 0, opWidget);
}
ui->treeWidgetSolution->collapseAll();
}
自定义widget相关代码
```c++
CTreeItemWidget::CTreeItemWidget(QTreeWidgetItem* item, QWidget* parent)
: QWidget(parent), relation_item_(item)
, current_index_(0), all_size_(0), del_is_show_(true)
{
// setAttribute(Qt::WA_TranslucentBackground);
// setStyleSheet("background-color: transparent;");
QSize btnSize(30, 30);
QString qss;//"QPushButton:disabled{color: gray;}QPushButton:enabled{color: white;}";
btn_up_ = new QPushButton(u8"↑");
btn_up_->setFixedSize(btnSize);
//btn_up_->setFlat(true); // 3588 上按钮背景是黑色,网上查找使用该函数后正常
//btn_up_->setStyleSheet(qss);
btn_down_ = new QPushButton(u8"↓");
btn_down_->setFixedSize(btnSize);
//btn_down_->setFlat(true);
//btn_down_->setStyleSheet(qss);
btn_del_ = new QPushButton(u8"×");
btn_del_->setFixedSize(btnSize);
//btn_del_->setFlat(true);
// btn_del_->setStyleSheet(qss);
QHBoxLayout* hLayout = new QHBoxLayout();
hLayout->addItem(new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Expanding));
hLayout->addWidget(btn_up_);
hLayout->addWidget(btn_down_);
hLayout->addWidget(btn_del_);
//hLayout->setMargin(0);
// hLayout->setSpacing(0);
setLayout(hLayout);
btn_up_->hide();
btn_down_->hide();
btn_del_->hide();
//this->hide();
//connect(btn_up_, SIGNAL(clicked(bool)), this, SLOT(slot_opList()));
// connect(btn_down_, SIGNAL(clicked(bool)), this, SLOT(slot_opList()));
// connect(btn_del_, SIGNAL(clicked(bool)), this, SLOT(slot_opList()));
}
CTreeItemWidget::~CTreeItemWidget()
{
}
void CTreeItemWidget::setDelHide()
{
del_is_show_ = false;
if(btn_del_ != NULL)
btn_del_->hide();
}
void CTreeItemWidget::slot_opList()
{
const QPushButton* opBtn = dynamic_cast<QPushButton*>(sender());
if(opBtn == btn_up_)
emit signal_upItem(relation_item_);
else if(opBtn == btn_down_)
emit signal_downItem(relation_item_);
else if((del_is_show_) && (opBtn == btn_del_))
emit signal_delItem(relation_item_);
}
void CTreeItemWidget::enterEvent(QEvent* event)
{
if(NULL != relation_item_)
{
qDebug() << "enter CTreeItemWidget::enterEvent:" << relation_item_->text(0);
}
if(btn_up_ != NULL)
{
btn_up_->show();
btn_up_->setEnabled(current_index_ > 0);
}
if(btn_down_ != NULL)
{
btn_down_->show();
btn_down_->setEnabled(current_index_ < all_size_ - 1);
}
if((del_is_show_) && (btn_del_ != NULL))
{
btn_del_->show();
}
QWidget::enterEvent(event);
}
void CTreeItemWidget::leaveEvent(QEvent* event)
{
if(NULL != relation_item_)
{
qDebug() << "enter CTreeItemWidget::leaveEvent:" << relation_item_->text(0);
}
if(btn_up_ != NULL)
{
btn_up_->hide();
}
if(btn_down_ != NULL)
{
btn_down_->hide();
}
if((del_is_show_) && (btn_del_ != NULL))
{
btn_del_->hide();
}
QWidget::leaveEvent(event);
}

请各位不吝赐教,万分感谢
交互问题?
采用chatgpt:
根据提供的信息和代码,您似乎面临一个问题,即当将鼠标悬停在 QTreeWidget 内的小部件上时,自定义 CTreeItemWidget 类的 EnterEvent 和 LeaveEvent 不会一致触发。
此行为可能是由于小部件的堆叠顺序以及事件在小部件层次结构中的传播方式造成的。 为了确保您的自定义小部件正确捕获事件,您可以尝试以下步骤:
为 CTreeItemWidget 启用鼠标跟踪。 这将确保即使没有按下鼠标按钮,小部件也会接收鼠标移动事件:
CTreeItemWidget::CTreeItemWidget(QTreeWidgetItem* item, QWidget* parent)
: QWidget(parent), relation_item_(item)
, current_index_(0), all_size_(0), del_is_show_(true)
{
// ...
setMouseTracking(true); // Enable mouse tracking
// ...
}
将 CTreeItemWidget 设置为 QTreeWidget 项的视口,因为这可以改善自定义小部件的事件处理:
ui->treeWidgetSolution->setItemWidget(childItem, 0, opWidget);
ui->treeWidgetSolution->viewport()->setMouseTracking(true); // Set the viewport mouse tracking
如果问题仍然存在,请考虑为 CTreeItemWidget 安装事件过滤器以直接拦截事件:
CTreeItemWidget::CTreeItemWidget(QTreeWidgetItem* item, QWidget* parent)
: QWidget(parent), relation_item_(item)
, current_index_(0), all_size_(0), del_is_show_(true)
{
// ...
// Install an event filter to intercept events
installEventFilter(this);
// ...
}
bool CTreeItemWidget::eventFilter(QObject* obj, QEvent* event)
{
if (obj == this)
{
if (event->type() == QEvent::Enter)
{
qDebug() << "CTreeItemWidget Enter:" << relation_item_->text(0);
// Handle the enter event here
// ...
return true; // Event handled, no further processing by this widget
}
else if (event->type() == QEvent::Leave)
{
qDebug() << "CTreeItemWidget Leave:" << relation_item_->text(0);
// Handle the leave event here
// ...
return true; // Event handled, no further processing by this widget
}
}
return QWidget::eventFilter(obj, event); // For other events, perform default handling
}
通过使用事件过滤器,您可以直接拦截 Enter 和 Leave 事件并在 CTreeItemWidget 本身内处理它们。
如果上述步骤未能解决问题,您可能需要检查是否有任何其他事件处理程序或样式可能会干扰 CTreeItemWidget 的事件传播。
是因为在子窗体内捕获事件后,则父窗体的捕获事件不再生效,若想事件生效需要在enterevent和leaveevent中加入
QWidget::leaveEvent(event);
本文简要介绍一个知识点,如题所示,就是如何给QTreeWidgetItem添加自定义数据。两种方法:
Qt QTableWidget类方法setItem()bug问题解决
可以参考这个例子
https://blog.csdn.net/weixin_42108411/article/details/107647746