c++ - 如何将 QTableWidget 添加到 QTreeWidget 中,但作为 QTreeWidgetItem

标签 c++ qt qt5 qtreewidget qtreewidgetitem

我正在设计一个主要界面,但在如何将 QTableWidget 添加到 QTreeWidget 中但作为 QTreeWidgetItem 时遇到了问题。为了节省大家的时间并提供最好的信息,下面是一个完全复制我遇到的问题的示例。我尽量简洁:

  1. 在我目前使用的不正确的小用户界面下方: cor
  1. 在界面下方我正在努力实现: ok

如您所见,我正在尝试在树中插入一个额外的小部件。 请参阅下面的界面最终外观: final

准备示例并在小范围内真正复制问题真的很困难,所以如果有任何疑问,请告诉我:

主窗口.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QSettings>
#include <QTreeWidget>
#include <QComboBox>
#include <QGraphicsView>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QWidget>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QObject>

#include "gaussianfilter.h"

class ImgPreProc;
class PreProcessing;
class MyMainWindow;

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class ImgPreProc : public QObject {
    Q_OBJECT
public:
    explicit ImgPreProc(QSettings *Settings = new QSettings("default", QSettings::IniFormat), QMainWindow *UserParent = nullptr);
    MyMainWindow *MainWindow;
    PreProcessing *PreProc;

public slots:
    void OpenWindow();
private:
    QWidget *parent;
    bool mainWinOpen;
    bool loadProp;
};

class MyMainWindow : public QMainWindow {
    Q_OBJECT
public:
    explicit MyMainWindow(QWidget *parent = nullptr);
    ~MyMainWindow();
};

class MainWindow : public QMainWindow {
    Q_OBJECT
public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void OpenPreProcessingWindow(void) {
        mImgPreProc->OpenWindow();
    }

private:
    Ui::MainWindow *ui;
    QSettings *Settings;
    ImgPreProc *mImgPreProc;
};

class PreProcessing : public QObject {
    Q_OBJECT
public:
    PreProcessing(QSettings *Settings = new QSettings(QString("default"), QSettings::IniFormat));
    ~PreProcessing(void);
    void CreateWidgets(QWidget *UserParent = nullptr);
    QWidget *MainWidget;
    Filter *filter;

private slots:
    void addFilter();
    int addFilterItem(std::string FilterType = "?");

private:
    QWidget *parent;
    QTreeWidget *mainTree;
    QComboBox *filterChoose;
    QTreeWidget* getTree(void){
        return mainTree;
    }
};

#endif // MAINWINDOW_H

主窗口.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "gaussianfilter.h"
#include <QTabWidget>
#include <QStatusBar>
#include <QLabel>
#include <QString>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    mImgPreProc = new ImgPreProc(Settings);
    QAction *showPreProc = new QAction(this);
    showPreProc->setIcon(QIcon(QPixmap(QString((":/images/gauss.png")))));
    ui->mainToolBar->addAction(showPreProc);
    connect(showPreProc,SIGNAL(triggered()),this,SLOT(OpenPreProcessingWindow()));
}

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

ImgPreProc::ImgPreProc(QSettings *set, QMainWindow *UserParent) {
    mainWinOpen = false;
    loadProp = false;
    parent = UserParent;
    PreProc = new PreProcessing(set);
}

void ImgPreProc::OpenWindow() {
    loadProp = true;
    MainWindow = new MyMainWindow(parent);
    QWidget *centralWidget = new QWidget(MainWindow);
    MainWindow->setCentralWidget(centralWidget);
    QVBoxLayout *MainLayout = new QVBoxLayout();
    centralWidget->setLayout(MainLayout);

    QStatusBar *statusbar = new QStatusBar(MainWindow);
    MainWindow->setStatusBar(statusbar);
    QTabWidget *mainTab = new QTabWidget(MainWindow);
    MainLayout->addWidget(mainTab);
    PreProc->CreateWidgets(MainWindow);
    mainTab->addTab(PreProc->MainWidget, QString("PreProcessing"));
    MainWindow->show();
}

MyMainWindow::MyMainWindow(QWidget *parent){(void) parent;}
MyMainWindow::~MyMainWindow(){}

