How to set Qt QStateMachine animation duration - c++

I'm trying to learn the Qt framework. My QStateMachine code does the correct thing (pressing the button makes the chat window popup change size).
I can't change the speed of the animation to get a nice visual transition.
Any suggestions?
Here's the code:
MainWindow::MainWindow()
{
widget.setupUi( this );
// chat window - Chat button opens
ChatWindowClosedState = new QState();
ChatWindowOpenState = new QState();
ChatWindowOpenGeometry = widget.groupBox->geometry();
ChatWindowClosedGeometry = widget.pushButton->geometry();
ChatWindowClosedGeometry.translate( -ChatWindowClosedGeometry.width(), 0 );
ChatWindowClosedState->assignProperty( widget.groupBox, "geometry", ChatWindowClosedGeometry );
ChatWindowOpenState->assignProperty( widget.groupBox, "geometry", ChatWindowOpenGeometry );
ChatWindowCloseTransition = ChatWindowClosedState->addTransition( widget.pushButton, SIGNAL( clicked() ), ChatWindowOpenState );
ChatWindowCloseAnimation = new QPropertyAnimation( widget.pushButton, "geometry" );
ChatWindowCloseAnimation->setDuration( 5000 );
ChatWindowCloseTransition->addAnimation( ChatWindowCloseAnimation );
ChatWindowOpenTransition = ChatWindowOpenState->addTransition( widget.pushButton, SIGNAL( clicked() ), ChatWindowClosedState );
ChatWindowOpenAnimation = new QPropertyAnimation( widget.pushButton, "geometry" );
ChatWindowOpenAnimation->setDuration( 5000 );
ChatWindowOpenTransition->addAnimation( ChatWindowOpenAnimation );
machine = new QStateMachine( this );
machine->addState( ChatWindowClosedState );
machine->addState( ChatWindowOpenState );
machine->setInitialState( ChatWindowClosedState );
machine->start();
}

The code
ChatWindowOpenAnimation = new QPropertyAnimation( widget.pushButton, "geometry" );
should be
ChatWindowOpenAnimation = new QPropertyAnimation( widget.groupBox, "geometry" );
The animation was being applied to the wrong widget.

Related

QGraphicsLinearLayout not aligning widgets as expected

I have got a QGraphicsScene that I have added a QGraphicsWidget.
I initially setup the widget this way
AGraphicsWidget::AGraphicsWidget( QGraphicsItem* parent, QGraphicsScene* scene )
: QGraphicsWidget( parent )
, m_mainLayout( new QGraphicsLinearLayout( Qt::Vertical ) )
, m_titleLabel( new QLabel( "Title" ) )
, m_executionPin( new NodeExecutionPin() )
{
setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
setGraphicsItem( this );
setFlag( ItemIsMovable, true );
m_mainLayout->setInstantInvalidatePropagation( true );
auto* labelProxy = scene->addWidget( m_titleLabel );
auto* secondLabel = scene->addWidget( new QLabel( "Subtitle" ) );
auto* button = scene->addWidget( new QPushButton( "Another" ) );
m_mainLayout->addItem( labelProxy );
m_mainLayout->addItem( secondLabel );
m_mainLayout->addItem( button );
setLayout( m_mainLayout );
}
This setup does not do what I expect which would be a vertically aligned set of widgets instead I get this
However when I add a text edit as the last element like this
AGraphicsWidget::AGraphicsWidget( QGraphicsItem* parent, QGraphicsScene* scene )
: QGraphicsWidget( parent )
, m_mainLayout( new QGraphicsLinearLayout( Qt::Vertical ) )
, m_titleLabel( new QLabel( "Title" ) )
, m_executionPin( new NodeExecutionPin() )
{
setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
setGraphicsItem( this );
setFlag( ItemIsMovable, true );
m_mainLayout->setInstantInvalidatePropagation( true );
auto* labelProxy = scene->addWidget( m_titleLabel );
auto* secondLabel = scene->addWidget( new QLabel( "Subtitle" ) );
auto* button = scene->addWidget( new QPushButton( "Another" ) );
auto* edit = scene->addWidget( new QTextEdit() );
m_mainLayout->addItem( labelProxy );
m_mainLayout->addItem( secondLabel );
m_mainLayout->addItem( button );
m_mainLayout->addItem( edit );
setLayout( m_mainLayout );
}
It works as expected, I get the nice vertical layout, I get the same non alignment as above if I try and nest any QGraphicsLinearLayouts any further where they will overlap each other, what is happening here?
Thanks in advance.

