Why do the next two code sequences behave differently? - qt

I don't understand why the first code sequence creates a QWidget where the elements overlap, while the second one behaves correctly.
The only difference is that in the first one there is a QVBoxLayout pointer, while in the second one it's an object.
It's about passing by reference vs passing by pointer? I really don't get the subtle difference.
First one:
QVBoxLayout vbox;
vbox.setSpacing(2);
QPushButton* quitButton = new QPushButton("Qsdfsuit");
QFont fnt = quitButton->font();
fnt.setPointSize(18);
fnt.setBold(true);
fnt.setFamily("Arial");
quitButton->setFont(fnt);
connect(quitButton, SIGNAL(clicked()), qApp, SLOT(quit()));
QLCDNumber* lcd = new QLCDNumber(2);
QSlider* slider = new QSlider(Qt::Horizontal);
slider->setRange(0, 99);
slider->setValue(0);
connect(slider, SIGNAL(valueChanged(int)), lcd, SLOT(display(int)));
vbox.addWidget(quitButton);
vbox.addWidget(lcd);
vbox.addWidget(slider);
this->setLayout(&vbox);
The second one:
QVBoxLayout* vbox = new QVBoxLayout();
vbox->setSpacing(2);
QPushButton* quitButton = new QPushButton("Qsdfsuit");
QFont fnt = quitButton->font();
fnt.setPointSize(18);
fnt.setBold(true);
fnt.setFamily("Arial");
quitButton->setFont(fnt);
connect(quitButton, SIGNAL(clicked()), qApp, SLOT(quit()));
QLCDNumber* lcd = new QLCDNumber(2);
QSlider* slider = new QSlider(Qt::Horizontal);
slider->setRange(0, 99);
slider->setValue(0);
connect(slider, SIGNAL(valueChanged(int)), lcd, SLOT(display(int)));
vbox->addWidget(quitButton);
vbox->addWidget(lcd);
vbox->addWidget(slider);
this->setLayout(vbox);

In the first segment QVBoxLayout vbox; is created on the stack.
It is destroyed as soon as the method execution if finished.
In the second segment QVBoxLayout* box is created in a heap and it's not destroyed until the widget is alive.
Layouts in Qt do their job when a widget is shown or resized that's why they should exist until a widget exists.
More information:
The stack and the heap
Blocks and local variables

Related

Qt, how to remove the frame of widget

I realize two QPlainTextEdit and lay them in one QSplitter, but the margin of these two widgets is a bit large. I also notice the wigets of Qt creator is very compact. I don't know how to reduce the distance of my widgets.
I post my code below:
QVBoxLayout * spuvbox = new QVBoxLayout ;
SPUEdit = new CodeEditor;
QLabel *label1 = new QLabel("SPU Code");
spuvbox->addWidget(label1);
spuvbox->addWidget(SPUEdit);
QWidget * spuwidget = new QWidget;
spuwidget->setLayout(spuvbox);
QVBoxLayout * mpuvbox = new QVBoxLayout ;
MPUEdit = new CodeEditor;
QLabel *label2 = new QLabel("MPU Code");
mpuvbox->addWidget(label2);
mpuvbox->addWidget(MPUEdit);
QWidget * mpuwidget = new QWidget;
mpuwidget->setLayout(mpuvbox);
QSplitter * textsplitter = new QSplitter(Qt::Horizontal,0);
textsplitter->setHandleWidth(2);
textsplitter->addWidget(spuwidget);
textsplitter->addWidget(mpuwidget);
setCentralWidget(textsplitter);

QHBoxLayout addwidget() order and two qglwidget share texture object

I created two QGLwidget objects:
slicerCanvas* slicerX_;
secCan* secWid_;
secWid_ = new secCan(this);
//slicerX_ load data and create texture object share with secWid_
slicerX_ = new slicerCanvas(this,secWid_);
and in the main window, I use QHBoxLayout:
hBox_ = new QHBoxLayout;
hBox_->addWidget(slicerX_);
hBox_->addWidget(secWid_);
centerWidget_->setLayout(hBox_);
It works right, but if I addWidget like this:
hBox_ = new QHBoxLayout;
hBox_->addWidget(secWid_);//first
hBox_->addWidget(slicerX_);//second
centerWidget_->setLayout(hBox_);
The secWid_ will not paint anything, only slicerX_ paints correctly. I am confused as to why.

Qt - how to access QComboBox data inserted in QTreeWidget

During runtime I have inserted QCombobox in my QTreeWidget like this:
//global defines
#define COLUMN_1 (0)
#define COLUMN_2 (1)
//Init QComboBox to QTreeWidget - works fine.
QTreeWidgetItem *item = new QTreeWidgetItem(_myTreeWidget);
item->setText(COLUMN_1,"testing");
QComboBox *box = new QComboBox();
box->addItem("select1");
box->addItem("select2");
box->addItem("select3");
_myTreeWidget->setItemWidget(item, 1, box);
The above code works, but I also want to read the data text in these columns. Eg. get the strings "testing" & "select2" from code above. The problem is that I can't figure out how to read the "QComboBox::currentText()" in the comboboxes.
I have tried:
QTreeWidgetItemIterator it(_myTreeWidget);
while(*it)
{
QTreeWidgetItem *item = *it;
QVariant first = item->text(COLUMN_1);
QString firstStr = loggerName.toString(); //this works
QComboBox *box = (QComboBox*)item->data(COLUMN_2, 0);
QString boxValStr = box->text().toString(); //this doesn't works, always empty string
//... more code to handle strings...
it++;
}
Feels like the "item->data(COLUMN_2, 0)" is wrong way to go cause it returns a QVariant.
Solution on this problem?
QComboBox *box = (QComboBox*)item->data(COLUMN_2, 0);
When I read this code, I went into panic mode. Look at the signature:
QVariant QTreeWidgetItem::data ( int column, int role ) const
As you used setItemWidget, you should probably use
QWidget * QTreeWidget::itemWidget ( QTreeWidgetItem * item, int column ) const
ps: If you want to cast, use C++ casts. Much better, use qobject_cast<SubtypeofQObjectPtr> for QObject. It returns null when the cast is invalid.
Indeed, I mean retrieve the combobox using a call similar to :
QComboBox* box = qobject_cast<QComboBox*>(treeWidget->itemWidget(item, column));
Solved it thanks to the help from #Umnyobe and #Zaiborg above. Here is a total working example:
Init QTreeWidget with text in column1 and QComboBox in column2:
//global defines
#define COLUMN_1 (0)
#define COLUMN_2 (1)
QTreeWidgetItem *item = new QTreeWidgetItem(_myTreeWidgetPtr);//item to put in tree
item->setText(COLUMN_1,"animal"); //item for column 1 in the tree.
QComboBox *box = new QComboBox();
box->addItem("mouse"); //adds selections for comboboxes
box->addItem("cat");
box->addItem("dog");
_myTreeWidgetPtr->setItemWidget(item, COLUMN_2, box); //insert items in tree.
Read values from tree:
QTreeWidgetItemIterator it(_myTreeWidgetPtr);
while(*it)
{
QTreeWidgetItem *item = *it;
//Init pointer to current combobox
QComboBox* box = qobject_cast<QComboBox*>(_myTreeWidgetPtr->itemWidget(item, COLUMN_2));
//Get data from QTreeWidget
QString col1Str = item->text(COLUMN_LOGGER);
QString col2Str = box->currentText();
it++;
}
hope it can help someone :)
use the QSignalMapper class to collect the different boxes in the treewidget.
then connect the QSignalMapper::mapped() signal to some slot and use the combobox
edit:
QSignalMapper* mapper = new QSignalMapper(this);
QComboBox *box = new QComboBox();
connect( box, SLOT(/*whatever*/), mapper, SLOT( map() ) );
mapper->setMapping( box );
myTreeWidget->setItemWidget(item, 1, comboBox);
For anyone who is looking for a Python solution,
(PySide / PyQt QComboBox in QTreeWidget), here is it:
item = QTreeWidgetItem(self.treeWidgetAnimals)
item.setText(0, "animal")
combo_box = QComboBox()
combo_box.addItem('mouse')
combo_box.addItem('cat')
combo_box.addItem('dog')
self.treeWidgetAnimals.setItemWidget(item, 1, combo_box)
I was looking for hours but no other forum like pass reference "parent" like a "delegation":
        item = QTreeWidgetItem (self.myTreeWidgetItemObject)
if you do not pass the parent, error ir not returned but the ComboBox not appears in display TreeWidget.

point or arrow on variables/methods in Qt

can you please tell me the difference between the "point" and the "arrow", for example :
file.open
and
->start() (with QThread)
i thought the arrow was used for "methods", whereas the "point" is used for "attributes", but open for example is a method.
thanks for your answer
It's not just for Qt, the . is used when the variable in question is referencing the actual instance of the type/class.
Example:
QLabel label(QString("Hello"));
label.show();
The -> is used when the variable is a pointer that can hold the address of the type/class.
Example:
QLabel *label = new QLabel(QString("Hello"));
label->show();
-> is used for pointers. if x is declared as pointer to sth, x-> is used for attributes, otherwise . is used.
QLabel *label = new QLabel(tr("Heyy"));
QHBoxLayout hbox = new QHBoxLayout;
label->show();
hbox.addWidget("foo");

Qt Qbrush issue

What is the difference in the following code,
QGraphicsScene * scence = new QGraphicsScene();
QBrush *brush = new QBrush((QColor(60,20,20)));
scence->setBackgroundBrush(*brush);
QGraphicsView *view = new QGraphicsView();
view->setScene(scence);
//view->setBackgroundBrush(*brush);
//view->setCacheMode(QGraphicsView::CacheBackground);
view->showFullScreen();
gives black color background
QGraphicsScene * scence = new QGraphicsScene();
QBrush *brush = new QBrush();
brush->setColor(QColor(60,20,20));
scence->setBackgroundBrush(*brush);
QGraphicsView *view = new QGraphicsView();
view->setScene(scence);
//view->setBackgroundBrush(*brush);
//view->setCacheMode(QGraphicsView::CacheBackground);
view->showFullScreen();
it gives nothing.
As the Qt doc says :
QBrush::QBrush ()
Constructs a default black brush with the style Qt::NoBrush (i.e. this brush will not fill shapes).
In your second example, you have to set the style of the QBrush object by setStyle(), for example with Qt::SolidPattern.
QGraphicsScene * scence = new QGraphicsScene();
QBrush *brush = new QBrush();
brush->setStyle(Qt::SolidPattern); // Fix your problem !
brush->setColor(QColor(60,20,20));
scence->setBackgroundBrush(*brush);
QGraphicsView *view = new QGraphicsView();
view->setScene(scence);
//view->setBackgroundBrush(*brush);
//view->setCacheMode(QGraphicsView::CacheBackground);
view->showFullScreen();
Hope it helps !
An alternate approach that achieves the same result is to put the color in the brush constructor, and that applies a default style of solid:
QBrush *brush = new QBrush (QColor (60, 20, 20));
The constructors that take a color have an optional parameter for the style, which defaults to Qt::SolidPattern. Both approaches produce the same result, but this one uses two fewer lines of code.

Resources