PreProcessing::PreProcessing(QSettings *Settings) : QObject() {
    mainTree = nullptr;
    filter = new Filter("Filter Node");
    (void) Settings;
}

PreProcessing::~PreProcessing(){}
void PreProcessing::CreateWidgets(QWidget *UserParent)
{
    parent = UserParent;
    MainWidget = new QWidget(parent);
    QVBoxLayout *MainLayout = new QVBoxLayout(MainWidget);
    MainWidget->setLayout(MainLayout);

        QHBoxLayout *filterLayout = new QHBoxLayout();
        MainLayout->addLayout(filterLayout);
        filterLayout->setAlignment(Qt::AlignLeft);

            filterChoose = new QComboBox(MainWidget);
            for(int x = 0; x < (int)filter->NameOfFilter.size(); x++){
                filterChoose->addItem(filter->NameOfFilter.at(x).c_str());
            }
            filterLayout->addWidget(new QLabel("Filter"));
            filterLayout->addWidget(filterChoose);

        QToolBar *toolbar = new QToolBar(MainWidget);
        MainLayout->addWidget(toolbar);
        toolbar->addAction("Insert",this,SLOT(addFilter()));

        mainTree = new QTreeWidget(MainWidget);
        QStringList headerList;
        headerList.append("Type Of Filter");
        headerList.append("Iteration");
        headerList.append("Save Configuration?");

        mainTree->setColumnCount(headerList.size());
        mainTree->setHeaderLabels(headerList);
        MainLayout->addWidget(mainTree);
        filter->setTree(mainTree);
        for(int x = 0; x < (int)filter->ItemFilter.size(); x++){
            filter->ItemFilter.at(x).CreateWidgets(parent);
        }
}

void PreProcessing::addFilter() {
    int index = addFilterItem(filterChoose->currentText().toStdString());
    filter->ItemFilter.at(index).CreateWidgets(parent);
}

int PreProcessing::addFilterItem(std::string FilterType) {
    if(FilterType == filter->NameOfFilter.at(Filter::GAUSSIAN)){
        filter->addFilterGauss();
    }
    return ((int)filter->ItemFilter.size() - 1);
}

高斯过滤器.h

#ifndef GAUSSIANFILTER_H
#define GAUSSIANFILTER_H
#include <QObject>
#include <QTreeWidget>
#include <QTreeWidgetItem>

class FilterItem;
class Filter : public QObject{
    Q_OBJECT

public:
    enum{ GAUSSIAN, OTHER };
    Filter(std::string Name, QTreeWidget *userTree = new QTreeWidget());
    ~Filter();
    std::vector<std::string>NameOfFilter;
    std::vector<FilterItem>ItemFilter;

    void setTree(QTreeWidget *userTree){
        tree = userTree;
    }

    QTreeWidget* getTree(void){
        return tree;
    }

    int getItemCount(void){
        return ((int)ItemFilter.size());
    }

    QTreeWidget *tree;

private:
    std::string filterName;

public slots:
    void addFilterGauss(int width = 3, int height = 3, int iter = 1, bool ok = true);
};

class GaussianFilter : public QObject{
    Q_OBJECT

public:
    GaussianFilter(Filter *UserFilter, int width = 3, int height = 3, int iter = 1, bool ok = true);
    void CreateFilterWidgets(QWidget *parent);
    void CreateAdvancedFilterWidgets(QWidget *parent);

    ~GaussianFilter();

    QWidget *type,*iteration,*execute, *type2;
    void setRectHeight(int x){rectH = x;}
    int getRectHeight(void){return rectH;}
    void setRectWidth(int x){rectW = x;}
    int getRectWidth(void){return rectW;}
    void setIteration(int x){gaussItera = x;}
    int getIteration(void){return gaussItera;}
    void setExecute(bool x){gaussOk = x;}
    bool getExecute(void){return gaussOk;}

private:
    Filter *filter;
    int rectH, rectW, gaussItera;
    bool gaussOk;
    QTreeWidgetItem *otherItem;

private slots:
    void changeRectHeight(int x){setRectHeight(x);}
    void changeIteration(int x){setIteration(x);}
    void changeExecute(bool x){setExecute(x);}
};

