Russian Qt Forum

Qt => Вопросы новичков => Тема начата: stas3638 от Ноябрь 08, 2015, 19:24



Название: Не выполняется метод QMainWindow::close()
Отправлено: stas3638 от Ноябрь 08, 2015, 19:24
Привет, ребят. Столкнулся с такой вот проблемой, что не закрывается главное окно. Вот в чем суть: в некоторых ситуациях, после закрытия одного из окон, должно закрыться главное окно (MainMenuWnd). Условия закрытия выполняются (спасибо qDebug), но само окно продолжает функционировать. В чем может быть проблема. Вот текст:

Код:
void MainMenuWnd::LoginFinished()
{
    if(currentEmployee == NULL)
    {
        qDebug() << "close MainWnd";
        //this->setHidden(false);
        this->close();
    }
    else
    {/*some code*/}
}
Буду благодарен за любые возможные ответы)


Название: Re: Не выполняется метод QMainWindow::close()
Отправлено: Vamireh от Ноябрь 08, 2015, 19:28
Ну вообще такое может быть, если это из конструктора вызывается, например.


Название: Re: Не выполняется метод QMainWindow::close()
Отправлено: stas3638 от Ноябрь 08, 2015, 19:45
Ну вообще такое может быть, если это из конструктора вызывается, например.
Тут вызов происходит не из конструктора, это отдельная функция.


Название: Re: Не выполняется метод QMainWindow::close()
Отправлено: stas3638 от Ноябрь 08, 2015, 20:23
Проблема решена посредством плохого кода:
Код:
    QTimer::singleShot(0, this, SLOT(close()));
Может кто-то подскажет более хорошее решение, а то все равно сталкиваюсь с проблемой мигания окна перед закрытием (спасибо методам setHidden). Убрал бы уже скрытие окна, но именно такова постановка задачи на курсовом.


Название: Re: Не выполняется метод QMainWindow::close()
Отправлено: Bepec от Ноябрь 08, 2015, 21:10
qApp->quit()? :)

На деле сложно ответить что у вас не так, т.к. работоспособность метода close зависит от положения в классе. Покажите код, мы вам подскажем решение (ну или скажем "фу какой код" :D)


Название: Re: Не выполняется метод QMainWindow::close()
Отправлено: lit-uriy от Ноябрь 09, 2015, 06:40
stas3638, а если закрывать окно щёлкая по крестику, то оно корректно себя ведёт?


Название: Re: Не выполняется метод QMainWindow::close()
Отправлено: stas3638 от Ноябрь 09, 2015, 15:44
stas3638, а если закрывать окно щёлкая по крестику, то оно корректно себя ведёт?
Да, в добавку, есть еще одно кнопка, которая позволяет закрывать окно, там все так же корректно работает.


Название: Re: Не выполняется метод QMainWindow::close()
Отправлено: Zerkin от Ноябрь 10, 2015, 12:46
Понятно, что close() работает так:

Цитировать
First it sends the widget a QCloseEvent. The widget is hidden if it accepts the close event. If it ignores the event, nothing happens. The default implementation of QWidget::closeEvent() accepts the close event.

Вы closeEvent()  не переопределяли?


Название: Re: Не выполняется метод QMainWindow::close()
Отправлено: Vamireh от Ноябрь 10, 2015, 15:21
В общем, минимально рабочий нерабочий пример в студию.


Название: Re: Не выполняется метод QMainWindow::close()
Отправлено: stas3638 от Ноябрь 10, 2015, 19:34
Понятно, что close() работает так:

Цитировать
First it sends the widget a QCloseEvent. The widget is hidden if it accepts the close event. If it ignores the event, nothing happens. The default implementation of QWidget::closeEvent() accepts the close event.

Вы closeEvent()  не переопределяли?

Нет, не переопределял. Если переопределять, то что именно там надо делать? (не надо кидать код, просто словами)


Название: Re: Не выполняется метод QMainWindow::close()
Отправлено: stas3638 от Ноябрь 10, 2015, 19:49
В общем, минимально рабочий нерабочий пример в студию.

LoginWnd.h
Код:
class LoginWnd : public QDialog
{
    Q_OBJECT

public:
    explicit LoginWnd(CEmployee* employee, QWidget *parent = 0);
    ~LoginWnd();

private slots:
    void on_EnterBtn_clicked();

    void CloseWnd();//вот в этом слоте происходит удаление указателя
private:
    Ui::LoginWnd *ui;

