Qt State Machine Transition in a Layout - c++

Well, I am developing a Qt application and I want use the Qt State Framework to make some animations.
First:
How I can animate a group of buttons contained in a horizontal layout, into another vertical layout, by using state a transition?
Second:
How I can show a widget when in a state? For example a menu: When the user clicks a button in the menu, the widget (that previously has been hidden with widget->hide()) is shown...???
This is a code example:
boxInsert = new BoxInsert(this);
boxInsert->hide ();
btn1 = new QPushButton("Introducir", this);
btn2 = new QPushButton("Informe", this);
btn3 = new QPushButton("Salir", this);
QStateMachine *machine = new QStateMachine(this);
QState *st1 = new QState(machine);
st1->setObjectName ("menuMode");
st1->assignProperty (btn1, "pos", QPointF(center - btn1->width () / 2, 20));
st1->assignProperty (btn2, "pos", QPointF(center - btn1->width () / 2, 40));
st1->assignProperty (btn3, "pos", QPointF(center - btn1->width () / 2, 60));
st1->assignProperty (boxInsert, "visible", QVariant(false));
QState *st2 = new QState(machine);
st2->setObjectName ("barMode");
st2->assignProperty (btn1, "pos", QPointF(40, 0));
st2->assignProperty (btn2, "pos", QPointF(40, 0));
st2->assignProperty (btn3, "pos", QPointF(40, 0));
st1->assignProperty (boxInsert, "visible", QVariant(true));
machine->setInitialState (st1);
QAbstractTransition *t1 = st1->addTransition (btn1, SIGNAL(clicked()), st2);
//QSequentialAnimationGroup *sq1 = new QSequentialAnimationGroup;
//sq1->addPause (250);
t1->addAnimation (new QPropertyAnimation(btn1, "pos"));
t1->addAnimation (new QPropertyAnimation(btn2, "pos"));
t1->addAnimation (new QPropertyAnimation(btn3, "pos"));
t1->addAnimation (new QPropertyAnimation(boxInsert, "visible"));
machine->start ();

It is something like when you will start machine it will change color of a button that may indicate this is clicked then perform something that is linked with your signal so its linked slot will be executed.
s0->addTransition(s1);
s1->assignProperty(ui->pushButton,"styleSheet","background-color:rgb(255,0,0);");
s1->addTransition(s2);
s2->addTransition(ui->pushButton,SIGNAL(clicked()),s0);
QStateMachine m;
m.addState(s0);
m.addState(s1);
m.addState(s2);
m.setInitialState(s0);
To make visible a widget add an state transition like this:
s1->assignProperty(MyWid,"visible", true);
and add transition in s0 for state s1.

First: Move widgets from horizontal layout to vertical using stateMachine? Don't know how to do it, really.
Second: You can implement widget with your own transparency property, that works with QGraphicsEffect:
class myWidget
{
//your methods
Q_PROPERTY(double alpha READ alpha WRITE setAlpha)
double mAlpha;
double alpha() {return mAlpha;}
void setAlpha(double a);
QGraphicsOpacityEffect* eff;
}
make QGraphicsEffect working in setAlpha() method:
void myWidget::setAlpha(double a)
{
mAlpha = a;
if(mAlpha < 0.0)
mAlpha = 0.0;
if(mAlpha > 1.0)
mAlpha = 1.0;
if(mAlpha == 0)
{
this->hide();
}
else
{
this->show();
eff->setOpacity(mAlpha);
}
this->update();
}
And, of course, set QGraphicsOpacityEffect to your widget in constructor:
eff = new QGraphicsOpacityEffect(this);
eff->setOpacity(mAlpha);
this->setGraphicsEffect(eff);
Then you can work with your alpha property in QState:
QState* s1 = new QState(mainState);
s1->assignProperty(mywidget, "alpha", 1.0);
//and so on...

Related

QListWidget items consistent positioning problem

