Qt5 Nowe okno wysuwane z belki tytułu widgets

0

Witam serdecznie
Co chce uzyskać
Okno główne i po naciśnięciu przycisku
Wysuwane okno z belki tytułu w dół - coś podobnego kiedyś często występowało w aplikacjach na Mac OS.
Taki efekt wysuniętego frame lub coś podobnego, kontrolki chce by automatycznie były poblokowane jak w modalny oknie.
Czy ma ktoś pomysł jak coś takiego zrealizować ewentualnie może podesłać jakieś linki pomocne do zrealizowania tego zadania.
Piszę pod Qt 5 oraz w widgets
Z qml mam problemy z prostymi rzeczami wiec fajnie jak by to było w widgets albo będę musiał interfejs przepisać Pod qml ale w nim raczkuje wiec wolałbym jednak Widgets.
Dzięki wielkie za pomoc.

0

A czy to teraz tak nie działa?
W sensie okna dialogowe Qt pokazywane jako modalne, np coś takiego:

void MainWindows::showDialog() {
     setSomeColor(QColorDialog::getColor(getSomeColor(), this, tr("Magic color"));
}

z tego co pamiętam powinno mieć takie zachowanie na MacOS.
Mogę się mylić. Sprawdzę jak będę miał więcej czasu.

0

Nie sprawdzę teraz bo z telefonu piszę, ale może to będzie punkt zaczepienia: https://doc.qt.io/qt-5/qpropertyanimation.html

0

@alagner: Właśnie kolego skończyłem na szybko coś robić, zawsze jest tak że jak umieszczę zapytanie to coś wynajdę.
Faktycznie chodziło o QPropertyAnimation
Dokładnie zrobiłem coś takiego w oknie widgetu

int x = (parent->width()/2)-(this->width()/2);
    QRect rec = QRect(x,this->y(),this->width(),this->height());


    QPropertyAnimation *anim = new QPropertyAnimation(this,"geometry");
    anim->setDuration(250);
    anim->setStartValue(QRect(rec.x(),rec.y(),rec.width(),0));
    anim->setEndValue(rec);
    anim->start();

Jeszcze nie działa to za cudownie być może dlatego że mam to bezpośrednio tak:

Form::Form(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Form)
{
    ui->setupUi(this);
    int x = (parent->width()/2)-(this->width()/2);
    QRect rec = QRect(x,this->y(),this->width(),this->height());


    QPropertyAnimation *anim = new QPropertyAnimation(this,"geometry");
    anim->setDuration(250);
    anim->setStartValue(QRect(rec.x(),rec.y(),rec.width(),0));
    anim->setEndValue(rec);
    anim->start();
}

Brakuje mi płynności, może jeszcze by pasowało dowalić trochę przenikania tyle że jeszcze nie wiem czy mogę to zrobić na jednym QPropertyAnimation tzn. bym mógł operować geometry oraz widocznością okna opacity.

0

Zawsze możesz wziąć timer i manipulować daną property (albo kilkoma) w jego „ticku” ale to trochę hardkor mi się wydaje ;)

0

@alagner: Wszystko prawie fajnie mam coś takiego

void Form::closeEvent(QCloseEvent *event)
{
    qDebug() << "Close";
    event->ignore();
    QPropertyAnimation *anim = new QPropertyAnimation(this,"geometry");
    anim->setDuration(250);
    anim->setStartValue(geometry());
    anim->setEndValue(QRect(x(),y(),width(),0));
    anim->start(QAbstractAnimation::DeleteWhenStopped);


}

void Form::showEvent(QShowEvent *event)
{
    qDebug() << "Show";
    int x = (_parent->width()/2)-(this->width()/2);
    QRect rec = QRect(x,this->y(),this->width(),this->height());


    QPropertyAnimation *anim = new QPropertyAnimation(this,"geometry");
    anim->setDuration(250);
    anim->setStartValue(QRect(rec.x(),rec.y(),rec.width(),0));
    anim->setEndValue(rec);
    anim->start(QAbstractAnimation::DeleteWhenStopped);
}

