Qt Sygnały, łączenie i przesyłanie danych

0

Witajcie,
to moje ostatnie pytanie z serii Qt w bieżącym projekcie.
Aczkolwiek wygląda ono następująco
W poniższym kodzie przesyłam sobie sygnał z QComboBox do mojej funkcji.

 for(int i=0;i<ui->tableWidget_2->columnCount();i++)
        {
            QComboBox *comboBox = new QComboBox;
            comboBox->addItem(QString::fromStdString("*all"));
            for(int j=0;j<ui->tableWidget->rowCount();j++)
            {
                bool tak=0;
                for(int k=0;k<comboBox->count();k++)
                    if(comboBox->itemText(k)==ui->tableWidget->item(j,i)->text())
                        tak=1;
                if(tak==0)
                    comboBox->addItem(ui->tableWidget->item(j,i)->text());
            }
            ui->tableWidget_2->setCellWidget(0,i,comboBox);
            connect(comboBox, SIGNAL(currentIndexChanged(int)),
                                     this, SLOT(Szukamy(int)));
        }

Dzięki czemu mam informację o tym jaki zostaje wybrany index w QComboBox.
rezultat jest następujący.
Zrzut_ekranu_z_2012-09-16_191235_png_300x300_q85.jpg
Zrzut_ekranu_z_2012-09-16_191314_png_300x300_q85.jpg
Zrzut_ekranu_z_2012-09-16_191336_png_300x300_q85.jpg

Aczkolwiek symulacje wyszukiwania zaprogramowałem na sztywno.
Ponieważ nie wiem z jakiej kolumny !ComboBox został użyty.

oto kod

void Elementy::Szukamy(int)
{
    QComboBox* combo=(QComboBox*)ui->tableWidget_2->cellWidget(0, 0);
    combo->currentIndex();

    for(int i=0;i<ui->tableWidget->rowCount();i++)
        ui->tableWidget->showRow(i);

    if(combo->itemText(combo->currentIndex()).toStdString()!="*all")
    {
        for(int i=0;i<ui->tableWidget->rowCount();i++)
        {
            if(ui->tableWidget->item(i,0)->text().toStdString()!=combo->itemText(combo->currentIndex()).toStdString())
                ui->tableWidget->hideRow(i);
        }
    }
} 

I teraz cały sekret Tkwi w tym jak zrobić by informacja z tym przesyłanym sygnałem zawierała również informacje z której kolumny został wywołany ?

1

Wydaje się, że w tym wypadku dobrze byłoby skorzystać z delegata ale nie jest to konieczne, istnieje inne (brzydsze) rozwiązanie:

QWidget *id = QApplication::focusWidget();
if(id)
    qDebug() << indexAt(id->pos());
0

Ja pomyślałem, ze zrobie zmienną klasy która będzie reprezentować mi tą kolumnę i dodam
takie coś

 connect(ui->tableWidget_2, SIGNAL(cellActivated(int,int)),
                                     this, SLOT(Komurka(int,int)));

oraz funkcje

 void Elementy::Komurka(int row,int column)
{
    kom=column;
}

i pozmieniałem następująco tamte funkcje:

for(int i=0;i<ui->tableWidget_2->columnCount();i++)
        {
            QComboBox *comboBox = new QComboBox;
            comboBox->addItem(QString::fromStdString("*all"));
            for(int j=0;j<ui->tableWidget->rowCount();j++)
            {
                bool tak=0;
                for(int k=0;k<comboBox->count();k++)
                    if(comboBox->itemText(k)==ui->tableWidget->item(j,i)->text())
                        tak=1;
                if(tak==0)
                    comboBox->addItem(ui->tableWidget->item(j,i)->text());
            }
            ui->tableWidget_2->setCellWidget(0,i,comboBox);
            connect(comboBox, SIGNAL(currentIndexChanged(int)),
                                     this, SLOT(Szukamy(int)));
            connect(ui->tableWidget_2, SIGNAL(cellActivated(int,int)),
                                     this, SLOT(Komurka(int,int)));
        } 
void Elementy::Szukamy(int)
{
    QComboBox* combo=(QComboBox*)ui->tableWidget_2->cellWidget(0, kom);
    combo->currentIndex();

    for(int i=0;i<ui->tableWidget->rowCount();i++)
        ui->tableWidget->showRow(i);

    if(combo->itemText(combo->currentIndex()).toStdString()!="*all")
    {
        for(int i=0;i<ui->tableWidget->rowCount();i++)
        {
            if(ui->tableWidget->item(i,kom)->text().toStdString()!=combo->itemText(combo->currentIndex()).toStdString())
                ui->tableWidget->hideRow(i);
        }
    }
} 