QScrollArea with dynamically resizing subWidgets

So I have something like the following layout in my Qt Application.
QScroll Area
- QSrollArea's InternalWidget
-QVBoxLayout
-Layout 1
- some items
- QTableView
-Layout 2
- some items
- QTableView
The contents of the QTableViews is changing dynamically, and what i want is that each table view to be as large as it has to be( without progressbars and without empty space ). I have written a function to calculate the appropriate size of a table. The problem is that when i dynamically resize one of the TableViews it goes behind the second view( and what should happen is that the whole second layout be moved bellow the first ). Furthermore when shrink the table view there is an empty space left between it and the second layout.
Here is the code when i arrange the widgets:
#include "Widget.h"
#include <QVBoxLayout>
#include <QLabel>
#include <QTableView>
#include <QStringBuilder>
#include <QHeaderView>
#include <QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent),
m_tableView1( 0 ),
m_tableView2( 0 ),
m_model1( 0 ),
m_model2( 0 ),
m_numberOfRowsEdit( 0 )
{
this->resize( 300, 520 );
QVBoxLayout* mainLayout = new QVBoxLayout( this );
QScrollArea* mainArea = new QScrollArea();
//mainArea->setWidgetResizable( true );
QWidget* scrollAreaWidget = new QWidget;
scrollAreaWidget->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Expanding );
QVBoxLayout* scrollAreaWidgetLayout = new QVBoxLayout( scrollAreaWidget );
scrollAreaWidgetLayout->setSizeConstraint( QLayout::SetMinAndMaxSize );
QVBoxLayout* firstSubLayout = new QVBoxLayout;
QLabel* label = new QLabel( "Label 1" );
m_tableView1 = new QTableView;
firstSubLayout->addWidget( label );
firstSubLayout->addWidget( m_tableView1 );
scrollAreaWidgetLayout->addLayout( firstSubLayout );
QVBoxLayout* secondSubLayout = new QVBoxLayout;
QLabel* label2 = new QLabel( "Label 2" );
m_tableView2 = new QTableView;
secondSubLayout->addWidget( label2 );
secondSubLayout->addWidget( m_tableView2 );
scrollAreaWidgetLayout->addLayout( secondSubLayout );
mainArea->setWidget( scrollAreaWidget );
mainLayout->addWidget( mainArea );
// Utility for dynamically changing rows
QHBoxLayout* hLayout = new QHBoxLayout;
QLabel* numberOfRowsLabel = new QLabel( "Number of rows" );
m_numberOfRowsEdit = new QLineEdit;
QPushButton* numberOfRowsButton = new QPushButton( "Apply" );
connect( numberOfRowsButton, SIGNAL(clicked()), SLOT(onApplyButtonPressed()) );
hLayout->addWidget( numberOfRowsLabel );
hLayout->addWidget( m_numberOfRowsEdit );
hLayout->addWidget( numberOfRowsButton );
m_model1 = new QStandardItemModel( this );
m_tableView1->setModel( m_model1 );
m_model2 = new QStandardItemModel( this );
m_tableView2->setModel( m_model2 );
mainLayout->addLayout( hLayout );
}
Widget::~Widget()
{
}
QSize Widget::calculateTableDesiredSize( QTableView* const table ) {...}
void Widget::onApplyButtonPressed()
{
bool ok = false;
const int rowCount = m_numberOfRowsEdit->text().toInt( &ok );
if ( !ok )
{
return;
}
this->initModel( m_model1, rowCount );
}
// inits model with rowCount rows
void Widget::initModel( QStandardItemModel* const model, const int rowCount )
void Widget::resizeTable( QTableView* const table )
You should use setFixedHeight() instead of resize() to set table height. Also you should addStretch() to scrollAreaWidgetLayout after all its items.

Qt exit when hiding window