Tylko że po czym sprawdzić że zakończyła się animacja ?? by wywołać event->accept();

0

w qt patrz zawsze z czego dziedziczy i na pełną listę API(List of All Members)
https://doc.qt.io/qt-5/qabstractanimation.html#finished

0

@revcorey: Mam jeszcze jeden kłopot dotyczący opacity tzn.
Samo jak wywołać wiem ale jak to połączyć razem z QPropertyAnimation nie mam pojęcia, może wy koledzy coś podpowiecie ??

void Form::closeEvent(QCloseEvent *event)
{
    qDebug() << "Close";
    event->ignore();
    QPropertyAnimation *anim = new QPropertyAnimation(this,"geometry");
    anim->setDuration(1500);
    anim->setStartValue(geometry());
    anim->setEndValue(QRect(x(),y(),width(),0));
    //anim->setEasingCurve(QEasingCurve::OutElastic);
    anim->setEasingCurve(QEasingCurve::InOutElastic);
    anim->start(QAbstractAnimation::DeleteWhenStopped);


}

void Form::showEvent(QShowEvent *event)
{
    qDebug() << "Show";
    int x = (_parent->width()/2)-(this->width()/2);
    QRect rec = QRect(x,this->y(),this->width(),this->height());

    QParallelAnimationGroup *group = new QParallelAnimationGroup(this);

    // Move
    QPropertyAnimation *anim = new QPropertyAnimation(this,"geometry");
    anim->setDuration(1500);
    anim->setStartValue(QRect(rec.x(),rec.y(),rec.width(),0));
    anim->setEndValue(rec);
    anim->setEasingCurve(QEasingCurve::OutElastic);

    group->addAnimation(anim);

    // opacity
    /*
    QGraphicsOpacityEffect *op= new QGraphicsOpacityEffect(this);
    setAutoFillBackground(true);
    op->setOpacity(0.50); // #0 to 1 will cause the fade effect to kick in
    setGraphicsEffect(op);
    */
    QPropertyAnimation *anim2 = new QPropertyAnimation(this,"opacity");
    anim2->setDuration(1500);
    anim2->setStartValue(0.00);
    anim2->setEndValue(1.00);
    //anim2->setKeyValueAt(0, 1);
    //anim2->setKeyValueAt(0.5, 0);
    //anim2->setKeyValueAt(1, 1);

    group->addAnimation(anim2);
    group->start(QAbstractAnimation::DeleteWhenStopped);

}

By zmienić przeźroczystość QWidget trzeba zastosować coś takiego

QGraphicsOpacityEffect *op= new QGraphicsOpacityEffect(this);
    setAutoFillBackground(true);
    op->setOpacity(0.50); // #0 to 1 will cause the fade effect to kick in
    setGraphicsEffect(op);

Ale jak to draństwo połączyć z QPropertyAnimation ??

0

EDIT: klasa bazowa, tj. QVariantAnimation nie emituje valueChanged co "klatkę" animacji? Jeśli tak, to może się do tego sygnału podepnij?
EDIT2: w sumie te aplikacja to chyba już ma, to jest terminal "wyjeżdżający" w stylu konsoli w Quake'u https://github.com/KDE/yakuake/tree/master/app
może Ci się przyda.

TO PONIŻEJ JEST ŹLE. Tzn. niepotrzebnie chyba powtarzam funkcję sygnału valueChanged...
Na szybko, nie wiem czy ładnie:

class MyAnimation : public QPropertyAnimation
{
Q_OBJECT;
signals:
  updated();//czy co tam chcesz przekazywac...
public:
  using QPropertyAnimation::QPropertyAnimation;
protected:
  void QPropertyAnimation::updateCurrentValue(const QVariant &value) override
  {
    QPropertyAnimation::updateCurrentValue(const QVariant &value);
   emit updated();
  }
};

