I know this has been asked several times in different posts, however I am still not convinced that my implementation is the best solution.
I have a QVBoxLayout in which I add a QHBoxLayout which hold widgets. The QVBoxLayout by default is empty.
I delete all layouts widgets using this code, however the widgets can fire signals. Is this save? Also I would rather want to change it to a recursive function as shown in https://stackoverflow.com/questions/4272196/qt-remove-all-widgets-from-layout/7077340#=
QLayoutItem *child;
while ((child = ui->verticalLayoutAmplitude->takeAt(0)) != 0) {
QLayoutItem * subchild;
while ((subchild = child->layout()->takeAt(0)) != 0) {
delete subchild->widget();
delete subchild;
}
delete child->widget();
delete child;
}
What I do not understand is why it is so complicated.
Also the creation of the widgets could be different
The parent layout can not be used in the creation of the widgets.
Thus only the MainWindow as a parent class was inserted.
I wonder what else should be inserted as a parent class?
for (int i = 0; i < parameterList.size(); ++i) {
QString valueName = parameterList.at(i);
double value = parameter(valueName);
QHBoxLayout * hLayout = new QHBoxLayout(this);
QDoubleSpinBox * spinbox = new QDoubleSpinBox();
QLabel * label = new QLabel();
label->setText(valueName);
spinbox->setValue(value);
hLayout->addWidget(label, 1);
hLayout->addWidget(spinbox, 3);
ui->verticalLayoutAmplitude->addLayout(hLayout);
}
I want to dynamically create X labels on a layout. The X is taken from the QSpinBox.
When X is decreased, I need to first remove items on layout and then create a new one, with decreased number of labels:
void dial::quantity1SpinClicked(int val)
{
QLayout *layout = fqbox->layout();
if(layout != 0)
{
QLayoutItem *item;
while ((item = layout->takeAt(0)) != 0)
layout->removeItem (item);
delete layout;
}
QGridLayout *gridLayout = new QGridLayout;
QList<QLabel*> labels;
for (int i = 0; i < val; ++i){
labels << new QLabel(QObject::tr("nr %1").arg(i));
gridLayout->addWidget(labels.at(i), i, 0);
}
fqbox->setLayout(gridLayout);
}
However, my code does not remove items, it creates a new layout, on top on the old one (it looks like so):
How to solve this?
It is needed to delete QLabel widget:
QLayoutItem *item;
while ((item = layout->takeAt(0)) != 0) {
layout->removeItem (item);
delete item->widget();
delete item;
}
Note also description of QLayout::removeItem(QLayoutItem * item):
It is the caller's responsibility to delete the item.
Notice that item can be a layout (since QLayout inherits
QLayoutItem).
I'm newbie with QT and have read many topics, but I just don't get it. I hope that someone could help me with this.
So, I have created a loop where i add QTables in QGroupBoxes. Table's 2nd column is meant for QCheckBoxes and first column is meant for condition text, which changes when checkbox is ticked.
Everything is working except the text won't change. So problem should be in the signal. I just can't figure it out :(
I would be glad for any help :)
inputBox = new QGroupBox();
QScrollArea *boxScroll = new QScrollArea();
QHBoxLayout *boxLayout = new QHBoxLayout();
boxTable = new QTableWidget();
inputBox->setLayout(boxLayout);
boxLayout->addWidget(boxTable);
boxTable->verticalHeader()->setVisible(false);
boxTable->setRowCount(24);
boxTable->setColumnCount(5);
boxTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
boxTable->setHorizontalHeaderItem(0, new QTableWidgetItem("ID"));
boxTable->setHorizontalHeaderItem(1, new QTableWidgetItem("State"));
boxTable->setHorizontalHeaderItem(2, new QTableWidgetItem("Enable"));
for (int i=0; i<24; i++)
{
inCheck = new QCheckBox();
iCheckLabel = new QLabel();
QTableWidgetItem *id = new QTableWidgetItem();
QTableWidgetItem *state = new QTableWidgetItem();
QTableWidget *checkWidget = new QTableWidget();
QHBoxLayout *checkLayout = new QHBoxLayout();
checkLayout->setAlignment(Qt::AlignCenter);
checkLayout->setContentsMargins(0,0,0,0);
checkLayout->addWidget(inCheck);
checkWidget->setLayout(checkLayout);
id->setText(QString::number(i));
id->setTextAlignment(Qt::AlignCenter);
id->setFlags(id->flags() & ~Qt::ItemIsEditable);
state->setText("Off");
state->setTextAlignment(Qt::AlignCenter);
state->setFlags(state->flags() & ~Qt::ItemIsEditable);
state->setTextColor(Qt::red);
boxTable->setItem(i, 0, id);
boxTable->setItem(i, 1, state);
boxTable->setCellWidget(i, 2, checkWidget);
connect(checkWidget, SIGNAL(cellChanged(int,int)), this, SIGNAL(inCheckChecked(int, int)));
}
inputBox->setMinimumSize(350, 450);
inputBox->setTitle(title);
ui->scrollAreaWidgetContents->layout()->addWidget(inputBox);
void Project::inCheckChecked(int row, int col)
{
QTableWidgetItem *item = boxTable->item(row, col);
if (item->checkState() == true)
{
qDebug("is checked");
}
}
You do something very strange here. You set a layout to your table widget and then add a check box to that layout, then you add this table widget to another table widget. Why? You could just use QTableWidget::setItem(int row, int column, QTableWidgetItem * item) to add a check box, like you use it for id and state items. Just make it a checkable item.
for (int i=0; i<24; i++)
{
QTableWidgetItem *id = new QTableWidgetItem();
QTableWidgetItem *state = new QTableWidgetItem();
QTableWidgetItem *checkItem = new QTableWidgetItem();
...
checkItem->setCheckState(Qt::Unchecked); // shuold be enough to make it checkable..
//you can also set the needed flags
boxTable->setItem(i, 0, id);
boxTable->setItem(i, 1, state);
boxTable->setItem(i, 2, checkItem);
}
Then you just connect the signal from boxTable to your slot, which will notify you when the checkbox state is changed.
In this code, there is bug in below line
connect(checkWidget, SIGNAL(cellChanged(int,int)), this, SIGNAL(inCheckChecked(int, int)));
For using connect, according to your implementation, you want to connect one signal and one slot, that consumes that signal. It should be as below :
connect(checkWidget, SIGNAL(cellChanged(int,int)), this, SLOT(inCheckChecked(int, int)));
Get More info on Signals and Slots here
I'm receiving a signal with parametres (Current, total) and each time I'm suppose to
alter the value of progressbar which is inside the QTreeWidgetItem.
That is my source code.
I have:
QMap<QXmppTransferJob*, TransferItemWidget*> widget_map;
And I add here new items
void MainWindow::addItem(QXmppTransferJob *job)
{
QTreeWidgetItem *item = new QTreeWidgetItem(ui->treeWidget);
widget_map[job] = new TransferItemWidget;
widget_map[job]->fileNameLabel->setText(job->fileName());
widget_map[job]->bareJidLabel->setText(job->jid());
ui->treeWidget->setItemWidget(item,0,widget_map[job]);
}
and each time when I receive a signal there implemented the following slot:
void MainWindow::progress(qint64 ¤t, qint64 &total)
{
QXmppTransferJob *job = (QXmppTransferJob*)QObject::sender();
widget_map[job]->progressBar->setMaximum(total);
widget_map[job]->progressBar->setValue(current);
}
Progressbar isn't changing by value but remains the same? Can anyone guide me through to find my mistake
I am adding three tables dynamically in widget containing table widget and labels, but nothing shows on screen, I have tried to do it with vertical layout but it does not expand if i add a new row, so not scrolling.
Is there any other way to get all three tables on a same page with scrolling.
QScrollArea *m_scrollArea =ui->scrollArea_Stats;
m_scrollArea->setWidgetResizable(true);
QWidget *area = new QWidget;
QVBoxLayout *vlay = new QVBoxLayout(m_scrollArea);
area->setLayout(vlay);
StatsWidget *objStatsWidget;
for(int i=0;i<2;i++)
{
objStatsWidget=new StatsWidget(ui->scrollArea_Stats);
vlay->addWidget(objStatsWidget);
}
m_scrollArea->setWidget(area);
here StatsWidget is my custom widget containing 2 lables at top and a table widget
I am adding three tables dynamically but page is not scrolling, vlay is not showing all tables it is just showing what it can show in a page without scrolling.
try rewrite the code as this:
m_scrollArea->setWidgetResizable(true);
QVBoxLayout *vlay = new QVBoxLayout;
StatsWidget *objStatsWidget;
for(int i=0;i<2;i++)
{
objStatsWidget=new StatsWidget(ui->scrollArea_Stats);
vlay->addWidget(objStatsWidget);
}
QWidget *area = new QWidget(m_scrollArea);
area->setLayout(vlay);
m_scrollArea->setWidget(area);
EDIT: i made something like what you are trying to do some time ago..
so: create a custom QWidget with a QVBoxLayout as member.let's call this object "widgetList". then reimplement all method that you need, as addWidget, takeAt etc.. using your layout as a list
finally set widgetList as widget for your scroll area..
let me know..
I made all this because QWidgetList was not enough easy to use and i needed something else that i have omitted here..
I found my piece of code:
class WidgetList : public QWidget
{
Q_OBJECT
public:
WidgetList(QWidget *parent = 0);
~WidgetList();
void addWidget(QWidget*);
void removeWidget(QWidget*);
QList<QWidget*> getListWidget() const;
QWidget* takeAt(int) const;
int count() const;
private:
QVBoxLayout* layout_;
};
.cpp
WidgetList::WidgetList(QWidget *parent)
: /**/QWidget(parent)
/**/,layout_(new QVBoxLayout(this))
{
this->setLayout(layout_);
}
void WidgetList::removeWidget(QWidget* widget)
{
layout_->removeWidget(widget);
}
void WidgetList::addWidget(QWidget* widget)
{
layout_->addWidget(widget);
}
QWidget* WidgetList::takeAt(int index) const
{
return layout_->takeAt(index)->widget();
}
int WidgetList::count() const
{
return layout_->count();
}
this will be your new Widget with layout where to insert your custom widget..
then i put widgetList as widget of QScrollArea:
QScrollArea* scrollArea = new QScrollArea;
widgetList* list = new widgetList(scrollArea);
scrollArea->setWidget(list);
everything works for me..
EDIT 2: i post my main that works good with my previous code:
QScrollArea* scroll = new QScrollArea;
WidgetList* w = new WidgetList(scroll);
QLabel * label = new QLabel("Label1");
QLabel* label2 = new QLabel("label2");
QTableWidget* table = new QTableWidget(10,10);
w->addWidget(label);
w->addWidget(label2);
w->addWidget(table);
scroll->setWidget(w);
scroll->setWidgetResizable(true);
scroll->show();