I have a MainWindow which calls the LoginWindow in the constructor. The LoginDialog has a button to create an account which will create a QDialog.
I wanted to hide the LoginDialog while the Dialog for the new account is showing but somehow it crashes.
When I remove the first and last line of the function which hides and shows the LoginDialog it's absolutely fine. Why does it crash with hide() and show() are called ?
void LoginDialog::createAccount()
{
// (-> will cause crash later) hide(); //Hides LoginDialog
QDialog dlg;
dlg.setGeometry( this->x(), this->y(), this->width(), this->height() );
QWidget* centralWidget = new QWidget( &dlg );
QVBoxLayout* l = new QVBoxLayout( centralWidget );
dlg.setLayout( l );
QLineEdit *dlgUser = new QLineEdit( centralWidget );
QLineEdit *dlgPass = new QLineEdit( centralWidget );
dlgPass->setEchoMode( QLineEdit::Password );
l->addWidget( new QLabel( tr("Username :"), centralWidget ) );
l->addWidget( dlgUser );
l->addWidget( new QLabel( tr("Password :"), centralWidget ) );
l->addWidget( dlgPass );
l->addWidget( new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, centralWidget ) );
if( dlg.exec() != QDialog::Rejected )
{
;
}
delete centralWidget;
// (-> will cause crash later) show(); //Show LoginDialog again
}
There are no errors, it just crashes unexpectedly and sometimes it exits with code (0).
When analyzing with the debugger and really going through every single step it doesn't crash. The LoginDialog will be shown and it's not going to crash.
I don't get the purpose of your centralWidget in the dialog? I don't think it is needed at all, and you can assemble your widgets directly in the dialog. I would rewrite your code in this way:
void LoginDialog::createAccount()
{
QDialog dlg;
dlg.setGeometry( this->x(), this->y(), this->width(), this->height() );
QLineEdit *dlgUser = new QLineEdit( &dlg );
QLineEdit *dlgPass = new QLineEdit( &dlg );
dlgPass->setEchoMode( QLineEdit::Password );
QVBoxLayout* l = new QVBoxLayout;
l->addWidget( new QLabel( tr("Username :"), &dlg ) );
l->addWidget( dlgUser );
l->addWidget( new QLabel( tr("Password :"), &dlg ) );
l->addWidget( dlgPass );
l->addWidget( new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, &dlg ) );
dlg.setLayout( l );
if( dlg.exec() != QDialog::Rejected )
{
// Do something.
}
}

Change QStackedLayout Index with QPushButton not QComboBox

