Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум на CrossPlatform.RU _ Qt Разработка баз данных _ Проблема с QTableView

Автор: Terep 20.11.2010, 11:11

Приветствую.
Я здесь новенький. Хотя читаю форум и сайт постоянно, решил зарегаться только сейчас.
Не бейте палками, знаю, что тема избитая, но мне нужна помощь. Долгие чтения статей на trolltech.com, на этом форуме/сайте мне не помогли.

Пишу диплом на QT, параллельно изучая ее.

Итак проблема.
Код:

#include <QtGui>
#include <QtSql>
#include "mainwindow.h"

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QSqlDatabase db = QSqlDatabase::addDatabase( "QMYSQL" );
    db.setDatabaseName( "dbname" );
    db.setUserName( "root" );
    db.setPassword("pass");
    db.setHostName( "localhost" );
    db.open();
    if (!db.open())
        {
            QMessageBox::warning( 0 , "Error! Not connect to base", db.lastError().databaseText());
        }
    QSqlTableModel model;// = new QSqlTableModel;
    QTableView *view = new QTableView;
    QString str = "tereptab";
    view->setModel(&model);
    model.setTable(str);
    model.select();
    view->show();
    app.exec();
    return 0;

Работает прекрасно, проблем не возникает.
Но когда я начинаю его пользовать в своем дипломнике, начинаются проблемы.

В поиске решения, я написал небольшой пример, наглядно демонтрирующий проблему:
[b]main.cpp[/b]

#include <QtGui>
#include <QtSql>
#include "mainwindow.h"

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    MainWindow *mw = new MainWindow();
        mw->setGeometry(200,200,640,480);
        mw->show();
        app.setStyle(new QPlastiqueStyle);
    app.exec();
    return 0;
}
//---------------------------------------------------
[b]mainwindow.cpp[/b]
#include "mainwindow.h"
//#include "ui_mainwindow.h"
#include <QtSql>

MainWindow::MainWindow()
{
    mainWidget = new QWidget();
    lay = new QVBoxLayout;
    butCon = new QPushButton(tr("Connect"));
    connect(butCon, SIGNAL(clicked()), this, SLOT(slotCon()));
    lay->addWidget(butCon);
    mainWidget->setLayout(lay);
    setCentralWidget(mainWidget);
}

MainWindow::~MainWindow()
{
}

void MainWindow::slotCon()
{
    QSqlDatabase db = QSqlDatabase::addDatabase( "QMYSQL" );
    db.setDatabaseName( "terep" );
    db.setUserName( "root" );
    db.setPassword("vertrigo");
    db.setHostName( "localhost" );
    db.open();
    if (!db.open())
        {
            QMessageBox::warning( 0 , "Error! Not connect to base", db.lastError().databaseText());
        }
    QSqlTableModel model;// = new QSqlTableModel;
    QTableView *view = new QTableView;
    QString str = "tereptab";
    view->setModel(&model);
    model.setTable(str);
    model.select();
    view->show();
    setCentralWidget(view);
}
//---------------------------------------------------
[b]mainwindow.h[/b]

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QMessageBox>

#include <QtGui>
#include <QtSql>

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow();
    ~MainWindow();
    QPushButton *butCon;
    QVBoxLayout *lay;
    QWidget *mainWidget;


private slots:
    void slotCon();
};


#endif // MAINWINDOW_H


Проблема заключается в том, что в первом варианте таблица отображается нормально.
Во втором (необходимом) это выглядит так:


То есть сам Грид куда то девается.

Прошу помощи. Уже вот вот грядет защита :)

ps пишу под 7ой виндой, QT 2010.05

Автор: BRE 20.11.2010, 11:21

void MainWindow::slotCon()
{
    QSqlDatabase db = QSqlDatabase::addDatabase( "QMYSQL" );
    db.setDatabaseName( "terep" );
    db.setUserName( "root" );
    db.setPassword("vertrigo");
    db.setHostName( "localhost" );
    db.open();                        // ??? Хватит и одного open
    if (!db.open())                    // ???
        {
            QMessageBox::warning( 0 , "Error! Not connect to base", db.lastError().databaseText());
        }


    QSqlTableModel model;// = new QSqlTableModel;        // <<<<<<< Что произойдет с объектом model после выхода из slotCon?


    QTableView *view = new QTableView;
    QString str = "tereptab";
    view->setModel(&model);
    model.setTable(str);
    model.select();
    view->show();
    setCentralWidget(view);
}


Автор: Terep 20.11.2010, 11:45

Сделал так:

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QMessageBox>
#include <QtGui>
#include <QtSql>

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow();
    ~MainWindow();
    QPushButton *butCon;
    QVBoxLayout *lay;
    QWidget *mainWidget;
    QSqlTableModel *model;



private slots:
    void slotCon();
};


#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include <QtSql>

MainWindow::MainWindow()
{
    mainWidget = new QWidget();
    model = new QSqlTableModel;
    lay = new QVBoxLayout;
    butCon = new QPushButton(tr("Connect"));
    connect(butCon, SIGNAL(clicked()), this, SLOT(slotCon()));
    lay->addWidget(butCon);
    mainWidget->setLayout(lay);
    setCentralWidget(mainWidget);
}

MainWindow::~MainWindow()
{
}