I'm new to Qt framework. In new application I want to create list with customised items. These items are quite simple and must contain title label, thumbnail and description label (picture here)
For now I don't want to play with custom drawing and all that stuff becuase I think it's easier to do items I want with proper widget/layout so I decided to use QListwidget and subclassed QAbstractItemModel (KeyframeModel) and QListWidgetItem (TileWidgetItem).
After some coding it looks how I wanted but strange thing happens to QListWidget (grid mode) when I add some items. In my case a QListWidget is resizable (due to how it's embedded inside main layout) and number of columns should be dependent on list and items width. Items are fixed size (at least for now).
But when I resize the list one of the items at some list's width is misaligned and not I don't know what's going on. Below are te screenshots from app:
Pic. 1 List initial state (right after start)
Pic. 2 List after resizing #1
Pic. 3 List after resizing #2
Resizing #2 is a few pixels wider than resizing #1 and resizing #1 is hard to get (border case) - few pixels width less and I've got 2 columns (it's okay) but some pixels more and I end up with case #2.
In all cases number of columns is okay.
Sometimes also last item is misaligned after program start right-away like here (right after start like in pic. 1 but as you can see different result despite same list width).
I wonder why is it so inconsistent after start-up.
Do I missing something? Do I must do some parts in different way?
Or is it just some glitches in debug mode?
Below I post some code:
Application:
// Source file
QtGuiApplication1::QtGuiApplication1(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
//--------------------------------------------------------------------------------
// Add elements to the list
TileWidgetItem *item = new TileWidgetItem();
item->setData(TileWidgetItem::TileRole::TitleRole, QVariant("Long title"));
item->setData(TileWidgetItem::TileRole::DescriptionRole, QVariant("My long info"));
item->setText("My super text");
qDebug() << "Widget size hint: " << item->sizeHint();
ui.listWidget_moves->addItem(item);
item->updateView();
TileWidgetItem *item1 = new TileWidgetItem();
item1->setData(TileWidgetItem::TileRole::TitleRole, QVariant("Item #2"));
item1->setText("Tile #2");
ui.listWidget_moves->addItem(item1);
item1->updateView();
TileWidgetItem *item2 = new TileWidgetItem();
ui.listWidget_moves->addItem(item2);
item2->updateView();
TileWidgetItem *item3 = new TileWidgetItem();
ui.listWidget_moves->addItem(item3);
item3->updateView();
//--------------------------------------------------------------------------------
// Adjust cell size
QSize cellSize;
for (uint i = 0; i < ui.listWidget_moves->count(); i++)
{
int dim = ui.listWidget_moves->item(i)->sizeHint().height();
if (dim > cellSize.height())
cellSize.setHeight(dim);
dim = ui.listWidget_moves->item(i)->sizeHint().width();
if (dim > cellSize.width())
cellSize.setWidth(dim);
}
ui.listWidget_moves->setGridSize(cellSize);
}
Item widget:
// Source file
constexpr int MAX_THUMB_SIZE = 100;
TileWidgetItem::TileWidgetItem(QListWidget *listview)
: QListWidgetItem(listview, ItemType::UserType)
{
/* Prepare main widget */
QWidget *view = new QWidget();
view->setObjectName("tile");
view->setStyleSheet(
"QWidget#tile { margin: 4 8; background-color: #404040; border: 1 solid rgba(0,0,0,30%); border-radius: 4px }\n"
"QWidget#tile::hover { border: 1 solid #EEE; background-color: #484848 }\n"
"QWidget#tile[selected=true] { background-color: #00F }"
);
//-----------------------------------------------------------
/* Prepare layout */
QVBoxLayout *layout = new QVBoxLayout();
layout->setSizeConstraint(QLayout::SizeConstraint::SetFixedSize);
//-----------------------------------------------------------
/* Prepare title with icon */
QHBoxLayout *titleLayout = new QHBoxLayout();
QLabel *titleIcon = new QLabel();
titleIcon->setObjectName("titleIcon");
titleIcon->setStyleSheet("background-color: black");
titleIcon->setFixedSize(QSize(16, 16));
titleLayout->addWidget(titleIcon);
QLabel *title = new QLabel("Title");
title->setObjectName("title");
title->setMinimumWidth(60);
title->setStyleSheet("background-color: #800;");
titleLayout->addWidget(title);
QWidget *titleWidget = new QWidget();
titleWidget->setStyleSheet("background-color: #080");
titleWidget->setLayout(titleLayout);
layout->addWidget(titleWidget);
//-----------------------------------------------------------
/* Prepare thumbnail */
QLabel *thumbnail = new QLabel();
thumbnail->setObjectName("thumbnail");
thumbnail->setStyleSheet("background-color: black; border: 1 solid #F00");
thumbnail->setFixedSize(QSize(MAX_THUMB_SIZE, MAX_THUMB_SIZE * 0.7f));
thumbnail->setPixmap(QPixmap("Resources/moto.jpg").scaledToWidth(MAX_THUMB_SIZE));
layout->addWidget(thumbnail);
//-----------------------------------------------------------
/* Preparing additional info */
QLabel *description = new QLabel("Description");
description->setObjectName("description");
//description->setToolTip("Custom info tip");
description->setContentsMargins(4, 2, 4, 2);
layout->addWidget(description);
//-----------------------------------------------------------
view->setLayout(layout);
_customView = view;
_titleView = title;
_descriptionView = description;
setSizeHint(_customView->sizeHint());
updateView();
}
TileWidgetItem::~TileWidgetItem()
{
}
void TileWidgetItem::setData(int role, const QVariant &value)
{
QListWidgetItem::setData(role, value);
if (value.type() == QVariant::Type::String)
{
if (role == TileRole::TitleRole)
{
this->_titleView->setText(value.toString());
}
else if (role == TileRole::DescriptionRole)
{
this->_descriptionView->setText(value.toString());
}
setSizeHint(_customView->sizeHint());
}
}
void TileWidgetItem::updateView()
{
if (listWidget() != nullptr)
{
listWidget()->setItemWidget(this, this->_customView);
}
}
// Header file
class TileWidgetItem : public QListWidgetItem
{
public:
enum TileRole
{
TitleRole = Qt::UserRole + 1,
DescriptionRole,
ThumbnailRole
};
public:
TileWidgetItem(QListWidget *listview = nullptr);
~TileWidgetItem();
void setData(int role, const QVariant &value) override;
void updateView();
QWidget *customView() const { return _customView; };
QString getTitle() const { return _titleView->text(); };
QString getInfo() const { return _descriptionView->text(); };
private:
QWidget *_customView;
QLabel *_titleView;
QLabel *_descriptionView;
};
Platform: Windows 10
Qt version: 5.14.2
IDE: Visual Studio 2019 (with Qt VS Tools)
In the end I just used custom delegates which solved problems.
I wanted to overuse system and in I was defeated :)

