如何完全清除 QTreeWidget 选择?

How do I fully clear a QTreeWidget selection?

我正在尝试制作一个具有多个 QTreeWidget 的程序。但是,我的目标是一次只允许选择 1 个 QTreeWidget 行。

我已经设法使用 currentItemChanged 信号实现了这一点,但它出错了。

要重现问题...

  1. Select 一个 QTreeWidget 上的一行。
  2. Select OTHER QTreeWidget 上的另一行。此时所有 QTreeWidget 选择都被删除(太棒了,这正是我想要的)。
  3. Select 与第 1 步相同的 QTreeWidget 上的同一行。此时它已经出现错误,因为您之前的选择仍然被选择...

我是否不正确地清除了选择,如果是,我应该如何清除它?

这是问题的图片。

这是我的来源...

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QTreeWidget>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private slots:
    void OnSelectedTreeValueChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous);

private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QDebug>
#include <QTreeWidget>
#include <QTreeWidgetItem>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    ui->treeWidget->expandAll();
    ui->treeWidget->setItemsExpandable(false);

    ui->treeWidget_2->expandAll();
    ui->treeWidget_2->setItemsExpandable(false);

    connect(ui->treeWidget, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), this, SLOT(OnSelectedTreeValueChanged(QTreeWidgetItem*,QTreeWidgetItem*)));
    connect(ui->treeWidget_2, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), this, SLOT(OnSelectedTreeValueChanged(QTreeWidgetItem*,QTreeWidgetItem*)));
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::OnSelectedTreeValueChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous)
{
    if(current->childCount() == 0)
    {
        // Get OUR parrent item.
        QTreeWidgetItem* parent_item = current->parent();

        // Go through each tree & deselect selections.
        QObject* sender_object = sender();
        QTreeView* sender_tree = static_cast<QTreeView*>(sender_object);
        const QList<QTreeWidget*> children = ui->TreeScrollAreaContents->findChildren<QTreeWidget*>(QRegularExpression(), Qt::FindDirectChildrenOnly);
        for(QList<QTreeWidget*>::const_iterator it = children.begin(); it != children.end(); it++)
        {
            QTreeWidget* child_tree = *it;
            if(sender_tree != child_tree)
            {
                child_tree->clearSelection();
                child_tree->clearFocus();
            }
        }
    }
}

mainwindow.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>400</width>
    <height>176</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralWidget">
   <widget class="QScrollArea" name="TreeScrollArea">
    <property name="geometry">
     <rect>
      <x>0</x>
      <y>0</y>
      <width>401</width>
      <height>171</height>
     </rect>
    </property>
    <property name="widgetResizable">
     <bool>true</bool>
    </property>
    <widget class="QWidget" name="TreeScrollAreaContents">
     <property name="geometry">
      <rect>
       <x>0</x>
       <y>0</y>
       <width>399</width>
       <height>169</height>
      </rect>
     </property>
     <property name="styleSheet">
      <string notr="true">#TreeScrollAreaContents {
    background-color: #000000;
}</string>
     </property>
     <layout class="QGridLayout" name="TreeScrollAreaGridLayout">
      <property name="leftMargin">
       <number>0</number>
      </property>
      <property name="rightMargin">
       <number>0</number>
      </property>
      <item row="0" column="0">
       <widget class="QTreeWidget" name="treeWidget">
        <property name="sizePolicy">
         <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
          <horstretch>0</horstretch>
          <verstretch>0</verstretch>
         </sizepolicy>
        </property>
        <property name="sizeAdjustPolicy">
         <enum>QAbstractScrollArea::AdjustToContents</enum>
        </property>
        <column>
         <property name="text">
          <string>1</string>
         </property>
        </column>
        <item>
         <property name="text">
          <string>Item 1</string>
         </property>
         <item>
          <property name="text">
           <string>Sub Item 1</string>
          </property>
         </item>
         <item>
          <property name="text">
           <string>Sub Item 2</string>
          </property>
         </item>
         <item>
          <property name="text">
           <string>Sub Item 3</string>
          </property>
         </item>
         <item>
          <property name="text">
           <string>Sub Item 4</string>
          </property>
         </item>
        </item>
       </widget>
      </item>
      <item row="0" column="1">
       <widget class="QTreeWidget" name="treeWidget_2">
        <property name="sizePolicy">
         <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
          <horstretch>0</horstretch>
          <verstretch>0</verstretch>
         </sizepolicy>
        </property>
        <property name="sizeAdjustPolicy">
         <enum>QAbstractScrollArea::AdjustToContents</enum>
        </property>
        <column>
         <property name="text">
          <string>1</string>
         </property>
        </column>
        <item>
         <property name="text">
          <string>Item 1</string>
         </property>
         <item>
          <property name="text">
           <string>Sub Item 1</string>
          </property>
         </item>
         <item>
          <property name="text">
           <string>Sub Item 2</string>
          </property>
         </item>
         <item>
          <property name="text">
           <string>Sub Item 3</string>
          </property>
         </item>
         <item>
          <property name="text">
           <string>Sub Item 4</string>
          </property>
         </item>
        </item>
       </widget>
      </item>
     </layout>
    </widget>
   </widget>
  </widget>
 </widget>
 <layoutdefault spacing="6" margin="11"/>
 <resources/>
 <connections/>
</ui>

main.cpp

#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}

一件事是 currentItem,另一件事是选择的项目,而不是使用 currentItemChanged 信号,您必须使用信号 itemSelectionChanged。当使用 clearSelection() 时,相应的 QTreeWidget 也会发出信号 itemSelectionChanged,这可能会产生无限循环,解决方案是使用 blockSignals().

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QTreeWidgetItem>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
private:
    Ui::MainWindow *ui;
private slots:
    void OnSelectedTreeValueChanged(); // remove arguments
};

#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QTreeWidget>
#include <QTreeWidgetItem>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    const QList<QTreeWidget*> childrens = ui->TreeScrollAreaContents->findChildren<QTreeWidget*>(QRegularExpression(), Qt::FindDirectChildrenOnly);
    for(QTreeWidget* child_tree: childrens)
    {
        child_tree->expandAll();
        child_tree->setItemsExpandable(false);
        connect(child_tree, &QTreeWidget::itemSelectionChanged, this, &MainWindow::OnSelectedTreeValueChanged);
    }
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::OnSelectedTreeValueChanged()
{
    QTreeWidget *sender_tree = qobject_cast<QTreeWidget *>(sender());

    if(sender_tree->currentItem()->childCount() == 0)
    {
        const QList<QTreeWidget*> childrens = ui->TreeScrollAreaContents->findChildren<QTreeWidget*>(QRegularExpression(), Qt::FindDirectChildrenOnly);
        for(QTreeWidget* child_tree: childrens)
        {
            if(sender_tree != child_tree)
            {
                child_tree->blockSignals(true);
                child_tree->clearSelection();
                child_tree->blockSignals(false);
            }
        }
    }
}

注:

我会解释为什么你的方法不起作用,你正在使用 currentItem 作为算法的基本元素,但是 currentItem 可能被选中或没有,clearSelection不影响 currentItem.