no i ten sygnał podłączasz pod OpacityEffect jakoś?

0

Dzięki panowie ale udało mi się podobnie jak kombinowałem wcześniej.
Nie jest to idealny efekt jaki chciałem uzyskać ale i tak jest nie źle.
Ciekawe czy na windowsie będzie ten sam efekt

void Form::closeEvent(QCloseEvent *event)
{
    qDebug() << "Close";
    event->ignore();
    QPropertyAnimation *anim = new QPropertyAnimation(this,"geometry");
    anim->setDuration(1500);
    anim->setStartValue(geometry());
    anim->setEndValue(QRect(x(),y(),width(),0));
    //anim->setEasingCurve(QEasingCurve::OutElastic);
    anim->setEasingCurve(QEasingCurve::InOutElastic);
    anim->start(QAbstractAnimation::DeleteWhenStopped);


}

void Form::showEvent(QShowEvent *event)
{
    qDebug() << "Show";
    int x = (_parent->width()/2)-(this->width()/2);
    QRect rec = QRect(x,this->y(),this->width(),this->height());

    QParallelAnimationGroup *group = new QParallelAnimationGroup(this);

    // Move
    QPropertyAnimation *anim = new QPropertyAnimation(this,"geometry");
    anim->setDuration(2500);
    anim->setStartValue(QRect(rec.x(),rec.y(),rec.width(),0));
    anim->setEndValue(rec);
    anim->setEasingCurve(QEasingCurve::OutElastic);

    group->addAnimation(anim);

    // opacity
    QGraphicsOpacityEffect *eff = new QGraphicsOpacityEffect(this);
    setGraphicsEffect(eff);
    QPropertyAnimation *anim2 = new QPropertyAnimation(eff,"opacity");

    anim2->setDuration(1500);
    anim2->setStartValue(0.20);
    anim2->setEndValue(1.00);


    anim2->setEasingCurve(QEasingCurve::InCubic);
    //anim2->setEasingCurve(QEasingCurve::OutElastic);


    group->addAnimation(anim2);
    group->start(QAbstractAnimation::DeleteWhenStopped);


}

Panowie Dzięki za pomoc.

0

Panowie mam jeszcze jeden kłopot, coś szukam na około
mianowicie
Wywołuje swój efekt w konstruktorze zaraz po poleceniu rysowania okna ```
ui->setupUi(this);

Pobieram oryginalne położenia kontrolek i pokazuje mi głupoty.
Rozmieszczam kontrolki poprzez Layouty
Mam automatyczne rozmieszczanie it.
Czyli Width i height w zależności od wielkości okienka.
Próbuje pobrać ui->kontrolka->geometry()
Niestety pokazuje mi głupoty.
Po załadowaniu okna całkowicie, i przyciśnięciu przycisku uzyskuję zupełnie inne położenia i wymiary.

Jest jakaś funkcja którą trzeba wywołać by wymusić rozmieszczenie kontrolek ??
3

Takie rzeczy to nie w konstruktorze, ale w reimplementowanym showEvent() się robi - wtedy rozmiary i położenie elementów jest już policzone, a widget gotowy do pokazania..

0

Tak kolego chociaż to nie miało większego znaczenia, powodem dziwnego zachowania są style
w pliku main.cpp
w sekcji main
ładuje style z pliku

QFile styleFile( ":/darkstyle/darkstyle" );
    styleFile.open( QFile::ReadOnly );
    QString style( styleFile.readAll() );
    a.setStyleSheet( style );

Gdy za komentuje style wszystko działa właściwie, czyli nie tylko muszę w sekcji showEvent ale również muszę oczekiwać na załadowanie styli bo inaczej kaplica, ale jak tego dokonać jeszcze nie udało mi się doszukać..
Dzięki za naprowadzenie finalnie oparłem to o dialog - same zawartości robie sobie w QWidget.
Wszystko pięknie śmiga dzięki.

1 użytkowników online, w tym zalogowanych: 0, gości: 1