crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

 
Ответить в данную темуНачать новую тему
coo_zoo
  опции профиля:
сообщение 15.10.2012, 0:17
Сообщение #1


Новичок


Группа: Новичок
Сообщений: 4
Регистрация: 8.3.2010
Пользователь №: 1517

Спасибо сказали: 0 раз(а)




Репутация:   0  


Здравствуйте,
Итак не много замучился вопросом, как же остановить рекурсию :). Коллективный разум он большой и умный, думаю поможет.
Идея следующая сохранение пропорций окна при изменении его размеров.
mainwindow.h
Раскрывающийся текст
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QMessageBox>
#include <QResizeEvent>
#include <QDebug>

namespace Ui {
    class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();


private:
    Ui::MainWindow *ui;
    void resizeEvent ( QResizeEvent * event );
};
#endif // MAINWINDOW_H


main.cpp
Раскрывающийся текст
#include <QtGui/QApplication>
#include "mainwindow.h"

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

    return a.exec();
}


mainwindow.cpp
Раскрывающийся текст
#include "mainwindow.h"
#include "ui_mainwindow.h"


MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}


void  MainWindow::resizeEvent ( QResizeEvent * event )
   {
    if (event)
    {
    int sizeheight=event->size().height();
    int oldsizeheight=event->oldSize().height();
    int sizewidth=event->size().width();
    int oldsizewidth=event->oldSize().width();
    ui->label->setText(QString::number(sizeheight));
    int newheight=(sizewidth)*9/16;
    ui->label_2->setText(QString::number(sizewidth));

        if(sizewidth!=oldsizewidth)
        {
            setMaximumHeight(newheight);
            setMinimumHeight(newheight);
        }
    }
   }


Главное окно имеет всего лишь два элемента label и label_2 при изменении размеров окна туда выводятся высота и ширина.
Проблема в том что по понятным причинам вызывается рекурсия, которая кстати по непонятным причинам :) прекращается тогда, когда окно возвращается к исходным размерам, к тем что были до ресайза.
Прошу помощи и дельного совета как "отсеять" рекурсию?
У меня была идея если не нажата левая кнопка мыши значит прекратить. Но в силу своего нубизма не понимаю как это сделать, хотя вроде интуитивно догадываюсь что как-то фильтрами, но мои попытки не увенчались успехом.
Буду благодарен за помощь.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Алексей1153
  опции профиля:
сообщение 15.10.2012, 8:27
Сообщение #2


фрилансер
******

Группа: Участник
Сообщений: 2943
Регистрация: 19.6.2010
Из: Обливион
Пользователь №: 1822

Спасибо сказали: 215 раз(а)




Репутация:   34  


наверное, вот так

class MainWindow : public QMainWindow
{
    Q_OBJECT

       bool m_bIsInResizeEvent;//++++


MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent)
   ,ui(new Ui::MainWindow)
   ,m_bIsInResizeEvent(false)//++++
{
    ui->setupUi(this);
}



void  MainWindow::resizeEvent ( QResizeEvent * event )
{
    if (event)
    {
        if(!m_bIsInResizeEvent)//++++
        {
            m_bIsInResizeEvent=true;//++++
            //------------------------
            {
                int sizeheight=event->size().height();
                int oldsizeheight=event->oldSize().height();
                int sizewidth=event->size().width();
                int oldsizewidth=event->oldSize().width();
                ui->label->setText(QString::number(sizeheight));
                int newheight=(sizewidth)*9/16;
                ui->label_2->setText(QString::number(sizewidth));

                if(sizewidth!=oldsizewidth)
                {
                    setMaximumHeight(newheight);
                    setMinimumHeight(newheight);
                }
            }
            //------------------------
            m_bIsInResizeEvent=false;//++++
        }
    }
}


Сообщение отредактировал Алексей1153 - 15.10.2012, 8:28
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
coo_zoo
  опции профиля:
сообщение 15.10.2012, 21:00
Сообщение #3


Новичок


Группа: Новичок
Сообщений: 4
Регистрация: 8.3.2010
Пользователь №: 1517

Спасибо сказали: 0 раз(а)




Репутация:   0  


Цитата(Алексей1153 @ 15.10.2012, 8:27) *
наверное, вот так

Идея очень хороша :) но...
но когда попробовал
то такое впечатление что это не совсем рекурсия, как будто триггер на срабатывание ивента на ресайз срабатывает после самого ивента, то-есть на момент срабатывания флаг уже в статусе ложь.

ЗЫ.
Интересное поведение под виндой: на уменьшение размера срабатывает, даже оригинальный код - хорошо, глючит только на увеличение, уменьшает окно к исходному размеру.
А под линуксом, в иксах, ещё более интересное: ресайз работает нормально, как на увеличение так и на уменьшение, но иногда сбоит что выражается в некрасивом побликивании :)
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Алексей1153
  опции профиля:
сообщение 16.10.2012, 14:50
Сообщение #4


фрилансер
******

Группа: Участник
Сообщений: 2943
Регистрация: 19.6.2010
Из: Обливион
Пользователь №: 1822

Спасибо сказали: 215 раз(а)




Репутация:   34  


если в слоте ресайза менять размер, то он сам себя вызывает новым сигналом ресайза. Вероятно, петля разрывается, когда размер устанавливается такой же, какой только что был (при наличии ООС на размер)

в винде WM_WINDOWPOSCHANGED ведёт себя так же (правда тОрмоза в виде установки такого же размера , как мне помнится, нет)



Сообщение отредактировал Алексей1153 - 16.10.2012, 14:51
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
ornelius
  опции профиля:
сообщение 17.10.2012, 11:56
Сообщение #5


Новичок


Группа: Новичок
Сообщений: 4
Регистрация: 17.10.2012
Пользователь №: 3565

Спасибо сказали: 0 раз(а)




Репутация:   0  


Проверка if(sizewidth!=oldsizewidth) -- это суть условие выхода из рекурсии. В данном случае проверяется, что ширина окна не изменилась. А должно проверяться, что пропорция окна соответствует требуемой.

Вот этот код всегда выходит из рекурсии:
class FixedWidget : public QWidget
{
public:
    explicit FixedWidget() : QWidget() {}
private:
    void resizeEvent(QResizeEvent *e)
    {
        qDebug("In resize");
        if (size().width() != size().height())
            resize(size().width(), size().width());
    }
};
int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    FixedWidget fw;
    fw.show();
    return app.exec();
}

Первый раз resizeEvent вызывается, когда пользователь изменяет размер, второй раз -- в результате ресайза. Но во второй раз resize уже не вызывается --> рекурсия кончилась.

Но такой вариант неправильный -- размер окна меняется после того, как пользователь отпустил мышь. Лучший вариант -- сделать внутренний виджет, для него перегрузить
int QWidget::heightForWidth ( int w ) const, потом засунуть в Layout и в главное окно.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0


RSS Рейтинг@Mail.ru Текстовая версия Сейчас: 6.5.2025, 21:25