Qt - własny model po QAbstractItemModel

Odpowiedz Nowy wątek
2019-11-07 13:43
0

Tworzę sobie swój własny model który dziedziczy po QAbstractItemModel i pojawił się u mnie "mały" problem...

mam 2 klasy

  1. MainWindow
  2. MyModel

.1. klasa - MainWindow
zawartość pliku nagłówkowego mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QTableView>

class mymodel;

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private:
    mymodel *_myModel;
    QTableView *view;
};
#endif // MAINWINDOW_H

zawartość pliku żródłowego mainwindow.cpp

#include "mainwindow.h"
#include "mymodel.h"

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{
    view = new QTableView();
}

MainWindow::~MainWindow()
{
}
  1. klasa - MyModel

zawartość pliku nagłówkowego mymodel.h

#ifndef MYMODEL_H
#define MYMODEL_H

#include <QAbstractItemModel>

class MyModel : public QAbstractItemModel
{
public:
    MyModel(QWidget *parent=nullptr);

    int columnCount(const QModelIndex &parent = QModelIndex()) const override;
    int rowCount(const QModelIndex &parent = QModelIndex()) const override;
};

#endif // MYMODEL_H

zawartość pliku źródłowego mymodel.cpp

#include "mymodel.h"

MyModel::MyModel(QWidget *parent)
{

}

int MyModel::columnCount(const QModelIndex &parent) const
{
    return 3;
}

int MyModel::rowCount(const QModelIndex &parent) const
{
    return 4;
}

i teraz mam pytanie, w jaki sposób mogę pokazać ilość wierszy i kolumn w mainwindow ? Bo chciałbym aby widok wyświetlił model

wyprzedzam już pytania typu "po co robisz swój model" skoro są inne "gotowe" - akurat chcę się nauczyć robić własne modele i zrozumieć jak to działa


bla

Pozostało 580 znaków

2019-11-07 14:45
0

Najpierw zacznij od opisania co będzie reprezentował ten model.
Drzewo? Np strukturę katalogów.
Listę?
Tabelę?
Inne cudo?

Zależnie od tego, należy dziedziczyć po potomkach QAbstractItemModel.

Następnie opisz jaki zestaw funkcjonalności ma mieć ten model danych.
Czy użytkownik ma prawo modyfikować dane?
Czy masz API do modyfikowania zdanych.
Czy ten model jest tylko proxy do innej struktury danych?
Itp itd.


Jeśli chcesz pomocy, NIE pisz na priva, ale zadaj dobre pytanie na forum.
edytowany 1x, ostatnio: MarekR22, 2019-11-07 15:58

Pozostało 580 znaków

2019-11-07 15:11
0

dzięki za odpowiedź, nie wiedziałem, że muszę to doprecyzować, ponieważ sądziłem, że ten model jest tylko do tabel, więc tak

  1. Model ma pobierać dane z bazy danych
  2. Tabela ma być edytowalna - ale nie wszystkie kolumny

Zależnie od tego, należy dziedziczyć po potomkach QMainWindow.

Czy możesz rozwinąć myśl ? Bo nie wiem, co miałoby dziedziczyć po QMainWindow i w jakim celu ?

Czy użytkownik ma prawo modyfikować dane?

tak, ale nie wszystkie kolumny

Czy masz API do modyfikowania zdanych.

czy możesz przybliżyć myśl o jakie API Tobie chodzi ? Ponieważ nie rozumiem tego pytania

Czy ten model jest tylko proxy do innej struktury danych?

tego też nie rozumiem, ponieważ nie wiem o co chodzi z tym "proxy". Natomiast mogę powiedzieć, że struktura danych ma być tabelaryczna


bla
eech... myślałem jedno napisałem drugie, miało być QAbstractItemModel - poprawione - MarekR22 2019-11-07 15:59

Pozostało 580 znaków

2019-11-07 15:26
0
zkubinski napisał(a):

dzięki za odpowiedź, nie wiedziałem, że muszę to doprecyzować, ponieważ sądziłem, że ten model jest tylko do tabel, więc tak

Model jest abstrakcją na jakieś dane, od ciebie zależy co reprezentuje. W tym wypadku:

zkubinski napisał(a):
  1. Model ma pobierać dane z bazy danych
  2. Tabela ma być edytowalna - ale nie wszystkie kolumny

Zależnie od tego, należy dziedziczyć po potomkach QMainWindow.

Czy możesz rozwinąć myśl ? Bo nie wiem, co miałoby dziedziczyć po QMainWindow i w jakim celu ?