(several qdockWidget) QWidget::repaint: Recursive repaint detected kernel\qwidget.cpp: 5557

I need your help please!
I have 8 dockwidget in my Qmainwindow without a centralwidget, when I try to move, float, and undock dockwidget that contains a 3D view, the program crash with segmentation fault!
I remain at your disposal for more information, thanks a lot!
SUB_WIN_3D_VIEW.cpp
/* -----------------------
* ----------------------- */
#include "sub_win_3dview.h"
#include <QtWidgets/QAction>
#include <iostream>
#include <QDesktopServices>
SUB_WIN_3D_VIEW::SUB_WIN_3D_VIEW(Mainwindow const& p) : QDockWidget(),mainwindow_ins(p)
{
ui.setupUi(this);
this->setWindowTitle("3D view");
// Initiate the 3D scene
view.defaultFrameGraph()->setClearColor(QColor("#FFC0CBD9")); // light blue
widget = QWidget::createWindowContainer(&view);
view.renderSettings()->pickingSettings()->setPickMethod(Qt3DRender::QPickingSettings::TrianglePicking);
// Initiate the root entity (all the other entities of the scene should
// inherit it to be part of the 3D scene
rootEntity = new Qt3DCore::QEntity;
input = new Qt3DInput::QInputAspect;
view.setRootEntity(rootEntity);
view.registerAspect(input);
// Get the default camera entity from view
cameraEntity = view.camera();
// Set Z the be the vertical axis
cameraEntity->setUpVector(QVector3D(0, 0, 1));
// Initiate the camera controller
MyOrbitCameraController *camController = new MyOrbitCameraController(rootEntity);
camController->setCamera(cameraEntity);
camController->setLookSpeed(-300);
camController->setLinearSpeed(12);
// Initiate the light entity with its components below
lightEntity = new Qt3DCore::QEntity(rootEntity);
Qt3DRender::QPointLight *lightPoint = new Qt3DRender::QPointLight(lightEntity);
lightPoint->setColor("white");
lightPoint->setIntensity(1);
Qt3DCore::QTransform *lightTransform = new Qt3DCore::QTransform(lightEntity);
lightTransform->setTranslation(QVector3D(20, 20, 20));
lightEntity->addComponent(lightPoint);
lightEntity->addComponent(lightTransform);
// Initiate the modifier of the scene
modifier = new SceneModifier(rootEntity, cameraEntity);
modifier->pb_sl_reset();
view3d->widget->setMinimumSize(QSize(200, 100));
QSizePolicy view3d_siz(QSizePolicy::Expanding, QSizePolicy::Expanding);
widget->setSizePolicy(view3d_siz);
// Add the widget to a layout attached to the UI
ui.verticalLayout_2->addWidget(widget);
modifier->pb_sl_loadModel("simple");
connect(ui.Reload, SIGNAL(clicked(bool)),this, SLOT(reload_clicked()));
connect(ui.btn_CubeMiddle, SIGNAL(clicked(bool)),this, SLOT(cubeMiddle_clicked()));
connect(ui.btn_ObjUp, SIGNAL(clicked(bool)),this, SLOT(objUp_clicked()));
connect(ui.btn_ObjLeft, SIGNAL(clicked(bool)),this, SLOT(objLeft_clicked()));
connect(ui.btn_ObjRight, SIGNAL(clicked(bool)),this, SLOT(objRight_clicked()));
connect(ui.btn_ShowAxis, SIGNAL(clicked(bool)),this, SLOT(showAxis_clicked()));}
SUB_WIN_3D_VIEW::~SUB_WIN_3D_VIEW()
{
}
void SUB_WIN_3D_VIEW::reload_clicked()
{
// Reload's button simply load the same model again
modifier->pb_sl_loadModel("simple");
}
void SUB_WIN_3D_VIEW::cubeMiddle_clicked()
{
modifier->pb_sl_cameraMiddle();
}
void SUB_WIN_3D_VIEW::objUp_clicked()
{
modifier->pb_sl_cameraUp();
}
void SUB_WIN_3D_VIEW::objLeft_clicked()
{
modifier->pb_sl_cameraLeft();
}
void SUB_WIN_3D_VIEW::objRight_clicked()
{
modifier->pb_sl_cameraRight();
}
void SUB_WIN_3D_VIEW::showAxis_clicked()
{
modifier->pb_sl_enableRef(ui.btn_ShowAxis->isChecked());
}
#include "moc_sub_win_3dview.cpp"
Errors:
In file ....\include/QtCore/../../src/corelib/global/qglobal.h, line
770: Out of memory Invalid parameter passed to C runtime function.
Invalid parameter passed to C runtime function. QWidget::repaint:
Recursive repaint detected
createDIB: CreateDIBSection failed. Invalid parameter passed to C
runtime function. Invalid parameter passed to C runtime function.
QWaitCondition: Destroyed while threads are still waiting
I solved the problem by modifying the qml code, before it was like that :
file.h
QQuickWidget *m_quickWidget_gauge_2;
QObject *object_gauge_2 ;
QQuickWidget *m_quickWidget_gauge_3;
QObject *object_gauge_3 ;
QQuickWidget *m_quickWidget_gauge_4;
QObject *object_gauge_4 ;
file.cpp
//QQuickWidget : actuator number 1
m_quickWidget_gauge_1 = new QQuickWidget(this) ;
m_quickWidget_gauge_1->setSource(QUrl("qrc:/Resources/res/gauge.qml"));
m_quickWidget_gauge_1->setResizeMode(QQuickWidget::SizeRootObjectToView);
m_quickWidget_gauge_1->setMinimumHeight(30);
m_quickWidget_gauge_1->setMinimumWidth(150);
m_quickWidget_gauge_1->setAttribute(Qt::WA_AlwaysStackOnTop);
m_quickWidget_gauge_1->setClearColor(Qt::transparent);
ui.horizontalLayout_al_1->addWidget(m_quickWidget_gauge_1, 1, Qt::AlignTop);
//QQuickWidget : actuator number 2
m_quickWidget_gauge_2 = new QQuickWidget(this) ;
m_quickWidget_gauge_2->setSource(QUrl("qrc:/Resources/res/gauge.qml"));
m_quickWidget_gauge_2->setResizeMode(QQuickWidget::SizeRootObjectToView);
m_quickWidget_gauge_2->setMinimumHeight(30);
m_quickWidget_gauge_2->setMinimumWidth(150);
m_quickWidget_gauge_2->setAttribute(Qt::WA_AlwaysStackOnTop);
m_quickWidget_gauge_2->setClearColor(Qt::transparent);
ui.horizontalLayout_al_2->addWidget(m_quickWidget_gauge_2, 1, Qt::AlignTop);
//QQuickWidget : actuator number 3
[....]
I made these changes and it works!!
file.h
QQuickView *m_qmlview_gauge_1;
QQuickView *m_qmlview_gauge_2;
QQuickView *m_qmlview_gauge_3;
file.cpp
m_qmlview_gauge_1 = new QQuickView(QUrl("qrc:/Resources/res/qml/actuator_gauge.qml"));
m_qmlview_gauge_1->setColor(QColor(Qt::white));
QWidget *container = QWidget::createWindowContainer(m_qmlview_gauge_1);
container->setSizePolicy(QSizePolicy::Preferred,QSizePolicy::Expanding);
ui.verticalLayout_11->addWidget(container);
m_qmlview_gauge_2 = new QQuickView(QUrl("qrc:/Resources/res/qml/actuator_gauge.qml"));
m_qmlview_gauge_2->setColor(QColor(Qt::white));
QWidget *container_1 = QWidget::createWindowContainer(m_qmlview_gauge_2);
container_1->setSizePolicy(QSizePolicy::Preferred,QSizePolicy::Expanding);
ui.verticalLayout_12->addWidget(container_1);
m_qmlview_gauge_3 = new QQuickView(QUrl("qrc:/Resources/res/qml/actuator_gauge.qml"));
m_qmlview_gauge_3->setColor(QColor(Qt::white));
QWidget *container_2 = QWidget::createWindowContainer(m_qmlview_gauge_3);
container_2->setSizePolicy(QSizePolicy::Preferred,QSizePolicy::Expanding);
ui.verticalLayout_13->addWidget(container_2);
i still not understand why the old code cause this crash, it worked well before !!