    CEmployee *employee;
};

LoginWnd.cpp
Код:
LoginWnd::LoginWnd(CEmployee *employee1, QWidget *parent) :
    QDialog(parent),
    ui(new Ui::LoginWnd)
{
    //...
    employee = employee1;
}
//...
void LoginWnd::CloseWnd()
{
    delete employee;
    employee = NULL;
    this->close();
//обнулил, закрыл, здесь все корректно работает, никаких багов не наблюдалось
}

MainMenuWnd.h
Код:
class MainMenuWnd : public QMainWindow
{
    Q_OBJECT
public:
    explicit MainMenuWnd(QWidget *parent = 0);
    virtual ~MainMenuWnd();
private:
    Ui::MainMenuWnd *ui;
    CEmployee *currentEmployee;
    LoginWnd* LogWnd;
private slots:
    void LoginFinished();//вызывается сразу же, как окно авторизации закрылось
};

MainMenuWnd.cpp
Код:
MainMenuWnd::MainMenuWnd(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainMenuWnd)
{
    ui->setupUi(this);

    currentEmployee = new CEmployee();
//...
    LogWnd = new LoginWnd(currentEmployee);
    connect(
                LogWnd,
                SIGNAL(finished(int)),
                this,
                SLOT(LoginFinished())
                );
    this->hide();
    LogWnd->exec();
}
//...
void MainMenuWnd::LoginFinished()
{
    if(currentEmployee == 0)
    {
        this->setHidden(false);
        this->close();
        //вот тут окно не закрывается. Пробовал и раскрывать/не раскрывать - никаких результатов
        //с помощью qDebug() проверял, что в этот if заходит, когда выполнены соответствующие действия

        //QTimer::singleShot(0, this, SLOT(close()));
        //с помощью таймера решил проблему, но на защите могут из-за него завалить + окошко мигает при закрытии
    }
    else
    {
        //some code
    }
}

Есть еще сигнал у класса CEmployee, который активируется, когда в классе запускается деструктор, но коннектор с этим сигналом так же никак не помог. Стоит учитывать, что окно так же закрывается одним из QAction, и там все работает прекрасно (там, в принципе нечему работать, просто закрывает :D ). Просто не могу понять почему такое может возникать, гугл обшарил - ответа не нашел.


Название: Re: Не выполняется метод QMainWindow::close()
Отправлено: Bepec от Ноябрь 10, 2015, 20:17
конструктор у вас не оканчивает свою работу, а вы свой диалог уже пихаете. Вот и вся проблема в строчке LogWnd->exec();


Название: Re: Не выполняется метод QMainWindow::close()
Отправлено: stas3638 от Ноябрь 10, 2015, 20:31
конструктор у вас не оканчивает свою работу, а вы свой диалог уже пихаете. Вот и вся проблема в строчке LogWnd->exec();
А не могли бы вы посоветовать тогда, как сделать, чтобы окно авторизации запускалось после выполнения конструктора? Как лучше всего поступить в этом случае?


Название: Re: Не выполняется метод QMainWindow::close()
Отправлено: gil9red от Ноябрь 10, 2015, 20:43
конструктор у вас не оканчивает свою работу, а вы свой диалог уже пихаете. Вот и вся проблема в строчке LogWnd->exec();
А не могли бы вы посоветовать тогда, как сделать, чтобы окно авторизации запускалось после выполнения конструктора? Как лучше всего поступить в этом случае?

Код авторизации поместите в отдельную функцию (пусть будет auth) и вызывайте после создания окна:
LoginWnd dlg;
dlg.auth();
или
LoginWnd * dlg = new LoginWnd();
dlg->auth();


Название: Re: Не выполняется метод QMainWindow::close()
Отправлено: Bepec от Ноябрь 10, 2015, 21:18
Ну и да, мини такие уточнения.
Самый простой способ - вызывать таймером синглшотом, из конструктора. Т.е. таймер допустим на 5 мс на вызов auth().
Так же можно сделать вызов в слоте "showEvent" окна, но тогда придётся где то хранить флаг на "однократный" запуск, ибо showEvent вызывается постоянно при открытии/скрытии окна.

PS на деле довольно бесящая штука и не особо очевидная.


Название: Re: Не выполняется метод QMainWindow::close()
Отправлено: Vamireh от Ноябрь 11, 2015, 05:54
Ну и первый же ответ оказался правильным. Все же на одни и те же грабли наступают в начале.