class FilterItem{

public:
    explicit FilterItem(Filter *userFilter);
    void CreateWidgets(QWidget *parent);
    void CreateAdvancedWidgets(QWidget *parent);
    GaussianFilter *gaussian;

    int getFilterType(void){return filterType;}
    void determFilterType(int x){ filterType = x;}

    std::string getFilterTypeStr(void){
        if(filterType != (-1)){
            return filter->NameOfFilter.at(filterType);
        }
        else{
            return "\0";
        }
    }

    ~FilterItem();

private:
    Filter *filter;
    QWidget *parent;
    QTreeWidget *tree;
    QTreeWidgetItem *item;
    QTreeWidgetItem *advancedChildItem;
    QList<QTreeWidgetItem *> options;
    int filterType;
    QString iconPath;
    QTreeWidgetItem *childItem;
    QTreeWidgetItem *otherItem;


};
#endif // GAUSSIANFILTER_H

高斯过滤器.cpp

#include "gaussianfilter.h"
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QToolBar>
#include <QLabel>
#include <QSpinBox>
#include <QCheckBox>
#include <QComboBox>
#include <QPainter>
#include <QTableWidget>
#include <QPushButton>

Filter::Filter(std::string Name, QTreeWidget *userTree) {
    filterName = Name;
    ItemFilter.clear();

    for(int x = 0; x < OTHER; x++){
        NameOfFilter.push_back(std::string());
    }
    // Here we will add the filter inside the QComboBox
    NameOfFilter.at(GAUSSIAN) = "Gaussian";
    tree = userTree;
}

Filter::~Filter(){}

void Filter::addFilterGauss(int width, int height, int iter, bool ok) {
    ItemFilter.push_back(FilterItem(this));
    ItemFilter.at(((int)ItemFilter.size() - 1)).gaussian = new GaussianFilter(this,width,height,iter,ok);
    ItemFilter.at(((int)ItemFilter.size() - 1)).determFilterType(GAUSSIAN);
}

GaussianFilter::GaussianFilter(Filter *UserFilter, int width, int height, int iter, bool ok) {
    filter = UserFilter;
    setRectWidth(width);
    setRectHeight(height);
    setIteration(iter);
    setExecute(ok);
}

void GaussianFilter::CreateFilterWidgets(QWidget *parent) {
    type = new QWidget(parent);
    iteration = new QWidget(parent);
    execute = new QWidget(parent);

    QGridLayout *group = new QGridLayout(type);
    type->setLayout(group);
    QSpinBox *width = new QSpinBox(parent);
    width->setSingleStep(2);
    width->setValue(getRectWidth());
//    connect(width,SIGNAL(valueChanged(int)),this,SLOT(changeRectWidth(int)));
    width->setRange(3,33);
    group->addWidget(new QLabel("Search"),0,0,1,1,Qt::AlignLeft);
    group->addWidget(width,0,1,1,1,Qt::AlignLeft);
    group->addWidget(new QLabel("pix"),0,2,1,1,Qt::AlignLeft);
    QHBoxLayout *iter = new QHBoxLayout(iteration);
    iteration->setLayout(iter);

    QSpinBox *It = new QSpinBox(parent);
    iter->addWidget(It);
    iter->addWidget(new QLabel("Time(s)"));
    It->setRange(1,10);
    It->setValue(getIteration());
    connect(It,SIGNAL(valueChanged(int)),this,SLOT(changeIteration(int)));

    QHBoxLayout *executeHBox = new QHBoxLayout(execute);
    execute->setLayout(executeHBox);
    QCheckBox *Execute = new QCheckBox(parent);
    executeHBox->addWidget(Execute);
    Execute->setChecked(getExecute());
    connect(Execute,SIGNAL(clicked(bool)),this,SLOT(changeExecute(bool)));
}

void GaussianFilter::CreateAdvancedFilterWidgets(QWidget *parent) {
    // This is the part that is giving me doubts
}

GaussianFilter::~GaussianFilter(){}