I do this in Qt Creator. I want to change my QStackedLayout with only QPushButton, not QComboBox. Is this possible? Anybody has implemented this? I got many example from Qt Documentation but all examples use QComboBox (now QPushButton like I need). This is my code:
#mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
Dialog::Dialog()
{
QVBoxLayout *mainlayout = new QVBoxLayout;
QVBoxLayout *layouta = new QVBoxLayout;
QVBoxLayout *layoutb = new QVBoxLayout;
QPushButton *tombola = new QPushButton("A");
QPushButton *tombolb = new QPushButton("B");
QPushButton *tombolc = new QPushButton("C");
QFrame *framea = new QFrame;
QFrame *frameb = new QFrame;
QStackedLayout *stackia = new QStackedLayout;
layouta->addWidget(tombola);
layoutb->addWidget(tombolb);
framea->setLayout(layouta);
frameb->setLayout(layoutb);
framea->setMinimumSize(88,88);
frameb->setMinimumSize(88,88);
//building frame
framea->setFrameShape(QFrame::StyledPanel);
framea->setFrameShadow(QFrame::Raised);
frameb->setFrameShape(QFrame::StyledPanel);
frameb->setFrameShadow(QFrame::Raised);
//get c button smaller
tombolc->setMaximumWidth(33);
stackia->addWidget(framea);
stackia->addWidget(frameb);
stackia->addWidget(tombolc);
mainlayout->addLayout(stackia);
QPushButton *tombold = new QPushButton("D");
mainlayout->addWidget(tombold);
setLayout(mainlayout);
connect(tombold, SIGNAL(clicked()), stackia, SLOT(setCurrentIndex(1))); //CONNECTOR
}
RESULT
Qt Creator says:
Object::connect: No such slot QStackedLayout::setCurrentIndex(1)
What is my mistake?
At second chance after searching and asking for 4 days, I have changed my connect() and function code into:
CONNECTOR:
connect(tombold, SIGNAL(clicked()), stackia, SLOT(change_stack()));
FUNCTION:
void Dialog::change_stack()
{
stackia->setCurrentIndex(1);
}
RESULT
But Qt Creator says:
Object::connect: No such slot QStackedLayout::change_stack()
and immediately the window closed.
At my sight, my code has error. But I don't know what error so I can't change QStackLayout content/page into another page. What is my mistake? I believe this is actually quite simple but I just don't know where is the error.
Any suggestion?
You should add change_stack function to your Dialog class and connect to it like this:
class Dialog : public QWidget
{
...
private slots:
void change_stack();
private:
QStackedLayout *stackia;
}
Dialog::Dialog
{
...
connect(tombold, SIGNAL(clicked()), this, SLOT(change_stack()));
...
}
void Dialog::change_stack()
{
stackia->setCurrentIndex(1);
}
Concerning
connect(tombold, SIGNAL(clicked()), stackia, SLOT(setCurrentIndex(1)));
A slot can only have as many parameters or less parameters than a signal.
E.g. you can do
connect( sender , SIGNAL( somethingHappened( const QString& ) ),
receiver, SLOT ( doSomething ( const QString& ) ) );
and you can do
// connect signal and ignore the parameter
connect( sender , SIGNAL( somethingHappened( const QString& ) ),
receiver, SLOT ( doSomethingElse ( ) ) );
but you cannot do
// this will not work
connect( sender , SIGNAL( somethingElseHappened( ) ),
receiver, SLOT ( doSomething ( const QString& ) ) );
What you probably want is something like this:
Dialog::Dialog
{
...
// This must be a member variable
_stackia = new QStackedLayout();
tombola->setProperty( "tabpage", 1 );
tombolb->setProperty( "tabpage", 2 );
tombolc->setProperty( "tabpage", 3 );
connect( tombola, SIGNAL( clicked () ),
this , SLOT ( tombol_clicked() ) );
connect( tombolb, SIGNAL( clicked () ),
this , SLOT ( tombol_clicked() ) );
connect( tombolc, SIGNAL( clicked () ),
this , SLOT ( tombol_clicked() ) );
}
// This must be defined as slot in the header
void Dialog::tombol_clicked()
{
int index = sender()->property( "tabpage" ).toInt();
_stackia->setCurrentIndex( index );
}

Visual artifacts when style is applied to overlapping Qt PushButtons

In the application I'm developing, I've got sets of QPushButtons that overlay each other like so:
resize(300, 300);
QRect geometry( 100, 100 , 100 , 100 );
m_button[0] = new QPushButton( this );
m_button[0]->setGeometry( geometry );
m_button[0]->setText( "Button 1" );
m_button[1] = new QPushButton( this );
m_button[1]->setGeometry( geometry );
m_button[1]->setText( "Button 2" );
m_button[1]->raise();
Result:
But when the follows style is added at application level
QApplication app(argc, argv);
app.setStyleSheet( "QPushButton{ border-width: 1px; border-color: blue; border-style: solid;}" );
the buttons are rendered as like so:
What would be the reason for this artefact, and how can I workaround it.
Information about my application
The overlapping buttons are keys belonging to different character sets of a virtual keyboard. These keys are raised or lowered depending on the current character set.
You want to use a QStackedWidget and place your QPushButtons in that stack. Then you just need to raise the button you want with QStackedWidget::setCurrentIndex or QStackedWidget::setCurrentWidget.
Edit: sample code:
resize(300, 300);
QStackedWidget* stack = new QStackedWidget(this);
stack->setGeometry( 100, 100 , 100 , 100 );
m_button[0] = new QPushButton( this );
m_button[0]->setText( "Button 1 );
stack->addWidget(m_button[0]);
m_button[1] = new QPushButton( this );
m_button[1]->setText( "Button 2" );
stack->addWidget(m_button[1]);
stack->setCurrentWidget(m_button[1]); //or stack->setCurrentIndex(1);