• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Dopasowanie rozmiaru kontrolek

VPS Starter Arubacloud
0 głosów
246 wizyt
pytanie zadane 17 maja 2017 w C i C++ przez niezalogowany
Problem standardowy, ale mimo to nie znalazłem w internecie żadnej konkretnej, dobrej odpowiedzi. Otóż chcę by wraz ze zmianą rozmiaru okna zmieniał się rozmiar kontrolek na nim.

Wiem, że są różne layouty, ale one sprawiają, że dopasowuje się tylko wysokość lub tylko szerokość, a przecież użytkownik może ciągnąć za róg okienka i wtedy obydwa te wymiary kontrolek powinny się odpowiednio dopasować.

Poza tym te layouty nie do końca działają tak jak bym chciał. Owszem, umożliwiają miłe dla oka rozmieszczanie widżetów, ale nie pomagają zbytnio w dopasowywaniu rozmiarów. Chyba, że ktoś kliknie na formatkę prawym przyciskiem i wybierze "Rozmieść" ale wtedy wszystkie widżety będą miały ten sam rodzaj rozmieszczenia co nie zawsze jest pożądane.

Ja np. chciałbym w swoim programie mieć 5 przycisków, jeden pod drugim, gdzie współrzędne dobieram tak żeby te przyciski znajdowały się idealnie pośrodku okna. I teraz gdy zmieniam rozmiar okna to proporcjonalnie powinny zmieniać się rozmiary tych przycisków, a nie przybywać dużo pustego miejsca na oknie.

4 odpowiedzi

0 głosów
odpowiedź 17 maja 2017 przez Garath Nowicjusz (180 p.)
Jak przejdziesz do okna "Design", to pod standardowym paskiem menu pojawia się dodatkowy z opcjami. Są tam ustawienia nazwane jako "Layout". Jeśli interfejs nimi pogrupujesz, to wtedy sam się skaluje w zależności od rozmiaru okna. Tutaj jest to dość dobrze wytłumaczone:
https://www.youtube.com/watch?v=2edb0VOkx-k
0 głosów
odpowiedź 22 maja 2017 przez niezalogowany
edycja 22 maja 2017

Poszperałem trochę w dokumentacji i googlach i napisałem klasę odpowiedzialną za wyłapywanie zdarzenia zmiany rozmiaru.

Plik resizingcapturer.h

#ifndef RESIZINGCAPTURER_H
#define RESIZINGCAPTURER_H

#include <QObject>
#include <QEvent>

class ResizingCapturer : public QObject
{
    Q_OBJECT

public:
    QList <QWidget *> widgets;

    ResizingCapturer(QList <QWidget *> childrenList);
protected:
    bool eventFilter(QObject *obj, QEvent *event);
};

#endif // RESIZINGCAPTURER_H

 

Plik resizingcapturer.cpp

#include "resizingcapturer.h"
#include <QDebug>
#include <QObject>
#include <QEvent>
#include <QResizeEvent>
#include <QMouseEvent>
#include <QWidget>

ResizingCapturer::ResizingCapturer(QList <QWidget *> childrenList)
{
    widgets = childrenList;
}

bool ResizingCapturer::eventFilter(QObject *obj, QEvent *event)
{
    if (event->type() == QEvent::Resize)
    {
        QResizeEvent *resizeEvent = static_cast <QResizeEvent *>(event);
        for(int i=0; i<widgets.size(); i++)
        {
            qDebug()<<"i= "<<i;

            // MainWindow sizes
            int Width_1 = resizeEvent->oldSize().width();
            int Height_1 = resizeEvent->oldSize().height();
            int Width_2 = resizeEvent->size().width();
            int Height_2 = resizeEvent->size().height();

            // widget old sizes
            int width_1 =  widgets[i] -> width();
            int height_1 = widgets[i] -> height();

            // new widget geometry
            int x = widgets[i] -> x() * Width_2 / Width_1;
            int y = widgets[i] -> y() * Height_2 / Height_1;
            int width_2 = width_1 * Width_2 / Width_1;
            int height_2 = height_1 * Height_2 / Height_1;

            widgets[i] -> setGeometry(x,y,width_2,height_2);

            qDebug()<<"Resizing\n";

            qDebug()<<"Width_1 = "<<Width_1;
            qDebug()<<"Height_1= "<<Height_1;
            qDebug()<<"Width_2 = "<<Width_2;
            qDebug()<<"Height_2= "<<Height_2;

            qDebug()<<"width_1 = "<<width_1;
            qDebug()<<"height_1= "<<height_1;
            qDebug()<<"x = "<<x;
            qDebug()<<"y = "<<y;
            qDebug()<<"width_2 = "<<width_2;
            qDebug()<<"height_2 = "<<height_2;
        }

        return true;
    }

    // standard event processing
    return QObject::eventFilter(obj, event);
}

 

main.cpp

