简体   繁体   English

如何将 QTableWidget 添加到 QTreeWidget 但作为 QTreeWidgetItem

[英]How to add a QTableWidget into a QTreeWidget but as a QTreeWidgetItem

I am designing a major interface but had a problem on how to add a QTableWidget into a QTreeWidget but as a QTreeWidgetItem .我正在设计一个主要界面,但在如何将QTableWidget添加到QTreeWidget但作为QTreeWidgetItem遇到了问题。 In order to save everyone's time and provide the best information, below an example that replicate exactly the problem I have.为了节省大家的时间并提供最好的信息,下面是一个完全复制我遇到的问题的示例。 I tried to be as concise as possible:我尽量简洁:

  1. Below the small user interface that I have so far which is incorrect :在我目前使用的小用户界面下方,这是不正确的科尔
  1. Below the interface I am trying to achieve :我试图实现的界面下方:好的

As you can notice I am trying to insert an additional widget in the tree.正如您所注意到的,我正在尝试在树中插入一个额外的小部件。 See below the final look of the interface:请参阅下面的界面最终外观:最终的

It was really hard to prepare the example and really replicate the problem on a small scale, so please if there are any doubts, let me know:准备这个例子真的很难,真正在小范围内复制问题,所以如果有任何疑问,请告诉我:

mainwindow.h主窗口.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

mainwindow.cpp主窗口.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);
}

gaussianfilter.h高斯滤波器.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

gaussianfilter.cpp高斯滤波器.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()
{

}

finally the main.cpp最后是main.cpp

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

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

In case you need to see the components of the ui see below, it is very minimal:如果您需要查看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>

I tried to solve the problem myself and consulted first of all the QTreeWidgetItem class to make sure I didn't miss any specifications.我试图自己解决这个问题,并首先咨询了QTreeWidgetItem类,以确保我没有遗漏任何规范。 In addition I also consulted the QTreeWidget class too to make sure I was correctly using the setItemWidget correctly.此外,我还咨询了QTreeWidget类,以确保我正确使用了setItemWidget It seems to me that it is.在我看来,确实如此。 However, as soon as I implement the additional function CreateAdvancedWidgets(QWidget *parent) things just stopped working as I planned.然而,一旦我实现了附加功能CreateAdvancedWidgets(QWidget *parent)事情就停止了按我的计划工作。

So did more research and came across this useful source .因此做了更多的研究并发现了这个有用的来源 I replicated the example to make sure I wasn't missing anything and applied it to my case but it didn't work.我复制了这个例子以确保我没有遗漏任何东西并将它应用到我的案例中,但它没有用。 I also went through this , this source and lastly this source too .我也经历了这个这个来源,最后也是这个来源

Thanks to anybody who would be willing to use a bit of their time to go through it and suggest a potential solution to this problem.感谢任何愿意花一点时间来完成它并提出解决此问题的潜在解决方案的人。

Whenever I use Qt and consider using a QTableWidget, I always consider other options first because they are NOT easy to work with.每当我使用 Qt 并考虑使用 QTableWidget 时,我总是首先考虑其他选项,因为它们不容易使用。 Here's what I'd consider at this point:在这一点上,我会考虑以下几点:

  • is there going to be a case where multiple rows are needed?是否会出现需要多行的情况?
  • is your layout going to need dynamic properties, like having resizable columns by the user or the ability to sort?您的布局是否需要动态属性,例如用户可调整大小的列或排序能力?

If the answer to these questions is no, then perhaps consider using a QGridLayout and a QSpacerItem or two.如果这些问题的答案是否定的,那么也许可以考虑使用一个 QGridLayout 和一个 QSpacerItem 或两个。

However, if you have to have some of those things (or maybe they're planned for the future), look at QAbstractItemModel and some examples that go along with it (eg: https://doc.qt.io/qt-5/qtwidgets-itemviews-simpletreemodel-example.html )但是,如果您必须拥有其中一些东西(或者它们可能是为未来计划的),请查看 QAbstractItemModel 和一些与之相关的示例(例如: https : //doc.qt.io/qt-5 /qtwidgets-itemviews-simpletreemodel-example.html )

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM