Displaying an image with QGraphics Scene - c++

Having an issue with displaying a loaded image in a QGraphicsScene.
CTextBox::CTextBox(QWidget* parent /* = NULL */)
{
QPixmap image;
image.load("basketball.png");
grid = new QGridLayout();
grid->setSpacing(1);
textBrowser = new QTextEdit(this);
treeView = new QTreeView;
treeLabel = new QLabel;
treeLabel->setText("Tree View:");
debugLabel = new QLabel;
debugLabel->setText("Debug:");
standardModel = new QStandardItemModel;
rootNode = standardModel->invisibleRootItem();
treeView->setModel(standardModel);
QGraphicsPixmapItem pixmapitem(image);
//scene.addText("Graphics");
scene.addItem(&pixmapitem);
//rect = scene.addRect(QRectF(0,0, 100, 100));
//QGraphicsItem *item = scene.itemAt(50, 50);
widget = new QWidget();
view = new QGraphicsView;
view->setScene(&scene);
view->setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers)));
//proxy = scene.addWidget(widget);
//label = new QLabel();
grid->addWidget(textBrowser, 1, 0);
grid->addWidget(debugLabel, 0, 0);
grid->addWidget(treeView, 1, 1);
grid->addWidget(treeLabel, 0, 1);
//grid->addWidget(&image, 2,0);
//grid->addWidget(view, 2, 0);
//grid->addWidget(widget, 2, 0);
//grid->addWidget(proxy, 2,0);
view->show();
//widget->setLayout(view);
//widget->show();
setLayout(grid);
//label->addItem()
}
Basically when I try and load the image in a QGraphicsScene it seems to scale up to the size of the image but displays a white screen. I can add text to the graphics scene fine and that will display correctly. Now if I try to do add the image into a label on a different widget it displays fine. Any ideas why?
Cheers.

You don't see it because you pass a reference to a local object of the constructor. The pixmap item will be destructed immediately after your constructor ends. Use dynamic allocation instead.
QGraphicsPixmapItem* pixmapitem = new QGraphicsPixmapItem(image);
scene.addItem(pixmapitem);

Related

QT C++ Scroll Issues

I have an issue in locking a widget's contents to a scroll-area.
I think the best way to describe is in the pictures attached.
Picture 'a' is normal operation without a scroll area
Picture 'b' is when I attempt to add a scroll area to the widget.
The scroll- area appears but the text is not contained within.
The scroll-area is its own seperate entity with the content appearing away from it.
This is the code which I have placed in my widget:
QScrollArea *scrollArea = new QScrollArea;
scrollArea->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
scrollArea->setVisible(true);
scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
scrollArea->setWidget(this);
scrollArea->setGeometry(680, 250, 560, 440);
scrollArea->setBackgroundRole(QPalette::Light);
Any ideas?
Picture a :
Picture b :
Here is the call to the custom child widget from the main GUI:
subalerPane = new subalertsPane(mstrWnd);
subalerPane->setObjectName(subalertspane_params._name);
subalerPane->setGeometry(QRect(subalertspane_params._x, subalertspane_params._y, subalertspane_params._w, subalertspane_params._h));
subalerPane->setPixmaps(QPixmap(subalertspane_params._normalImageDm), QPixmap(subalertspane_params._normalImageNm), QPixmap(subalertspane_params._minimisedImageDm), QPixmap(subalertspane_params._minimisedImageNm));
subalerPane->setWindowFlags(Qt::Window | Qt::FramelessWindowHint);
subalerPane->setAttribute(Qt::WA_TranslucentBackground);
subalerPane->setState(subalertspane_params._defaultState);
subalerPane->setUIMode(subalertspane_params._defaultUIMode);
subalerPane->setVisible(true);
subalerPane->raise();
Here is the subalertsPane cpp file:
subalertsPane::subalertsPane(QWidget *parent) :QLabel(parent)
{
subalertsPane::state=bsNormal;
subalertsPane::pressable=true;
subalertsPane::uiMode=bdnDay;
connect(this, SIGNAL(clicked()), this, SLOT(slotClicked()));
connect(this, SIGNAL(released()), this, SLOT(slotReleased()));
statbutts[0] = new statusButton(this);
statbutts[1] = new statusButton(this);
statbutts[2] = new statusButton(this);
statbutts[3] = new statusButton(this);
statbutts[4] = new statusButton(this);
statbutts[5] = new statusButton(this);
statbutts[6] = new statusButton(this);
statbutts[7] = new statusButton(this);
statbutts[8] = new statusButton(this);
statbutts[9] = new statusButton(this);
statbutts[10] = new statusButton(this);
for (int i = 0; i < 11; i++)
{
statbutts[i]->fadeIn();
statbutts[i]->setVisible(false);
}
QScrollArea *scrollArea = new QScrollArea;
scrollArea->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
scrollArea->setVisible(true);
scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
scrollArea->setWidget(this);
scrollArea->setGeometry(680, 250, 560, 440);
scrollArea->setBackgroundRole(QPalette::Light);
}
QScrollArea::setWidget() is used for setting a widget inside the scroll area with the the content.
Example: if you want a QLabel with a text inside the scroll area - scrollArea->setWidget(qLabel);
Then add the scroll area to a layout of the view
auto *scrollArea = new QScrollArea(this);
scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
scrollArea->setWidgetResizable(true);
auto *buttonsWidget = new QGroupBox(scrollArea);
scrollArea->setWidget(buttonsWidget);
auto *comboboxesLayout = new QVBoxLayout();
buttonsWidget->setLayout(comboboxesLayout);
mainLayout->addWidget(scrollArea);

how to destroy a layout before we rebuild it Qt c++

I have a little problem displaying my layouts. I have an application that contains a GridLayout, HBoxLayout, and VBoxLayout.
The HBoxLayout contains: a button and line edit
The GridLayout contains: progbars (1-99)
The HBoxLayout and the GridLayout are put in a VBoxLayout
My problem is when I click, The grid layout appears on the HBoxLayout. It's like the HBoxLayout wasn't a part of the VBoxLayout. So, even when I destroy the layout and create it again, I still have the same problem.
An image is displayed below to better understand my problem.
code: window.cpp
Window::Window(QWidget *parent) :
QWidget(parent){
label = NULL;
progressbar = NULL;
workerThread = NULL;
m_counter = NULL;
layout = new QHBoxLayout(NULL);
lineEdit = new QLineEdit(NULL);
m_button = new QPushButton("click", NULL);
time= new QTimer(this);
lineEdit-> setInputMask("00");;
//lineEdit->setGeometry(400,10,160,30);
lineEdit->setPlaceholderText("N between 1 & 99");
// Create and position the button
// m_button->setGeometry(100, 10, 150, 30);
QIcon icon("/home/ca/Downloads/chauvin.png");
m_button->setIcon(icon);
m_button->setIconSize(QSize(100, 30));
m_button->setToolTip("this is a beautifull button ");
//layout = new QFormLayout;
layout->addWidget(m_button);
layout->addWidget(lineEdit);
setLayout( layout );
// showTime();
time->start(1000);
setWindowTitle(tr("Digital Clock"));
// NEW : Do the connection
connect(m_button, &QPushButton::pressed, this , &Window::slotButtonPressed);}
void Window::slotButtonPressed(){
layoutgrid = new QGridLayout(NULL);
m_button->setEnabled(true);
QString contenu = lineEdit->text();
int i_contenunumber= contenu.toInt(0,10);
m_counter= new int[i_contenunumber];
memset( m_counter, 0, i_contenunumber );
label = new QLabel*[ i_contenunumber ];
progressbar = new QProgressBar*[ i_contenunumber ];
workerThread= new mythread*[ i_contenunumber ];
int x= 0;
int y= -1;
int i=0;
m_button->setText("Checked");
for(i=0;i< i_contenunumber ;i++)
{
if (i%5==0)
{
x=0;
y++;
}
int i_Randomvalue = rand() % 500 + 100;
// label[i] = new QLabel(NULL);
// //label[i]->setGeometry(100*x*1.7, 80+(50*y), 160, 30);
// label[i]->setText("Tread" + QString::number(i_Randomvalue));
// label[i]->setVisible(true);
progressbar[i] = new QProgressBar(NULL);
progressbar[i]->setRange(0, 100);
progressbar[i]->setOrientation(Qt::Horizontal);
//progressbar[i]->setGeometry(100*x*1.7,60+(50*y),150,30);
progressbar[i]->setValue(0);
progressbar[i]->setVisible(true);
layoutgrid->addWidget(progressbar[i],y,x);
setLayout(layoutgrid);
workerThread[i] = new mythread(i_Randomvalue, i);
connect(workerThread[i], &mythread::signalemit, this, &Window::barprogress);enter code here
connect(workerThread[i], &mythread::signalFinThread, this, &Window::findethread);
workerThread[i] ->start();
x++;
m_counter[i]=0;
}
// Window::setFixedSize(1000,120+(50*y-1));
removeLayout();
layoutvbox = new QVBoxLayout(NULL);
layoutvbox->addLayout(layout);
layoutvbox->addLayout(layoutgrid);
setLayout(layoutvbox);
adjustSize();
}
void Window::removeLayout ( void )
{
QLayout* po_l_layout = QWidget::layout ();
if (po_l_layout != 0)
{
QLayoutItem *item;
while ((item = po_l_layout->takeAt(0)) != 0)
po_l_layout->removeItem (item);
delete po_l_layout;
}
}
delete layout will not work here because it will not delete all the containing widgets
Instead just create a new widget that contains the layout
m_widget = new QWidget();
QGridLayout *outerLayout = new QGridLayout(m_widget);
m_layout->addWidget(m_widget);
this->setLayout(m_layout);
to remove and rebuild just delete the widget
delete m_widget
deleting a widget deletes all sub layouts and widgets contained by the widget
Once the layout of your widget is set, you can not change it unless you remove the old layout. My suggestion is to delete the old layout
//remove all of layouts widgets here
delete layout
Then create the QVBoxLayout and call setLayout(layoutvbox)
If you wish to switch back and forth, just recreate/delete when needed.

QT dynamically generate label, LineEdit, Button

I want to do serial communication in the QT inside, according to the number of serial ports to dynamically generate label, LineEdit, Button, and these three buttons can pull down the scroll bar when the size of the interface, how to do well, I write this below is dead of.
The effect of encapsulation into a method
The interface was washed last
Define QGridLayout insude QScrollArea. And add your new widgets into
that layout in code. QGridLayout::addWidget
Define table where you will show several widgets in table cells. That real complicated way.
void BaseUi::BaseScrollArea()
{
QScrollArea *pArea = new QScrollArea();
QWidget *pWidget = new QWidget();
pWidget->setStyleSheet("QWidget" "{background:white;}");
m_vbox_layout = new QVBoxLayout();
m_vbox_layout->addSpacerItem(new QSpacerItem(100, 30,
QSizePolicy::Expanding, QSizePolicy::Expanding));
pWidget->setLayout(m_vbox_layout);
pArea->setWidget(pWidget);
pArea->setWidgetResizable(true);
m_main_layout = new QVBoxLayout();
m_main_layout->addWidget(pArea);
}
void BaseUi::addAutoRecordUi(QString lab_neme, QString ledit_name)
{
QWidget *page = new QWidget;
QGridLayout *layout = new QGridLayout(page);
QLabel *label = new QLabel;
label->setText(lab_neme);
label->setFont(font());
QLineEdit *ledit = new QLineEdit;
ledit->setText(ledit_name);
ledit->setFont(font());
layout->addWidget(label, 0, 1);
layout->addWidget(ledit, 0, 2);
page->setLayout(layout);
m_vbox_layout->insertWidget(m_vbox_layout->count()-1, page);
}
void BaseUi::addMulRecordUi(QString lab_neme, QString ledit_name, QString
but_name)
{
QWidget *page = new QWidget;
QGridLayout *layout = new QGridLayout(page);
QLabel *label = new QLabel;
label->setText(lab_neme);
label->setFont(font());
QLineEdit *ledit = new QLineEdit;
ledit->setText(ledit_name);
ledit->setFont(font());
QPushButton *but = new QPushButton(but_name);
but->setFont(font());
layout->addWidget(label, 0, 1);
layout->addWidget(ledit, 0, 2);
layout->addWidget(but, 0, 3);
page->setLayout(layout);
m_vbox_layout->insertWidget(m_vbox_layout->count()-1, page);
}

Widget inside another widget Qt

I am trying to achieve this layout:
where Widget1 is some widget (central widget of QMainWindow) and I want to add second widget Widget2 over it but it should be in left bottom corner of Widget1.
EDIT: my previous description wasn't very useful so I will try to describe it in more details.
I am inheriting QWidget class (class MyClass : public QWidget) and creating my own widget where I in void MyClass ::paintEvent(QPaintEvent *event) draw something on screen.
MyClass is then centralWidget of my QMainWindow.
Now on top of that I want to add smaller widget (Widget2 in image) where I would display some video (here I am not asking how to display video only how to add this Widget2 to my view).
Main thing here is that Widget2 is inside (floating in) Widget1.
EDIT2: Previous code I posted is rubbish.
Use QGridLayout to set the position of the widget:
QGridLayout* layout = new QGridLayout(this);
// 2x2 layout
QWidget* green = new QWidget(this);
green->setStyleSheet("background:green;");
QWidget* yellow = new QWidget(this);
yellow->setStyleSheet("background:yellow;");
QWidget* red = new QWidget(this);
red->setStyleSheet("background:red;");
QWidget* blue = new QWidget(this);
blue->setStyleSheet("background:blue;");
layout->addWidget(green, 0, 0); // Top-Left
layout->addWidget(yellow, 0, 1); // Top-Right
layout->addWidget(red, 1, 0); // Bottom-Left
layout->addWidget(blue, 1, 1); // Bottom-Right
ui->centralWidget->setLayout(layout);
Will give you something like that:
So, custom your own widget using QGridLayout and set the position of your widget inside it.
Set another widget as parent with black background:
QGridLayout* layout = new QGridLayout(this);
// 2x2 layout
QWidget* green = new QWidget(this);
green->setStyleSheet("background:green;");
QWidget* yellow = new QWidget(this);
yellow->setStyleSheet("background:yellow;");
QWidget* red = new QWidget(this);
red->setStyleSheet("background:red;");
QWidget* blue = new QWidget(this);
blue->setStyleSheet("background:blue;");
layout->addWidget(green, 0, 0); // Top-Left
layout->addWidget(yellow, 0, 1); // Top-Right
layout->addWidget(red, 1, 0); // Bottom-Left
layout->addWidget(blue, 1, 1); // Bottom-Right
QWidget* mainWidget = new QWidget(this);
mainWidget->setStyleSheet("background:black;");
mainWidget->setLayout(layout);
QHBoxLayout* centralLayout = new QHBoxLayout(this);
centralLayout->addWidget(mainWidget);
ui->centralWidget->setLayout(centralLayout);

How to fix QHBoxLayout items size and add drop-down list to every item in QHBoxLayout

I have custom window class
#define NAME_WIDTH 150
#define NAME_HEIGHT 20
ObjectWindow::ObjectWindow(QWidget * parent)
{
}
void ObjectWindow::SetKey(KeyObject * keyObj)
{
QGridLayout * layout = new QGridLayout(this);
nameField = new QTextEdit(this);
nameField->setText(keyObj->name);
nameField->setGeometry(nameField->geometry().x(), nameField->geometry().y(),
NAME_WIDTH, NAME_HEIGHT);
layout->addWidget(nameField);
QHBoxLayout * picsLayout = new QHBoxLayout(this);
for(std::vector<ImageInstance*>::iterator imgObj = keyObj->images.begin(); imgObj != keyObj->images.end(); imgObj++)
{
QComboBox * folderList = new QComboBox;
picsLayout->addWidget(folderList);
QImage image((*imgObj)->imgPath);
QLabel * picLabel = new QLabel;
picLabel->setPixmap(QPixmap::fromImage(image).scaled(200, 200, Qt::KeepAspectRatio, Qt::SmoothTransformation));
picsLayout->addWidget(picLabel);
}
layout->addLayout(picsLayout, 2, 0);
QPushButton * saveBtn = new QPushButton(this);
saveBtn->setText("Save");
connect(saveBtn, SIGNAL(released()),this, SLOT(Save()));
layout->addWidget(saveBtn);
setLayout(layout);
}
What i need is
small text field to set the name, I don't unerstand why SetGeometry doesn't work
dropdown list above each image. I can create QHVertical layout for each set of image and list, but maybe there is more simple way to do it?
If you just want the user to set the name, a QLineEdit is probably enough.
Then the main advantage of using a QGridLayout is that you don't need to create other layouts. It acts like a grid where you put your widgets, a bit like Excel (and other spreadsheet programs).
Oh and I see that you are not constructing the Widgets in the constructor (which seems to be empty), that's what people usually do because constructing the UI can be expensive and you just want to update it when relevant, not rebuilding the whole UI just to update a field. But without more code I cannot tell when this function is being called.
You can try something like this:
QGridLayout * layout = new QGridLayout(this);
nameField = new QLineEdit(this);
nameField->setText(keyObj->name);
layout->addWidget(nameField, 0, 0, -1, 1); // expand to the right edge
int currentColumn = 0;
for(std::vector<ImageInstance*>::iterator imgObj = keyObj->images.begin(); imgObj != keyObj->images.end(); imgObj++)
{
QComboBox * folderList = new QComboBox;
layout->addWidget(folderList, 1, currentColumn);
QPixmap pixmap((*imgObj)->imgPath);
pixmap = pixmap.scaled(200, 200, Qt::KeepAspectRatio, Qt::SmoothTransformation);
QLabel * picLabel = new QLabel(this);
picLabel->setPixmap(pixmap);
layout->addWidget(picLabel, 2, currentColumn);
++currentColumn;
}
QPushButton * saveBtn = new QPushButton("Save", this);
connect(saveBtn, SIGNAL(released()),this, SLOT(Save()));
layout->addWidget(saveBtn, 3, 0, -1, 1);
setLayout(layout);
But it doesn't seem to be a good idea to add those widgets horizontally like that. What would happen if there are 100 items in this vector? You should investigate in using something like a QScrollArea or modifying the UI to give your client the best way to view and edit those (but without more context it seems difficult to give your more advice).