#include "mainwindow.h"
#include "keypresseater.h"
#include "resizingcapturer.h"
#include <QApplication>
#include <QWidget>
#include <QLineEdit>
#include <QDebug>
#include <QList>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;

    QPushButton *przycisk = new QPushButton("Siemanko", &w);
    przycisk->setGeometry(10,10,120,20);
    przycisk->show();

    // pobieram wszystkie dzieci głównego okna
    QList <QWidget *> childrens = w.findChildren <QWidget *> ();

    qDebug() << "childrens[0]->width() " << childrens[0]->x();
    qDebug() << "childrens[0]->width() " << childrens[0]->y();
    qDebug() << "childrens[0]->width() " << childrens[0]->width();
    qDebug() << "childrens[0]->width() " << childrens[0]->height();

    ResizingCapturer *resizingCapturer = new ResizingCapturer(childrens);

    w.show();
    w.installEventFilter(resizingCapturer);

    return a.exec();
}

 

Tylko problem w tym, że za pojedyncze zdarzenie zmiany rozmiaru uznaje się zmianę tego rozmiaru choćby o jeden piksel. Czyli jeśli okno główne ma szerokość 500, a ja je rozciągnę na tysiąc to nie jest tak, że:

oldSize().width() = 500 a size().width() = 1000

tylko:

oldSize().width() = 500 a size().width() = 501

oldSize().width() = 501 a size().width() = 502

...

Czyli zdarzenie się wywołuje 500 razy i moje wzory, gdzie wymnażam dotychczasowe rozmiary widżetów przez skalę podobieństwa nowego okna do starego nie zadziałają bo wtedy jest:

roz_widzeta = roz_widzeta * 501/500;

nawet gdy zmienię wszystkie inty na np. floaty (zrobiłem to przed chwilą) to i tak nic nie daje bo

501/500 to 1.002

więc dla buttona o szerokości 200 mamy:

roz_widzeta = 200 * 1.002 czyli 200.4

a zmienna roz_widzeta musi być typu int więc część ułamkowa zostanie obcięta i będzie nadal 200.

Z kolei jak zmniejszam to mam np

roz_widzeta = 200 * 0.998 czyli 199.6 czyli tak naprawdę 199 co oznacza, że rozmiary kontrolek zmieniają się o tyle samo co okna głównego i w końcu mają któryś wymiar równy 0 i znikają (np. zmniejszę szerokość okna z 500 na 481 to lineEdit o szerokości 20 będzie miał szerokość 1, przeciągnę jeszcze trochę to zniknie).

Myślałem o sprawdzaniu zdarzenia MousePressButton i kombinowaniu z tym, ale ono nie jest aktywne gdy kursor myszki jest na brzegu tylko na oknie. Kodzę w Qt od niedawna. Ktoś ma jakieś sugestie jak można poprawić mój kod?

0 głosów
odpowiedź 23 maja 2017 przez niezalogowany
Jest ktoś obeznany z tematem, kto pomoże?
0 głosów
odpowiedź 24 maja 2017 przez Bondrusiek Maniak (61,440 p.)

Witam,

najlepiej do Tego typu zadań użyj layoutów. W Twoim problemie użyłbym metody QResizeEvent(QResizeEvent *) ta funkcja będzie dodawać wysokość oraz szerokość. Tutaj przykład:

void Klasa::resizeEvent(QResizeEvent * /* event */)
{
int extraWidth = width() - minimumWidth();
int extraHeight = height() - minimumHeight();
namedLabel->setGeometry(9, 9, 50, 25);
namedLineEdit->setGeometry(65, 9, 100 + extraWidth, 25);
lookInLabel->setGeometry(9, 40, 50, 25);
lookInLineEdit->setGeometry(65, 40, 100 + extraWidth, 25);
subfoldersCheckBox->setGeometry(9, 71, 156 + extraWidth, 23);
tableWidget->setGeometry(9, 100, 156 + extraWidth,
50 + extraHeight);
messageLabel->setGeometry(9, 156 + extraHeight, 156 + extraWidth,
25);
findButton->setGeometry(171 + extraWidth, 9, 85, 32);
stopButton->setGeometry(171 + extraWidth, 47, 85, 32);
closeButton->setGeometry(171 + extraWidth, 84, 85, 32);
helpButton->setGeometry(171 + extraWidth, 149 + extraHeight, 85,
32);
}

 

Podobne pytania

0 głosów
2 odpowiedzi 3,236 wizyt
pytanie zadane 1 stycznia 2018 w HTML i CSS przez ThePatrykOOO Dyskutant (8,400 p.)
0 głosów
1 odpowiedź 678 wizyt
pytanie zadane 5 maja 2015 w C i C++ przez marcelo89 Nowicjusz (160 p.)
0 głosów
1 odpowiedź 234 wizyt

92,839 zapytań

141,780 odpowiedzi

320,855 komentarzy

62,171 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...