Raczej nie QMainWindow, ale bardziej potrzebujesz QTableView aby zaprezentować dane. Ów QTableView umieść jako central widget instancji QMainWindow.

zkubinski napisał(a):

Czy użytkownik ma prawo modyfikować dane?

tak, ale nie wszystkie kolumny

Czy masz API do modyfikowania zdanych.

czy możesz przybliżyć myśl o jakie API Tobie chodzi ? Ponieważ nie rozumiem tego pytania

Czy ten model jest tylko proxy do innej struktury danych?

tego też nie rozumiem, ponieważ nie wiem o co chodzi z tym "proxy". Natomiast mogę powiedzieć, że struktura danych ma być tabelaryczna

Generalnie skoro potrzebujesz dobierać się do bazy danych to bardziej przyda ci się oprzeć nie na QAbstractItemModel, a QSqlTableModel.


"Sugeruję wyobrazić sobie Słońce widziane z orbity Merkurego, a następnie dupę tej wielkości. W takiej właśnie dupie specjalista ma teksty o wspaniałej atmosferze, pracy pełnej wyzwań i tworzeniu innowacyjnych rozwiązań. Pracuje się po to, żeby zarabiać, a z resztą specjalista sobie poradzi we własnym zakresie, nawet jeśli firma mieści się w okopie na granicy obu Korei."
-somekind,
konkretny człowiek-konkretny przekaz :]

Pozostało 580 znaków

2019-11-07 15:41
0

Model jest abstrakcją na jakieś dane, od ciebie zależy co reprezentuje.

tak, wiem

Raczej nie QMainWindow, ale bardziej potrzebujesz QTableView aby zaprezentować dane. Ów QTableView umieść jako central widget instancji QMainWindow.

to też wiem, że muszę te dane wyświetlić w widoku QTableView, ale chciałem aby kolega @MarekR22 rozwinął myśl o co jemu chodzi, bo sądzę, że wie o tym iż muszę wyświetlić to w QTableView być może miał na myśli inną rzecz ?

Generalnie skoro potrzebujesz dobierać się do bazy danych to bardziej przyda ci się oprzeć nie na QAbstractItemModel, a QSqlTableModel.

próbowałem QSqlTableModel, a w zasadzie QSqlQueryModel i tak:

  1. QSqlTableModel ma problemy z zapytaniami setQuery i to działa tylko na jednej tabeli, więc nie jest to satysfakcjonujące rozwiązanie
  2. QSqlQueryModel jest tylko do wyświetlania danych pobranych za pomocą zapytań SQL, generalnie da się zrobić model edytowalny ale już poległem przy próbie dodawania i usuwania wierszy w tym modelu dlatego padł wybór na QAbstractItemModel ponieważ stworzenie własnego modelu daje większe możliwości niż modele które są "gotowe" ponieważ mają jakieś ograniczenia i jak jedno się zrobi, to na drugim łamię zęby

ogólnie rzecz biorąc mam już jakieś doświadczenia z modelami ale to początki

PS. Jak chcecie, to mogę umieścić cały swój kod oparty o klasę QSqlQueryModel mam tam zaimplementowany QItemDelegate, Qt::ItemFlags (Qt::ItemIsEditable), no i mam swój "model" ale połamałem zęby na dodawaniu i usuwaniu rekordów, bo dodają się i usuwają ale nie są edytowalne, gdyż QSqlQueryModel nie ma czegoś takiego jak insertRow i removeRow, co prawda dziedziczy to po QAbstractItemModel ale nie da się już edytować tych rekordów


bla

Pozostało 580 znaków

2019-11-07 16:01
0

A nie wystarczy ci QSqlTableModel? Jeśli nie to czym to się ma różnić?


Jeśli chcesz pomocy, NIE pisz na priva, ale zadaj dobre pytanie na forum.

Pozostało 580 znaków

2019-11-07 19:05
0

nie wystarczy, bo chcę mieć możliwość wykonywania zapytań SQL, a gdy użyję tej klasy, to wszystkie dane musiałbym po prostu umieszczać w jednej tabeli


bla

Pozostało 580 znaków

2019-11-07 21:28
1
zkubinski napisał(a):

