Qt5 - problem z jednorazową blokadą sygnału.

0

Witam, mam taki kod:

void MainWindow::on_listWidgetNotes_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous)//Test!
{
    if(current != NULL)
    {
        ui->plainTextEditContent->setEnabled(true);
        change = false;
        if(isModified)
        {
            auto reply = QMessageBox::question(this, "Test", "Do you want save changes?", QMessageBox::Yes|QMessageBox::No|QMessageBox::Cancel);
            if (reply == QMessageBox::Yes) on_pushButtonSave_clicked();
            else if(reply == QMessageBox::No) notes.closeFile();
            else
            {
                //ui->listWidgetNotes->blockSignals(true);
                ui->listWidgetNotes->setCurrentItem(previous);
                //ui->listWidgetNotes->blockSignals(false);
                return;
            }
        }
        isModified = false;
        this->setWindowTitle(current->text()+" - VfNotes 1.0");
        ui->plainTextEditContent->setPlainText(notes.openFile(current->text()));
    }
}

W pewnym przypadku ma on wyświetlić okno dialogowe i ustawić zaznaczenie elementu, gdy to okno się zamknie lub, gdy się wybierze cancel. Jednak setCurrentItem powoduje ponowne wywołanie on_listWidgetNotes_currentItemChanged czego efektem jest ciągłe ponowne pojawianie się okna dialogowego po jego zamknięciu. Użycie blockSignals sprawia, że problem znika, ale zaznaczenie nie wraca na poprzedni element. Próbowałem wielu innych rozwiązań np. użycie zmiennej przechowującej informację o tym czy wywołać nowe okno, ale nic nie pomaga. W dokumentacji, którą przeglądałem wielokrotnie czy na zagranicznych forach również nie znalazłem odpowiedzi.

0

obczai
http://doc.qt.io/qt-5/qitemselectionmodel.html#details
http://www.qtcentre.org/threads/11723-How-to-select-a-cell-in-a-QTableView

Ogólnie coś mi w twoim zamyśle ogólnie nie gra ale nie wiem jaki jest cały pomysł i jaki jest scenariusz.

0

Jaki masz selectionMode ustawiony w QListWidgecie i czy na pewno chcesz taki mieć? Nie widać, żebyś gdzieś sprawdzał, które itemy są selected, więc może daj po prostu NoSelection. Upewnij się też, czy na pewno rozróżniasz pojęcie "current" i "selected". CurrentItem jest też w pewnym sensie zaznaczony (ma focusa). Może to CI wystarczy.

Jak robisz setCurrentItem w slocie podłączonym do currentItemChanged, to robi Ci się nieskończona rekurencja. Itemy current i previous są zmieniane miejscami w nieskończoność (albo przepełnienia stosu). Musisz to przerwać. Do tego powinna wystarczyć głupia flaga, czyli coś w stylu:

void MainWindow::on_listWidgetNotes_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous)//Test!
{
  static bool x = false;
  if (x)
    return;
....
                x = true;
                ui->listWidgetNotes->setCurrentItem(previous);
                x = false;
                return;
...
}

Rozwiązanie pewnie średnio eleganckie. Nie znam całej koncepcji, więc więcej nie pomogę.

0

@git To rozwiązanie ze zmienną x działa tak samo jak blokowanie sygnałów. Co prawda nie pojawia się ciągle okno dialogowe, ale po wybraniu cancel, focus nie wraca na swoje miejsce. Ustawienie NoSelection też nie pomaga. A co do całej koncepcji, to tu jest cały kod źródłowy tego programu: https://github.com/arkadiusz97/VfNotes

1

Wychodzi na to, że nie można wywołać metody setCurrentItem przed zakończeniem obsługi zdarzenia currentItemChanged. Rozwiązaniem jest dodanie wywołania metody setCurrentItem do kolejki komunikatów:

void MainWindow::on_listWidgetNotes_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous)
{
    ...
    else
    {
        QTimer::singleShot(0, qApp, [this, previous]
        {
            ui->listWidgetNotes->blockSignals(true);
            ui->listWidgetNotes->setCurrentItem(previous);
            ui->listWidgetNotes->blockSignals(false);
        });
        return;
    }
    ...
}
0

W sumie nie jestem pewien czy tak jest lepiej, ale ja bym po prostu zapamiętał poprzednią pozycję zaznaczenia i dla niej nie tworzył okienka.

0

@Pebal: Dzięki wielkie, Twoje rozwiązanie zadziałało :) Wszystkie inne z zagranicznych for, itp. nie chciały działać a ile to sobie nerwów napsułem z tym z pozoru błahym problemem.

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