FilterItem::FilterItem(Filter *userFilter)
{
    filter = userFilter;
}

void FilterItem::CreateWidgets(QWidget *parent)
{
    item = new QTreeWidgetItem();
    QPushButton *childButton = new QPushButton("Child Button 0");
    QTreeWidgetItem *childItemButton = new QTreeWidgetItem();
    if(filterType == Filter::GAUSSIAN){
        item->setText(0,QString("Gaussian"));
        filter->tree->addTopLevelItem(item);

        childItem = new QTreeWidgetItem();
        item->addChild(childItem);
        gaussian->CreateFilterWidgets(parent);
        filter->tree->setItemWidget(childItem,0,gaussian->type);
        filter->tree->setItemWidget(childItem,1,gaussian->iteration);
        filter->tree->setItemWidget(childItem,2,gaussian->execute);
    }
}

void FilterItem::CreateAdvancedWidgets(QWidget *parent)
{
    otherItem->setText(0,QString("Advanced Gaussian"));
    filter->tree->addTopLevelItem(otherItem);

    QTreeWidgetItem *childItem1 = new QTreeWidgetItem();
    QTableWidget *tw = new QTableWidget();
    tw->setColumnCount(3);
    tw->setRowCount(3);
}

FilterItem::~FilterItem()
{

}

最后是 ma​​in.cpp

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

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

如果您需要查看 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>800</width>
    <height>600</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <layout class="QGridLayout" name="gridLayout">
    <item row="0" column="0">
     <layout class="QHBoxLayout" name="HLayout"/>
    </item>
   </layout>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>800</width>
     <height>22</height>
    </rect>
   </property>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
  <widget class="QToolBar" name="mainToolBar">
   <property name="windowTitle">
    <string>toolBar</string>
   </property>
   <attribute name="toolBarArea">
    <enum>TopToolBarArea</enum>
   </attribute>
   <attribute name="toolBarBreak">
    <bool>false</bool>
   </attribute>
  </widget>
 </widget>
 <resources/>
 <connections/>
</ui>

我尝试自己解决问题,首先咨询了QTreeWidgetItem类以确保我没有错过任何规范。另外我还咨询了QTreeWidget也上课以确保我正确使用了 setItemWidget正确。在我看来是的。 然而,一旦我实现了附加函数 CreateAdvancedWidgets(QWidget *parent),事情就按我的计划停止了。

因此进行了更多研究并发现了 this useful source .我复制了该示例以确保我没有遗漏任何内容并将其应用于我的案例,但它没有用。我也经历了this , this source最后 this source too .

感谢任何愿意花一点时间来研究它并提出解决这个问题的潜在解决方案的人。

最佳答案

每当我使用 Qt 并考虑使用 QTableWidget 时,我总是首先考虑其他选项,因为它们不容易使用。以下是我目前会考虑的内容:

  • 是否会出现需要多行的情况?
  • 您的布局是否需要动态属性,例如由用户调整大小的列或排序的能力?

如果这些问题的答案是否定的,那么或许可以考虑使用 QGridLayout 和一两个 QSpacerItem。

但是,如果您必须拥有其中一些东西(或者它们可能是为将来计划的),请查看 QAbstractItemModel 以及一些与之相关的示例(例如:https://doc.qt.io/qt-5/qtwidgets-itemviews-simpletreemodel-example.html)

关于c++ - 如何将 QTableWidget 添加到 QTreeWidget 中,但作为 QTreeWidgetItem,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69831268/

相关文章:

c++ - 从源代码编译 Qt 5.3 失败

javascript - 在 Node.js 插件中使用 std::thread

c++ - 错误 : undefined reference to 'player()'

C++ 查找方法不是 const 吗?

c++ - 项目错误 : Unknown module(s) in QT: charts on Mac

c++ - 如何在 QSqlTableModel 和 Q_OBJECT 之间不发生冲突的情况下构建我的类?

qt - 如何为QPlainTextEdit设置文本?

c++ - 简单的 GUI 应用程序在 Qt 5 中崩溃

c++ - 在 Windows Compact 2013 中标记存储卷

c++ - 来自变量的 QJsonObject 部分路径