QWidget Overflow

I have a main QGridLayout on the dialog I'm working on. It's split into content-containers (QWidgets with their own QVBoxLayout) of varying sizes, each assigned a particular number of grid-columns within the grid layout (depending on their needs).
Each content-container holds some buttons. Some of these buttons should span across 2 content-containers. The way I'm trying to achieve this is by overflowing these 2-container buttons outside their layout, while keeping the size of the content-containers the same (what it was allocated according to the number of columns within the grid). I have no idea how to go about this, because either the size of the containers changes, or the QWidget doesn't overflow.
Is there a way to set some sort of overflow property on the button, or do I have to just place the buttons on the grid? I'm trying to avoid doing this because I think it could be messy once new requirements arise and I'll have to recalculate their positioning.
Here is an image of what I'm trying to do:
Here is the relevant code:
ModeDialog::ModeDialog(MainWindow *pMainWindow)
: XDialog(pMainWindow, tr("Operating Mode"), true)
{
XDialog::AddButton(tr("Exit"), QDialogButtonBox::AcceptRole);
ConstructStylingFromTemplates();
CSettings* Settings = pMainWindow->GetSettings();
QString SlotString1, SlotString2;
QGridLayout* mp_MainLayout = new QGridLayout();
mp_MainLayout->setContentsMargins(10, 30, 10, 20);
// Construct Channel Group Layouts with Channel Containers
for (int i = 0; i < 3; i++)
{
switch(i)
{
case 0: { SlotString1 = "A"; SlotString2 = "B"; break; }
case 1: { SlotString1 = "C"; SlotString2 = "D"; break; }
case 2: { SlotString1 = "E"; SlotString2 = "F"; break; }
}
QHBoxLayout* ChannelGroupLayout = new QHBoxLayout();
if (CSettings_RR::IsE1T1Channel(Settings, i*2))
{
AddChannelToChannelGroup(ChannelGroupLayout, SlotString1);
AddChannelToChannelGroup(ChannelGroupLayout, SlotString2);
}
else if(CSettings_RR::IsPtpChannel(Settings, i*2))
{
AddChannelToChannelGroup(ChannelGroupLayout, SlotString1);
}
else if(CSettings_RR::IsOtaChannel(Settings, i*2))
{
AddChannelToChannelGroup(ChannelGroupLayout, SlotString1);
}
else
{
continue;
}
mp_MainLayout->addLayout(ChannelGroupLayout, 0, i*2, 1, 2);
}
SetContentLayout(mp_MainLayout);}
void ModeDialog::AddChannelToChannelGroup(QHBoxLayout* ChannelGroupLayout, QString SlotString)
{
QVBoxLayout* ChannelLayout = new QVBoxLayout();
// Add Label to Channel Layout
XLabel* ChannelLabel = new XLabel("Channel " + SlotString, m_textSize, true, Qt::AlignCenter | Qt::AlignVCenter, this);
ChannelLabel->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
ChannelLayout->addWidget(ChannelLabel);
// Add Container to Channel Layout
QWidget* ChannelContainer = new QWidget();
ChannelContainer->setStyleSheet(m_styleSheetChannelContainer);
ChannelLayout->addWidget(ChannelContainer);
//WIP - add buttons to container
QVBoxLayout* ChannelContainerLayout = new QVBoxLayout();
ChannelContainer->setLayout(ChannelContainerLayout);
XPushButton* ModeButton = new XPushButton(tr("CLOCK"), 160, 40, this, true);
ChannelContainerLayout->addWidget(ModeButton);
//WIPEND
// Add Channel Layout to Channel Group Layout
ChannelGroupLayout->addLayout(ChannelLayout);
}
It is not possible to overflow using QWidgets.
But it is possible with QML.
By default, items will overflow and you have to manage their positions and sizes (and z-index to tell who overlaps who) : http://doc.qt.io/qt-5/qtquick-positioning-topic.html
You have to use QML layouts or set the item's parent property clip to true to avoid the overflow.
There is no way to overflow widgets in Qt, not even if you don't use a layout. A widget will always be limited to its parent's bounds.