void MainWindow::slotCon()
{
    QSqlDatabase db = QSqlDatabase::addDatabase( "QMYSQL" );
    db.setDatabaseName( "terep" );
    db.setUserName( "root" );
    db.setPassword("vertrigo");
    db.setHostName( "localhost" );
    if (!db.open())
        {
            QMessageBox::warning( 0 , "Error! Not connect to base", db.lastError().databaseText());
        }
    QTableView *view = new QTableView;
    QString str = "tereptab";
    view->setModel(model);
    model->setTable(str);
    model->select();
    view->show();
    setCentralWidget(view);
}


Где-то еще проблема... :(
View теперь совсем отсутствует.

Unable to find table tereptab.
Буду разбираться.

Автор: BRE 20.11.2010, 11:52

Объект QSqlTableModel нужно создавать после открытия базы данных, но создавать его нужно на куче.

Автор: Terep 20.11.2010, 12:07

QSqlDatabase db = QSqlDatabase::addDatabase( "QMYSQL" );
    db.setDatabaseName( "terep" );
    db.setUserName( "root" );
    db.setPassword("vertrigo");
    db.setHostName( "localhost" );
    if (!db.open())
        {
            QMessageBox::warning( 0 , "Error! Not connect to base", db.lastError().databaseText());
        }
    model = new QSqlTableModel;
    QTableView *view = new QTableView;
    QString str = "employee";
    view->setModel(model);
    model->setTable(str);
    model->select();
    QMessageBox::warning( 0 , "Error! Not connect to base", model->lastError().text());
    view->show();
    view->showGrid();
    setCentralWidget(view);


Ну вот, к базе подключились, с таблицей проблем нет, есть одна с отображением:


И, простите, что значит "на куче"?


upd то есть таблица не отобразилась. она точно не пустая.

upd про кучу понял :rolleyes:

Автор: BRE 20.11.2010, 12:12

Попробуй вначале настраивать модель (setTable, select), а потом указать ее view. Хотя модель во время select должна сама уведомить view.

Точно таблица не пустая? :)

Автор: Terep 20.11.2010, 12:21

К сожалению, уже много раз пробовал и так и сяк.
В данный момент :

    db = QSqlDatabase::addDatabase( "QMYSQL" );
    db.setDatabaseName( "terep" );
    db.setUserName( "root" );
    db.setPassword("vertrigo");
    db.setHostName( "localhost" );
    if (!db.open())
        {
            QMessageBox::warning( 0 , "Error! Not connect to base", db.lastError().databaseText());
        }
    model = new QSqlTableModel;
    QString str = "tereptab";
    model->setTable(str);
    model->select();
    view = new QTableView;
    view->setModel(model);
    view->show();
    setCentralWidget(view);


результат тот же, то есть заголовки дергает нормально, а саму таблицу нет.

upd возможно, это все потому что:
Цитата
QSqlDatabasePrivate::removeDatabase: connection 'qt_sql_default_connection' is still in use, all queries will cease to work.

И из-за этого она просто не может селект * выполнить.

Хотя в деструкторе убиваю соединение:

MainWindow::~MainWindow()
{
    db.close();
    db.removeDatabase(db.connectionName());
}


Может, еще и модель надо разрушать..

Автор: Terep 20.11.2010, 13:00

В данный момент:

#include "mainwindow.h"
#include <QtSql>

MainWindow::MainWindow()
{
    mainWidget = new QWidget();

    lay = new QVBoxLayout;
    butCon = new QPushButton(tr("Connect"));
    connect(butCon, SIGNAL(clicked()), this, SLOT(slotCon()));
    lay->addWidget(butCon);
    mainWidget->setLayout(lay);
    setCentralWidget(mainWidget);
}

MainWindow::~MainWindow()
{
    db.close();
    QSqlDatabase::removeDatabase("QMYSQL");
    delete(lay);
    delete(butCon);
    model->clear();
    delete(model);
    delete(view);
}

void MainWindow::slotCon()
{
    db = QSqlDatabase::addDatabase("QMYSQL");
    db.setDatabaseName( "terep" );
    db.setUserName( "root" );
    db.setPassword("vertrigo");
    db.setHostName( "localhost" );
    if (!db.open())
        {
            QMessageBox::warning( 0 , "Error! Not connect to base", db.lastError().databaseText());
        }
    model = new QSqlTableModel;
    QString str = "tereptab";
    model->setTable(str);
    model->select();
    view = new QTableView;
    view->setModel(model);
    view->show();
    setCentralWidget(view);
}


Таблица по прежнему не выводится :(
В соседней теме прочитал, что варнинг по поводу незакрытого соединения при выходе можно игнорить.
В чем проблема так и не могу понять...

Автор: Terep 20.11.2010, 16:15

И еще, может кто подскажет почему вот от этого:

QString str = "employee";
    model->setTable(str);

приложению хорошо

А при таком раскладе:
model->setTable("employee");


падает на
model->select();

Автор: Litkevich Yuriy 20.11.2010, 16:21

Цитата(Terep @ 20.11.2010, 14:21) *
Хотя в деструкторе убиваю соединение:
ты не правильно удаляешь соединение, смотри описание соответствующего метода.
Но проблема отображения не в этом. В принципе можно вообще не удалять соединение.

Terep, открой свою таблицу в демке - sqlbrowser будет ли работать?

Автор: Terep 20.11.2010, 16:47

Как то странно.
Названия таблиц дергает, схему показывает, а при двойном клике по таблице рушится и семерка начинает искать причину падения...
На любой таблице такая реакция

Автор: Terep 20.11.2010, 17:23

Под Дебианом работает :blink:
Кинулся скорее добивать диплом под ним.

Форум Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)