próbowałem QSqlTableModel, a w zasadzie QSqlQueryModel i tak:

  1. QSqlTableModel ma problemy z zapytaniami setQuery i to działa tylko na jednej tabeli, więc nie jest to satysfakcjonujące rozwiązanie
  2. QSqlQueryModel jest tylko do wyświetlania danych pobranych za pomocą zapytań SQL, generalnie da się zrobić model edytowalny ale już poległem przy próbie dodawania i usuwania wierszy w tym modelu dlatego padł wybór na QAbstractItemModel ponieważ stworzenie własnego modelu daje większe możliwości niż modele które są "gotowe" ponieważ mają jakieś ograniczenia i jak jedno się zrobi, to na drugim łamię zęby

ogólnie rzecz biorąc mam już jakieś doświadczenia z modelami ale to początki

PS. Jak chcecie, to mogę umieścić cały swój kod oparty o klasę QSqlQueryModel mam tam zaimplementowany QItemDelegate, Qt::ItemFlags (Qt::ItemIsEditable), no i mam swój "model" ale połamałem zęby na dodawaniu i usuwaniu rekordów, bo dodają się i usuwają ale nie są edytowalne, gdyż QSqlQueryModel nie ma czegoś takiego jak insertRow i removeRow, co prawda dziedziczy to po QAbstractItemModel ale nie da się już edytować tych rekordów

Hmmm, z opisu jaki efekt chcesz uzyskać wynika, że potrzebujesz tak de facto prezentacji tego, co zwróci zapytanie QSqlQuery. W takim wypadku nie ma co się bawić w dodawanie/usuwanie wierszy, tylko robisz reset modelu opartego o QSqlQuery za każdym razem jak ustawiasz nowe zapytanie. Edycję pola zrobisz wtedy poprzez pobieranie QSqlRecord i QSqlField.

Na razie, zamiast pokazywać kod, opisz jakieś przykładowe zapytania i ich wynik, oraz w jaki sposób ma wyglądać ich edycja.


"Sugeruję wyobrazić sobie Słońce widziane z orbity Merkurego, a następnie dupę tej wielkości. W takiej właśnie dupie specjalista ma teksty o wspaniałej atmosferze, pracy pełnej wyzwań i tworzeniu innowacyjnych rozwiązań. Pracuje się po to, żeby zarabiać, a z resztą specjalista sobie poradzi we własnym zakresie, nawet jeśli firma mieści się w okopie na granicy obu Korei."
-somekind,
konkretny człowiek-konkretny przekaz :]

Pozostało 580 znaków

2019-11-08 08:51
0

trochę się nie rozumiemy, źle objaśniłem sprawę, a więc tak:

  1. program łączy się z bazą i przy pomocy zapytania pobiera dane z bazy
    (w bazie jest tak, że mam jedną tabelę główną w której zawarte są klucze obce i tutaj chciałbym korzystać z QItemDelegate aby wyświetlać listę rozwijaną QComboBox, wiem, że można to lepiej osiągnąć za pomocą QSqlRelationalDelegate ale chcę to sobie poćwiczyć i się nauczyć)
  2. pobrane dane z bazy ładują się do modelu
  3. model wyświetla dane w widoku QTableView
  4. model ten musi być edytowalny aby użytkownik mógł sobie zmienić dowolny rekord wedle uznania
  5. musi mieć możliwość dodawania i usuwania wybranych rekordów

Co chcę osiągnąć ?

  1. Umieć tworzyć zapytania SQL i ich wynik zwracać do modelu
  2. otrzymany wynik zapytania model musi umieć zwrócić na przykład wybrane dane widokowi
    (chciałbym też umieć ukrywać niektóre kolumny np z ID bo user nie musi ich oglądać, a niektóre kolumny chciałbym mieć zablokowane do edycji gdyż jest pewna potrzeba aby user w tych kolumnach nie grzebał)
  3. dodawać, usuwać i edytować wybrane rekordy

bla
edytowany 1x, ostatnio: zkubinski, 2019-11-08 08:52

Pozostało 580 znaków

2019-11-08 12:07
0

pozwolę sobie zrobić mały update pierwszego postu. Poradziłem sobie z problemem wyświetlania rekordów w widoku. Wszystko się rozeszło o właściwe zrozumienie jak odwołać się do wskaźnika metody wirtualnej, jest to pokazane w pliku mainwindow.cpp w miejscu absModel = new MyModel();

no więc kod jest taki:

  1. Klasa MainWindow

plik mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QWidget>
#include <QGridLayout>
#include <QTabWidget>
#include <QVBoxLayout>
#include <QHBoxLayout>

#include <QAbstractItemModel>
#include <QTableView>