Qt Scroll Area does not add in scroll bars

Hi guys I have to dynamically create push buttons depending on user inputs, therefore if user gives a large input number the widget containing the push buttons has to have the ability to scroll up and down. For this reason I am using QScrollArea. I generate the template in Qt designer and the UIC generates the code for me after which I add in my part which should handle dynamic creation of push buttons. However, I can not seem to get the vertical scroll bars to appear. Here is the relevant part of the code.
verticalWidget = new QWidget(FWHMWorkflowDialog);
verticalWidget->setObjectName(QString::fromUtf8("verticalWidget"));
verticalWidget->setMinimumSize(QSize(150, 0));
verticalWidget->setMaximumSize(QSize(150, 16777215));
verticalLayout_5 = new QVBoxLayout(verticalWidget);
verticalLayout_5->setObjectName(QString::fromUtf8("verticalLayout_5"));
scrollArea = new QScrollArea(verticalWidget);
scrollArea->setObjectName(QString::fromUtf8("scrollArea"));
scrollArea->setMaximumSize(QSize(150, 16777215));
scrollArea->setWidgetResizable(true);
scrollAreaWidgetContents = new QWidget();
scrollAreaWidgetContents->setObjectName(QString::fromUtf8("scrollAreaWidgetContents"));
scrollAreaWidgetContents->setGeometry(QRect(0, 0, 130, 432));
numberOfSlices = numberSlices;
for (int i = 0; i < numberOfSlices; i++)
{
QWidget *horizontalWidget = new QWidget(scrollAreaWidgetContents);
horizontalWidget->setMaximumSize(150,40);
horizontalWidget->setGeometry(QRect(0, i*40, 150, 40));
hWidgetList.push_back(horizontalWidget);
QHBoxLayout *hLayout = new QHBoxLayout(horizontalWidget);
hLayoutList.push_back(hLayout);
hLayout->setSizeConstraint(QLayout::SetMinimumSize);
hLayout->setContentsMargins(-1, 1, -1, 1);
QPushButton *pushButton = new QPushButton(horizontalWidget);
pushButtonList.push_back(pushButton);
QString temp = QString("m_sliceButton").arg(i);
pushButtonList[i]->setObjectName(temp);
pushButtonList[i]->setGeometry(QRect(10, 20+i*40, 98, 27));
hLayout->addWidget(pushButton);
QCheckBox *checkBox = new QCheckBox(horizontalWidget);
checkBoxList.push_back(checkBox);
temp = QString("m_checkBox").arg(i);
checkBoxList[i]->setObjectName(temp);
checkBoxList[i]->setEnabled(true);
checkBoxList[i]->setGeometry(QRect(110, 20+i*40, 21, 22));
hLayout->addWidget(checkBox);
}
scrollArea->setWidget(scrollAreaWidgetContents);
//scrollArea->setWidgetResizable(true);
verticalLayout_5->addWidget(scrollArea);
The output window always looks like the following.
In this example the input by the user is 25 however you can see that the 21st button is cut off and 4 other buttons are not visible.
The size window problem occurring after scroll functionality started working.
You need to add your horizontalWidget to a vertical widget like so:
QVBoxLayout* vLayout = new QVBoxLayout();
for (int i = 0; i < numberOfSlices; i++)
{
QWidget *horizontalWidget = new QWidget();
vLayout->addWidget(horizontalWidget);
....
}
scrollAreaWidgetContents->setLayout(vLayout);
You second problem looks like it comes from this line:
scrollArea = new QScrollArea(verticalWidget);
You're adding scrollArea directly to verticalWidget, but to get it to lay out the way you want you need to put it in a layout. Try the following instead:
QVBoxLayout* l = new QVBoxLayout();
l->addWidget(sliceLabel); // or whatever you call it
l->addWidget(scrollArea);
l->addWidget(clearButton); // again, your name here
verticalWidget->setLayout(l);
Try playing around with the QScrollBarPolicy.
http://doc.qt.digia.com/qt/qabstractscrollarea.html#horizontalScrollBarPolicy-prop
I'm guessing that the default behavior isn't working because there is something strange going on with layouts.

stop event propagation from QGraphicsItem to QGraphicsScene QT

I have an Qgraphicsscene implemented as a class, then i use QGraphicsScene::mousePressEvent to add a QGraphicsRectItem, this item have also an implementation for QGraphicsRectItem::mousePressEvent, the problem is that the event in the rect item is propagated to the scene and when i click it is added a new rect item, but i want is that the events inside this item do not propagate to the scene, i try event->accept but the event is propagated, how i cant do that? thanks for any help.
here is my qgraphicsscene code:
#include "imageview.h"
ImageView::ImageView(QWidget *parent){
scene = new ImageScene(this);
setScene(scene);
//this->setMouseTracking(true);
this->setInteractive(true);
}
ImageScene::ImageScene(QWidget *parent){
current = NULL;
selection = new QRubberBand(QRubberBand::Rectangle,parent);
selection->setGeometry(QRect(10,10,20,20));
setSceneRect(0,0,500,500);
}
void ImageScene::mousePressEvent(QGraphicsSceneMouseEvent *event){
QGraphicsScene::mousePressEvent(event);
/*IGNORING THIS EVENT FROM QGRAPHICSRECTITEM*/
cout<<"image view"<<endl;
if(this->selectedItems().length() == 0){ /*WORKS BUT IN SOME IMPLEMENTATION IS A PROBLEM (WHEN I DELETE THE ITEM WITH A DELETE BUTTON THE EVENT IS FIRED AND ADD A NEW ITEM .)*/
origin = event->scenePos();
selection->show();
}
}
void ImageScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event){
if(selection->isVisible() && selection->rect().width() >= 20 && selection->rect().height() >= 20){
QGraphicsScene::mouseReleaseEvent(event);
ResizableRect * rselection = new ResizableRect();
//selection->origin = event->scenePos();
//selection->grabMouse();
cout<<"add"<<endl;
this->addItem(rselection);
rselection->setPos(selection->pos());
rselection->setRect(0,0,selection->rect().width(),selection->rect().height());
}
selection->hide();
}
void ImageScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event){
QGraphicsScene::mouseMoveEvent(event);
if(selection->isVisible()){
QPoint rorigin(origin.x(),origin.y());
int xdes = event->scenePos().x();
int ydes = event->scenePos().y();
xdes = xdes > 0? xdes:0;
ydes = ydes > 0? ydes:0;
xdes = xdes < this->width()?xdes:this->width();
ydes = ydes < this->height()?ydes:this->height();
QPoint rdest(xdes,ydes);
selection->setGeometry(QRect(rorigin,rdest).normalized());
}
}
Opposite to QWidgets, QGraphicsScene catches events before child items. It is described on Qt documentation.
For correctly work with that, use reimplementation of QGraphicsView instead of QGraphcisScene.
Reimplement mousePressEvent there.
At that moment you can determine item under mouse pointer.
it it is there - you can just call QGraphicsView::mousePressEvent();
It it is not - use your implementation for add new item.
It also allows you to separate behavior of different views.