I am designing a major interface but had a problem on how to add a QTableWidget
into a QTreeWidget
but as a 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:
- Below the small user interface that I have so far which is incorrect:
- 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
#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
#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
#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
#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
#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:
<?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. In addition I also consulted the QTreeWidget class too to make sure I was correctly using the setItemWidget correctly. 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.
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.