Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

tabela w qt

Ostatnio zmodyfikowano 2020-01-31 19:23
Autor Wiadomość
Bartex321
Temat założony przez niniejszego użytkownika
tabela w qt
» 2020-01-14 11:15:57
tworzę table widget w qt, jednak mam problem ze znikającymi danymi:
C/C++
/*01*/ QVector < QVector < QTableWidgetItem >> tablica;
/*02*/ QVector < QTableWidgetItem > wiersz;
/*03*/ QTableWidgetItem komorka( "X" );
/*04*/
/*05*/ void MainWindow::on_pushButton_clicked() // dodaj kolumnę
/*06*/ {
    /*07*/ ui->tableWidget->setColumnCount( ui->tableWidget->columnCount() + 1 );
    /*08*/ for( int i = 0; i < ui->tableWidget->rowCount(); i++ )
    /*09*/ {
        /*10*/ tablica[ i ].push_back( komorka );
        /*11*/ ui->tableWidget->setItem( i, ui->tableWidget->columnCount() - 1, & tablica[ i ][ ui->tableWidget->columnCount() - 1 ] );
        /*12*/ }
    /*13*/ }
/*14*/
/*15*/ void MainWindow::on_pushButton_2_clicked() // dodaj wiersz
/*16*/ {
    /*17*/ ui->tableWidget->setRowCount( ui->tableWidget->rowCount() + 1 );
    /*18*/ for( int i = 0; i < ui->tableWidget->columnCount(); i++ )
         /*19*/ wiersz.push_back( komorka );
    /*20*/
    /*21*/ tablica.push_back( wiersz );
    /*22*/
    /*23*/ for( int i = 0; i < ui->tableWidget->columnCount(); i++ )
         /*24*/ ui->tableWidget->setItem( ui->tableWidget->rowCount() - 1, i, & tablica[ ui->tableWidget->rowCount() - 1 ][ i ] );
    /*25*/ }
To jest kod obsługujący przycisk dodaj kolumnę oraz dodaj wiersz, niestety o ile dodawanie wierszy działa, to przy dodawaniu kolumn czasami znikają dane z jednego z wierszy(jeśli ktoś posiada qt creator to można przetestować, wystarczy stworzyć projekt oraz dodać tabele i dwa przyciski w trybie designu).
Może się mylę, jednak według mnie jest to spowodowane tym, że vektor czasami zmienia miejsce na dysku(gdy w obecnej lokalizacji brakuje miejsca, a ja chcę dodać element), a wskaźniki mające pokazywać ten wektor, się nie zmieniają(linia 11 i 24 - ustawiam je tylko raz przy dodawaniu wiersza/kolumny).
Próbowałem rozwiązać ten problem za każdym razem ustawiając wszystkie wskaźniki od nowa, niestety jest to zdecydowanie zbyt długie przy dużej tabeli(choć działa).
Bardzo proszę o jakiś pomysł :)
P-176058
nanoant20
» 2020-01-14 12:22:38
nie jestem kompetentny i nie znam się na qt ale ten zapis
QVector < QVector < QTableWidgetItem >> tablica;

mówi, że jest to tablica tablic czyli matrix 2D
zapis do tablicy 2d mógłby wyglądać np. coś w tym stylu
C/C++
QVector < QVector < QTableWidgetItem >> tablica;
ui->tableWidget->setRowCount( 6 );
ui->tableWidget->setColumnCount( 6 );
for( int i = 0; i < ui->tableWidget->rowCount(); ++i ) {
    QVector < QTableWidgetItem > wiersz;
    for( int j = 0; j < ui->tableWidget->columnCount(); ++j ) {
        /*
            QTableWidgetItem *tableitem = new QTableWidgetItem(" ");
            ui->tableWidget->setItem(i,j,tableitem);
            */
        //ui->tableWidget->setItem(i,j,tablica); //trzeba by sprawdzić
        wiersz.push_back( komorka );
    }
    tablica.push_back( wiersz );
}
powinien wystarczyć 1 button i 2 petle for
U ciebie są 2 funkcje: 1-a dodaje wiersze
a 2-ga dodaje kolumny
P-176059
Bartex321
Temat założony przez niniejszego użytkownika
» 2020-01-14 12:46:32
QVector < QVector < QTableWidgetItem >> tablica;
vektor, którego każdy element jest vektorem, którego każdy element jest QTableWidgetItemem(taka rozszerzalna w każdą stronę 2-wymiarowa tablica)
np.: 2.1 to tablica[2][1]
1.1   1.2   1.3
2.1
3.1   3.2   3.3   3.4

Co do twojego kodu:
1. Potrzeba mi oddzielne przyciski do dodawania kolumn i wierszy,
2. Nie odniosłeś się zupełnie do problemu:
Aby stworzyć tabelę w qt, oprócz wskazania liczby wierszy i kolumn potrzeba każdej komórce przyporządkować QTableWidgetItem(każdej inny), dlatego tworzę ten vektor o nazwie tablica(są w nim QTableWidgetItem-y dla każdej komórki w tabeli), niestety przyporządkowuje się to przez wskaźnik:

ui->tableWidget->setItem(ui->tableWidget->rowCount() - 1, i, &tablica[ui->tableWidget->rowCount() - 1]);
tabela->ustawItem(ostatni wiersz, i-ta kolumna, wskaźnik na item[ostatni wiersz][i-ta kolumna])

Problem jest taki, że vektor zmienia swoje położenie na dysku, a wskaźnik się nie zmienia i wskazuje na nic, przez co z komórki znika tekst, formatowanie itd.

Próbowałem za każdym zwiększeniem vektora od nowa przypisywać wszystkie wskaźniki(na wypadek gdyby zmienił miejsce na dysku) i to działa, ale zbyt wolno
P-176060
nanoant20
» 2020-01-14 20:26:45
oddzielne przyciski do dodawania kolumn i wierszy,
nie wiem, pierwszy raz się z czymś takim spotykam, żeby oddzielnie
wstawiać wartości do kolumn i oddzielnie do wierszy
P-176063
Bartex321
Temat założony przez niniejszego użytkownika
» 2020-01-14 23:27:09
"nie wiem, pierwszy raz się z czymś takim spotykam, żeby oddzielnie
wstawiać wartości do kolumn i oddzielnie do wierszy"
Pierwszy przycisk dodaje nowy wiersz, a przycisk drugi dodaje nową kolumnę.
W kodzie, który tutaj podałem do nowo powstałych komórek wpisuje się znak "X", żeby zobrazować problem, którym są najprawdopodobniej następstwa realokacji vektora
Nie mam problemu z dodaniem wiersza/kolumny, chodzi o "znikanie", a raczej przeniesienie danych na dysku, podczas dodawania do tabeli nowej kolumny
P-176069
killjoy
» 2020-01-15 00:12:42
Jeżeli koniecznie chcesz używać std::vector, to zamiast trzymać w nim obiekty, trzymaj pointery na obiekty - albo jeszcze lepiej smart pointery np. std::unique_ptr. Po smart pointerach (unique_ptr) nie będzie trzeba ręcznie sprzątać, zostaną zwolnione razem z wektorem.

To będzie działać mniej więcej tak (nie mam Qt pod ręką, żeby dać gotowca):
C/C++
#include <vector>
#include <iostream>
#include <memory>
#include <string>
using namespace std;



int main()
{
   
    vector < string > objs;
    vector < unique_ptr < string > > ptrs;
    objs.reserve( 1024 );
    ptrs.reserve( 1024 );
   
    objs.push_back( "obj str" );
    ptrs.push_back( unique_ptr < string >( new string( "obj str" ) ) );
   
   
    cout << "Before relocation" << endl;
    cout << " *Object address: " <<( void * ) & objs[ 0 ] << endl;
    cout << " *Ptr hold address: " <<( void * ) ptrs[ 0 ].get() << ", ptr address: " <<( void * ) & ptrs[ 0 ] << endl << endl;
   
    objs.shrink_to_fit();
    ptrs.shrink_to_fit();
   
    cout << "After forced relocation (very likely)" << endl;
    cout << " *Object address: " <<( void * ) & objs[ 0 ] << endl;
    cout << " *Ptr hold address: " <<( void * ) ptrs[ 0 ].get() << ", ptr address: " <<( void * ) & ptrs[ 0 ] << endl;
   
   
    return 0;
}

Możliwy wynik:

Before relocation
 *Object address: 0x2602490
 *Ptr hold address: 0xe41700, ptr address: 0x260a4a0

After forced relocation (very likely)
 *Object address: 0xe41a70
 *Ptr hold address: 0xe41700, ptr address: 0xe41730

Jak widać przenoszony jest sam smart pointer, a nie to na co wskazuje.
P-176070
Bartex321
Temat założony przez niniejszego użytkownika
» 2020-01-31 19:23:47
Bardzo dziękuję za odpowiedź na poprzednie pytanie, działa, jednak mam jeszcze jeden problem, ponieważ chciałbym, aby 4 pierwsze wiersze "zjeżdżały" przy przewijaniu tabeli w dół (tzn zachowywały się tak jak nagłówki - gdy zjadę w dół widze nagłówek, a  pod nim np. 10 wiersz), próbowałem wstawić te wiersze w nagłówek, niestety nagłówek ustawia się w sposób:
setHorizontalHeaderItem(int nrkolumny, QTableWidgetItem komórka), więc mogę w nim zrobić tylko jeden wiersz :/
Efekt, który chcę uzyskać można dostać w excelu blokując wiersz(wstążka widok)
P-176151
« 1 »
  Strona 1 z 1