Qt — два сигнала и модальное диалоговое окно

У меня есть класс на основе QDialog.

У меня есть QEditLine *editLine и QButton *button.

Я использую clicked() сигнал кнопки. И editingFinished() сигнал editLine.

Когда я изменяю текст в строке редактирования и нажимаю кнопку, сначала испускается сигнал editingFinished(). В методе слота я вызываю QMessageBox::question(). После этого я не могу получить сигнал clicked() моей кнопки.

Я пытался использовать Qt::QueuedConnection для метода подключения, но это не помогает.

Как решить мою проблему?


person Funt    schedule 17.10.2012    source источник


Ответы (3)


Я думаю, проблема в том, что цикл событий для окна сообщения блокирует основной цикл событий, поэтому сигнал вашей кнопки не испускается. Но как вы все равно планируете нажимать кнопку, если у вас открыто модальное диалоговое окно?

person Rudolfs Bundulis    schedule 17.10.2012
comment
Кнопка выглядит как нажатая. И когда модальный диалог закрыт, он все еще выглядит нажатым. Я хотел бы обработать сигнал clicked() после закрытия модального диалога. Итак, я должен каким-то образом отложить генерацию сигнала clicked() до тех пор, пока модальный диалог не будет закрыт... или я мог бы проверить, нажата ли кнопка после закрытия модального диалога. Но это некрасиво :( - person Funt; 17.10.2012
comment
Можете ли вы опубликовать хотя бы частичный код? Я бы сказал, что сигнал все равно должен быть испущен, просто после закрытия диалога. Является ли вызов connect (), когда вы подключаете сигнал кнопки, возвращается без ошибок? - person Rudolfs Bundulis; 17.10.2012

Вот код:

Window::Window(QWidget *parent)
: QDialog(parent)
{
    setupUi(this);

    appPath = QApplication::applicationDirPath();

    connect(pButton, SIGNAL(clicked()), this, SLOT(build()), Qt::QueuedConnection);

    connect(pLineEdit, SIGNAL(editingFinished()), this, SLOT(pathChanged()), Qt::QueuedConnection);
}

void Window::pathChanged()
{
    QString path = pLineEdit->text();

    if(createPath(path))
        updatePath(path);
}

bool Window::createPath(QString path)
{
    if(!QDir(path).exists())
    {
        QMessageBox::StandardButton reply;
        reply = QMessageBox::question(this, tr("Folder is not exist"), "Folder " + path + " is not exist. Do you want to create it?", QMessageBox::Yes | QMessageBox::No);
        if (reply == QMessageBox::Yes)
        {
             QDir dir;
             dir.mkpath(path);
        }
    }
    return true;
}

class Window : public QDialog, public Ui::GLConverterDialogUI
{
    Q_OBJECT

public:
    Window(QWidget *parent = 0);
    ~Window(void);
    ......
}
person Funt    schedule 17.10.2012
comment
С Qt::DirectConnection не получилось так же? Поскольку объекты живут в основном потоке, в принципе нет необходимости в Qt::QueuedConnection. Еще одна вещь, которую вы можете сделать, это фактически поставить точку останова в источниках qt, где испускается сигнал clicked(), и посмотреть, как он отправляется, поскольку я не уверен, почему он терпит неудачу. - person Rudolfs Bundulis; 17.10.2012
comment
Да, поведение с Qt::DirectConnection такое же. Я попробую поиграть с clicked(). - person Funt; 17.10.2012
comment
Если вы уберете звонок в окно сообщения, станет лучше? Поскольку без второго цикла событий я не вижу, что еще может все испортить. - person Rudolfs Bundulis; 17.10.2012
comment
да. Я только что попытался прокомментировать reply = QMessageBox::question(... и вместо этого поставил reply = QMessageBox::Yes. В этом случае вызываются как pathChanged(), так и build(). - person Funt; 17.10.2012
comment
Вы можете попробовать этот небольшой пример по link, чтобы воспроизвести мою проблему. - person Funt; 17.10.2012
comment
clicked() генерируется в mouseReleaseEvent() QAbstractButton. Но после отображения окна сообщения кнопка остается нажатой, поэтому mouseReleaseEvent() не вызывается.... - person Funt; 17.10.2012
comment
Хм, хорошо, это становится интересным, может быть, это съедает цикл событий модальных диалогов, однако я не уверен, возможно ли это. Вы считаете, что диалог должен быть немодальным? - person Rudolfs Bundulis; 17.10.2012
comment
На самом деле, сначала пользователь должен сделать выбор, а после этого мне нужно вызвать свой код для события, на которое нажали. Вот почему модальный диалог — это решение отложить вызов кода для события нажатия. - person Funt; 17.10.2012
comment
Разве вы не можете показать диалог о создании пути в слоте обработки сигнала clicked() и просто вернуться, если пользователь отменит? Таким образом, вам понадобится только один обработчик сигналов? - person Rudolfs Bundulis; 17.10.2012
comment
Да, это решит проблему. Но поведение приложения будет немного другим. А у меня другая проблема. - person Funt; 18.10.2012

У меня такая же проблема в другом приложении. Я использую некоторую библиотеку. Я предполагаю, что эта библиотека использует сигнал Press() QAbstractButton вместо clicked(). И когда я вызываю QFileDialog::getSaveFileName() после нажатия кнопки, кажется, что mouseReleaseEvent() тоже не вызывается. Поэтому после закрытия диалогового окна кнопка все еще нажата, и мне приходится вручную отправлять событие MouseButtonRealese. Может быть, я должен вызвать диалог с некоторыми специальными параметрами?

person Funt    schedule 18.10.2012
comment
Когда у меня будет время, я отлажу ваш пример, не уверен, где исчезает mouseReleaseEvent(). - person Rudolfs Bundulis; 18.10.2012
comment
Большое спасибо! Пожалуйста, взгляните на этот пример: ссылка Здесь я удалил сигнал editFinished(). Но проблема та же. - person Funt; 18.10.2012