ALe w efekcie i tak działa tylko na kolumnie pierwszej ;/ tak jak miałem w prototypie w mojej wersji testowej u góry ;/

Jakieś pomysły na rozwiązania ?

0

myślę, że mniej kombinowania:

class MyTableWidget : public QTableWidget {
    Q_OBJECT
    public:
        MyTableWidget(const QStringList & columns, QWidget *parent = 0)
            : QTableWidget(1, columns.size(), parent)
        {
            setHorizontalHeaderLabels(columns);
        }

    public slots:
        void sl1(int)
        {
            QWidget *id = QApplication::focusWidget();
            if(id)
                qDebug() << indexAt(id->pos()); //i tutaj robisz co chcesz

        }
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QStringList columns;
    QStandardItemModel sim;

    columns << "kolumna 1" << "kolumna 2" << "kolumna 3";
    sim.setHorizontalHeaderLabels(columns);

    for(int i = 0; i < 50; ++i)
    {
        QList<QStandardItem*> l;
        for(int j = 0; j < columns.size(); ++j)
            l << new QStandardItem("wiersz: " + QString::number(i + 1) +
                                   " kolumna: " + QString::number(j + 1));
        sim.appendRow(l);
    }

    //QTableView tv;
    //tv.setModel(&sim);

    MyTableWidget mtw(columns);

    for(int i = 0; i < mtw.columnCount(); ++i)
    {
        QComboBox *cb = new QComboBox;

        for(int j = 0; j < sim.rowCount(); ++j)
            cb->addItem(sim.item(j, i)->text());
        mtw.setCellWidget(0, i, cb);
        mtw.connect(cb, SIGNAL(currentIndexChanged(int)), SLOT(sl1(int)));
    }

    mtw.resizeColumnsToContents();
    mtw.show();

    return a.exec();
}

#include "main.moc" // w przypadku gdy budujesz w miescu projektu
0

A jeszcze jedno liczba column nie jest statyczna tylko dynamiczna Tworzy się od ilości kolumn w QtableWidget poniżej niego
I to okienko na , którym teraz pracujemy jest dzieckiem MainWindow

0

No nie wiem jak Twoje rozwiązanie odnieść do mojego projektu

0

Mój kod to tylko przykład. Jeśli, w którymś z combobox'ów wybierzesz element to wywoływany jest slot sl1 i to z tym masz problem. Wiesz, że zostało coś zrobione na combobox'ie ale nie wiesz, na którym. Dlatego w tym slocie przy pomocy "indexAt(id->pos())" dostaję dokładne współrzędne komórki, w której znajduje się combobox, który wyemitował sygnał. Mając już współrzędne tej komórki (wierszy i kolumnę) robisz co chcesz - chyba, że źle zrozumiałem twój problem. Myślę, że można to rozwiązać jeszcze przy pomocy sender'a ale to kolejna tylko propozycja.

0

Okey teraz widzę ale ja Tworzę TableWidget jako element mojego okna z Qt Creatora
i ja w moich plikach projektu nie mam kody klasy :p bynajmniej tak mi się wydaje.
I nie wiem jak dodać metode

public slots:
        void sl1(int)
        {
            QWidget *id = QApplication::focusWidget();
            if(id)
                qDebug() << indexAt(id->pos()); //i tutaj robisz co chcesz
 
        } 

Twojej propozycji do mojego QtableWidget

0

nie wiem czy mnie rozumiesz bo Wy tutaj tak wszyscy ogarnięci jesteście ale też kiedyś zaczynaliście prawda ?

0
Shial napisał(a):

Ja pomyślałem, ze zrobie zmienną klasy która będzie reprezentować mi tą kolumnę i dodam
takie coś

 connect(ui->tableWidget_2, SIGNAL(cellActivated(int,int)),
                                     this, SLOT(Komurka(int,int)));

oraz funkcje

 void Elementy::Komurka(int row,int column)
{
    kom=column;
}

i pozmieniałem następująco tamte funkcje:

for(int i=0;i<ui->tableWidget_2->columnCount();i++)
        {
            QComboBox *comboBox = new QComboBox;
            comboBox->addItem(QString::fromStdString("*all"));
            for(int j=0;j<ui->tableWidget->rowCount();j++)
            {
                bool tak=0;
                for(int k=0;k<comboBox->count();k++)
                    if(comboBox->itemText(k)==ui->tableWidget->item(j,i)->text())
                        tak=1;
                if(tak==0)
                    comboBox->addItem(ui->tableWidget->item(j,i)->text());
            }
            ui->tableWidget_2->setCellWidget(0,i,comboBox);
            connect(comboBox, SIGNAL(currentIndexChanged(int)),
                                     this, SLOT(Szukamy(int)));
            connect(ui->tableWidget_2, SIGNAL(cellActivated(int,int)),
                                     this, SLOT(Komurka(int,int)));
        } 
void Elementy::Szukamy(int)
{
    QComboBox* combo=(QComboBox*)ui->tableWidget_2->cellWidget(0, kom);
    combo->currentIndex();

    for(int i=0;i<ui->tableWidget->rowCount();i++)
        ui->tableWidget->showRow(i);

    if(combo->itemText(combo->currentIndex()).toStdString()!="*all")
    {cellPressed(int,int)
        for(int i=0;i<ui->tableWidget->rowCount();i++)
        {
            if(ui->tableWidget->item(i,kom)->text().toStdString()!=combo->itemText(combo->currentIndex()).toStdString())
                ui->tableWidget->hideRow(i);
        }
    }
} 

ALe w efekcie i tak działa tylko na kolumnie pierwszej ;/ tak jak miałem w prototypie w mojej wersji testowej u góry ;/

Jakieś pomysły na rozwiązania ?

Bo w tej opcji Sygnał

 connect(ui->tableWidget_2, SIGNAL(cellActivated(int,int)),
                                     this, SLOT(Komurka(int,int)));

albo nie działa albo nie łączy albo nie wiem bo wgl nie emituje i nie wywołuje funkcji

 void Elementy::Komurka(int row,int column)
{
    kom=column;
}
0

Znalazłem takie rozwiązanie:
http://stackoverflow.com/questions/1332110/selecting-qcombobox-in-qtablewidget
Lecz po zastosowaniu coś mi nie działa.

Kod mój wygląda tak:

  QSignalMapper* signalMapper = new QSignalMapper(this);
        for(int i=0;i<ui->tableWidget_2->columnCount();i++)
        {
            QComboBox *comboBox = new QComboBox;
            comboBox->addItem(QString::fromStdString("*all"));
            for(int j=0;j<ui->tableWidget->rowCount();j++)
            {
                bool tak=0;
                for(int k=0;k<comboBox->count();k++)
                    if(comboBox->itemText(k)==ui->tableWidget->item(j,i)->text())
                        tak=1;
                if(tak==0)
                    comboBox->addItem(ui->tableWidget->item(j,i)->text());
            }
            ui->tableWidget_2->setCellWidget(0,i,comboBox);
            connect(comboBox, SIGNAL(currentIndexChanged(int)), signalMapper,
                    SLOT(map()));
                 signalMapper->setMapping(comboBox, QString("%1-%2").arg(0).arg(i));
        }connect(signalMapper, SIGNAL(mapped(const QString &)),
                 this, SIGNAL(Szukamy(const QString &)));
void Elementy::Szukamy(QString position)
{
    QStringList coordinates = position.split("-");
    //int wiersz = coordinates[0].toInt();
    int columna = coordinates[1].toInt();
    QMessageBox::warning(this,"",position.toStdString().c_str());
    QComboBox* combo=(QComboBox*)ui->tableWidget_2->cellWidget(0, columna);
    combo->currentIndex();

    for(int i=0;i<ui->tableWidget->rowCount();i++)
        ui->tableWidget->showRow(i);

    if(combo->itemText(combo->currentIndex()).toStdString()!="*all")
    {
        for(int i=0;i<ui->tableWidget->rowCount();i++)
        {
            if(ui->tableWidget->item(i,columna)->text().toStdString()!=combo->itemText(combo->currentIndex()).toStdString())
                ui->tableWidget->hideRow(i);
        }
    }
} 

Poprawiłem SIGNAL na SLOT i ładnie wszystko działa :)

1
Shial napisał(a):

Okey teraz widzę ale ja Tworzę TableWidget jako element mojego okna z Qt Creatora
i ja w moich plikach projektu nie mam kody klasy :p

już tak na marginesie - możesz stworzyć swoją klasę podobnie jak ja dziedziczącą po QTableWidget. W designerze wstawiasz na formatkę normalnego QTableWidget'a, a następnie w menu kontekstowym wywołanym wybierasz opcję "promoted widgets" bądź zastępcze widgety w wersji polskiej i tam podstawiasz swoją klasę. W ten sposób możesz reimplementować widgety, w zasadzie to jest filozofia Qt.

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