QTableWidget - przycisk jako item

0

Dobry wieczór.

Od wczoraj męczę się z takim pomysłem: Mam w oknie programu obiekt typu QTableWidget. Do tego obiektu wczytuję sobie dane w postaci obiektów QTableWidgetItem.

Obiekt QTableWidget posiada na starcie programu pięć predefiniowanych kolumn oraz zero rzędów. Rzędy pojawiają się kiedy użytkownik użyje opcji wyszukiwania i coś znajdzie (nie ważne co, jakieś dane po prostu).

To wszystko bardzo ładnie działa, ponieważ obiekty typu QTableWidgetItem zawierają dane tekstowe, z którymi nic się nie robi tylko czyta z ekranu.

Ja chciałbym do rzędów, które się pojawią wczytać przyciski, tak żeby wyglądało to następująco:

// Pionowe kreski reprezentują kolumny tabeli
Dane | Dane | Dane | Przycisk | Przycisk   // rząd nr 1

...

Dane | Dane | Dane | Przycisk | Przycisk   // rząd nr 'n'

// gdzie 'n' to liczba znalezionych przez użytkownika rzędów
// wg jakichś tam kryteriów.

Jak to zrobić w kodzie to wiem, bo robię sobie odpowiednio dużą dynamiczną tablicę obiektów klasy QPushButton i wklejam jej elementy do tabeli na zasadzie:

this->ui->twWyniki->setCellWidget(0,4,&pb[0]); 
// gdzie obiekt pb[0] to obiekt typu QPushButton, a
// twWyniki to obiekt klasy QTableWidget.

// powoduje to wczytanie do rzędu nr '0', w kolumnie nr '5' przycisku nr [0] z ww tablicy.

Pytanie:
Jak napisać do tego sloty kiedy nie wiem jak duża będzie tak naprawdę tablica przycisków? Chcę żeby te przyciski wyświetlały nowe okno z rysunkiem pobranym z pliku jpg z dysku. Jak zaprogramować sloty do tego skoro liczba przycisków jest zmienna i zależy od ilości rzędów w tabeli wyszukiwania?

Pozdrawiam
Grzegorz

[EDIT]
Zapomniałem dopisać, że działa coś takiego:

    for(int i = 0; i < 3; i++) // dla trzech przycisków
        connect(&pb[i],SIGNAL(clicked()),pb,SLOT(hide())); // przykładowy slot 'hide()'

tylko teraz chodzi o to, że chcę pojedynczy slot do każdego przycisku, który to slot będzie miał argument, będący ścieżką do jpg na dysku.
Jeżeli każdy przycisk otwiera plik o innej nazwie to musiałbym mieć i-tą ilość takich slotów - tutaj jest pies pogrzebany, bo nie ma sygnału typu clicked(QString tekst).
Pozwalałoby mi to na zdefiniowanie jednego slotu, gdzie ścieżka byłaby przekazywana przez tego stringa.

0

Co wymyśliłem (specjalnie w osobnym poście):

  1. Definiuję sobie taki sygnał:
 
signals:
    void clicked(QString tekst);
  1. I takie dwa sloty:
 
void pbclicked(){ emit clicked("Grzegorz"); } // Zamias "Grzegorz" będzie ścieżka do feralnego pliku przypuśćmy.
void test(QString tekst){ this->ui->leTyp->setText(tekst); }; // wstawienie stringa do jakiegoś obiektu QLineEdit
  1. Na końcu robię takie połączenia:
 
    for(int i = 0; i < 3; i++){
        connect(&pb[i],SIGNAL(clicked()),this,SLOT(pbclicked()));
        connect(this,SIGNAL(clicked(QString)),this,SLOT(test(QString)));
    }

To działa, ale nie wiem... może da się to zrobić jakoś ładniej?

0

Da się.
Na dzień dobry wszystkie te QStringi zdefiniuj jako const QString& dzięki czemu unikniesz kopiowania obiektów.

0

cały pomysł jest zły (najlepiej zawsze opisywać co chcesz uzyskać, a dopiero w drugim kroku opisać jak próbujesz to uzyskać).
Potrzebujesz delegata, który będzie tworzył przycisk dla danej komórki i zmieniał stan MODELU danych w momencie, gdy coś się ma zmienić.
Patrz:

0

Dziękuję za odpowiedź. Z delegatami u mnie jeszcze jest ciężko. Jeszcze tego nie rozumiem ale wgryzę się w temat. Na razie wiem tylko tyle, że jest to coś takiego jak wskaźnik na funkcję :)

0

Zrobiłem!

Nie robiłem do tego delegatów ale obszedłem to przez rzutowanie wskaźnika.
Do sygnału clicked() obiektu QPushButton zrobiłem slot

void pbTabWcisniety()

o takim ciele:

 
void OknoGlowne::pbTabWcisniety(){
    QPushButton *pb = qobject_cast<QPushButton *>(sender());
    pb->setText("TRAF!");
}

W tym momencie wskaźnik 'caller' wie, który przycisk został wciśnięty i o to mi chodziło, bo mogę już wykorzystać sobie jego nazwę do poparsowania sobie nazwy pliku z obrazkiem:)

Do tego taka realizacja połączeń (długość pętli oczywiście określona przez listę w programie i ilość przycisków w jednym rzędzie):

for(int i = 0; i < this->lista.length(); i++){
    for(int j = 0; j < 2; j++){
        connect(&this->pbTab[i][j],SIGNAL(clicked()),this,SLOT(pbTabWcisniety()));
    }
}

Niestety nie rozumiem jeszcze delegatów i musiałem pogłówkować w trochę inny sposób.

Pozdrawiam
Grzegorz

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