class MyModel;

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private:
    QWidget *mainWigdet, *widgetTab1, *widgetTab2;
    QGridLayout *mainLayout;
    QTabWidget *mainTabWidget;
    QVBoxLayout *layout1;
    QHBoxLayout *BttLayout1;

    QAbstractItemModel *absModel;
    QTableView *view;
};
#endif // MAINWINDOW_H

plik mainwindow.cpp

#include "mainwindow.h"
#include "mymodel.h"

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{
    //![1]
        mainWigdet = new QWidget(this);
    //![/1]

    //![2]
        mainLayout = new QGridLayout(mainWigdet);
    //![/2]

    //![3]
        mainTabWidget = new QTabWidget(mainWigdet);
    //![/3]

    //![4]
        widgetTab1 = new QWidget(mainTabWidget);
        widgetTab2 = new QWidget(mainTabWidget);
    //![/4]

        mainTabWidget->addTab(widgetTab1, "Widok");
        layout1 = new QVBoxLayout();

    absModel = new MyModel();
    //absModel->rowCount();
    //absModel->columnCount();

    view = new QTableView();
    view->setModel(absModel);

    mainWigdet->setLayout(mainLayout);
    mainLayout->addWidget(mainTabWidget,0,0);

    widgetTab1->setLayout(layout1);
    layout1->addWidget(view);

    this->setCentralWidget(mainWigdet);
}

MainWindow::~MainWindow()
{
}
  1. Klasa MyModel

plik mymodel.h

#ifndef MYMODEL_H
#define MYMODEL_H

#include <QAbstractItemModel>

class MyModel : public QAbstractItemModel
{
public:
    MyModel(QWidget *parent=nullptr);

    static int _column, _row;
    QModelIndex _parent;

    int columnCount(const QModelIndex &parent = QModelIndex()) const override;
    int rowCount(const QModelIndex &parent = QModelIndex()) const override;

    bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;

    QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
    QModelIndex parent(const QModelIndex &index) const override;
};

#endif // MYMODEL_H

plik mymodel.cpp

#include "mymodel.h"
#include <QDebug>

int MyModel::_row=5;
int MyModel::_column=3;

MyModel::MyModel(QWidget *parent)
{
}

int MyModel::columnCount(const QModelIndex &parent) const
{
    qDebug()<<"funkcja columnCount"<<_column;
    return _column;
}

int MyModel::rowCount(const QModelIndex &parent) const
{
    qDebug()<<"funkcja rowCount"<<_row;
    return _row;
}

QVariant MyModel::data(const QModelIndex &index, int role) const
{
}

QModelIndex MyModel::index(int row, int column, const QModelIndex &parent) const
{
    qDebug()<< "wykonala sie funkcja index";
    qDebug()<< "parent"<<_parent.parent();
    return _parent;
}

QModelIndex MyModel::parent(const QModelIndex &index) const
{
}

bool MyModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
}

No i widzę stworzone przez siebie kolumny i wiersze oraz zastanawiam się dalej co trzeba zrobić. W sumie się domyślam, że trzeba te metody jakoś ogólnie oprogramować co mają robić, potem dodać jakąś klasę z zapytaniami QSqlQuery i przekierować te zapytanie do funkcji MyModel::setData i zobaczyć efekty ale jeszcze muszę wiedzieć ile ma wierszy i kolumn tabela w bazie itp...

Jak macie jakieś uwagi (nawet te krytyczne), pomysły, propozycje to podzielcie się.


bla

Pozostało 580 znaków

2019-11-08 12:54
0

Chcesz koniecznie zrobić sposobem trudniejszym, cóż, kimże my z Markiem jesteśmy aby ci bronić? Proszę bardzo, reimplementuj QAbstractItemModel - w sumie, to nawet wskazane jest na pewnym etapie nauki Qt aby jakiś item model od zera napisać.
Jednak tutaj zacznij od implementacji metody index(), jak będziesz ją miał wtedy reszta będzie duużo prostsza.


"Sugeruję wyobrazić sobie Słońce widziane z orbity Merkurego, a następnie dupę tej wielkości. W takiej właśnie dupie specjalista ma teksty o wspaniałej atmosferze, pracy pełnej wyzwań i tworzeniu innowacyjnych rozwiązań. Pracuje się po to, żeby zarabiać, a z resztą specjalista sobie poradzi we własnym zakresie, nawet jeśli firma mieści się w okopie na granicy obu Korei."
-somekind,
konkretny człowiek-konkretny przekaz :]

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

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