Добавление класса для работы с БД
Для открытия и подготовки БД в Android используется наследник класса . Мы тоже создадим наследник этого класса , но он будет сильно модифицированный, так как мы будем работать с готовой базой данных, а не создавать ей с помощью SQL запросов:
Ниже приведен текст всего класса, который нужно просто скопировать (не трогая свой первой строчки ):
Для работы в последующим с другими базами данных вам ничего не нужно будет менять в данном классе, кроме строчек:
Разберем что означают эти строчки.
— имя файла БД. Какой файл БД вы создали, такое название сюда и копируем.
— путь к БД. Каждое приложение в Android имеет свою область памяти, куда складываются файлы программы. Вдруг вы захотите вывернуть путь к файлу БД. Я бы ничего не трогал.
— самая интересная переменная (причем в примерах в сети по работе с готовой БД её обходят стороной). Это номер версии БД. Ниже описан принцип работы данного класса. Например, вы пишите справочник рецептов под Android и рецепты храните в БД. В момент создания установки приложения программа должна скопировать БД на устройство. Потом через какое-то время вы решили обновить приложение, и БД у вас обновилась: структура БД поменялась, добавились новые рецепты. И вам нужно заменить старую БД на новую. Вот тут вы и пропишите в данной переменной новую версию БД. И при открытии приложения будет произведена проверки версии БД, и файл БД обновится. Вначале версия БД равна 1.
Итак, логика работы класса в подготовке базы данных:
-
Копируем файл БД, если этого файла нет (при установке приложения).
-
Если номер БД обновлен, то заменяем один файл базы данных на другой:
После работы с базой данных из данного класса вытаскиваем экземпляр SQLiteDatabase, с которым будем работать в дальнейшем: осуществлять запросы и так далее.
NOT NULL и DEFAULT
Ограничитель NOT NULL используют, чтобы запретить оставление поля пустым. По умолчанию, если поле не является первичным ключом, в него можно не помещать данные. В этом случае полю будет присвоено значение NULL. В случае NOT NULL вы не сможете добавить запись, не указав значения соответствующего поля.
Однако, добавив ограничитель DEFAULT, вы сможете не указывать значение. DEFAULT задает значение по умолчанию. В результате, когда данные в поле не передаются при добавлении записи, поле заполняется тем, что было указано по умолчанию.
Допустим, в таблице поля url, theme и num не должны быть пустыми. При этом если значение для num не передается, то полю присваивается 0. В этом случае команда для создания таблицы будет такой:
sqlite> CREATE TABLE pages ( ...> _id INTEGER PRIMARY KEY AUTOINCREMENT, ...> title TEXT, ...> url TEXT NOT NULL, ...> theme INTEGER NOT NULL, ...> num INTEGER NOT NULL DEFAULT 0);
С помощью команд и PRAGMA TABLE_INFO() можно посмотреть схему таблицы.
Внешний ключ
С помощью внешнего ключа устанавливается связь между записями разных таблиц. Внешний ключ в одной таблице для другой является первичным. Внешние ключи не обязаны быть уникальными. В одной таблице может быть несколько внешних ключей, при этом каждый будет устанавливать связь со своей таблицей, где он является первичным.
Представим, что у нас есть вторая таблица, в которой перечислены темы-разделы, а их номера являются уникальными идентификаторами.
sqlite> CREATE TABLE sections ( ...> _id INTEGER PRIMARY KEY, ...> name TEXT);
Тогда в первой таблице в столбце theme следует хранить номера тем – их ID, взятые из второй таблицы. Это будут внешние ключи, представляющие собой первичные в таблице с разделами. Внешние ключи уникальными не будут, так как разные страницы могут принадлежать к одной и той же теме.
sqlite> CREATE TABLE pages ( ...> _id INTEGER PRIMARY KEY AUTOINCREMENT, ...> title TEXT, ...> url TEXT NOT NULL, ...> theme INTEGER NOT NULL, ...> num INTEGER NOT NULL DEFAULT 100, ...> FOREIGN KEY (theme) REFERENCES sections(_id) ...> );
FOREIGN KEY является ограничителем, так как не дает нам записать в поле столбца theme какое-либо иное значение, которое не встречается в качестве первичного ключа в таблице sections. Однако в SQLite поддержка внешнего ключа по умолчанию отключена. Поэтому, даже назначив столбец внешним ключом, вы сможете записывать в его поля любые значения.
Чтобы включить поддержку внешних ключей в sqlite3, надо выполнить команду . После этого добавить в таблицу запись, в которой внешний ключ не совпадает ни с одним первичным из другой таблицы, не получится.
Изменение значений в таблице
Изменить значение в какой-либо записи можно с помощью SQL командыUPDATEили с помощью метода db.update:
<p>public int UpdateEmp(Employee emp) { SQLiteDatabase db=this.getWritableDatabase(); ContentValues cv=new ContentValues(); cv.put(colName, emp.getName()); cv.put(colAge, emp.getAge()); cv.put(colDept, emp.getDept()); return db.update(employeeTable, cv, colID+"=?",new String{String.valueOf(emp.getID())}); }</p>
Метод update имеет следующие параметры:
- String Table: название таблицы в которой мы хотим что-то изменить.
- ContentValues cv: пара ключ-значение с новой информацией.
- String where: строка-шаблон, определяющая условие WHERE, которое проверяется для каждой строки таблицы. Ксли условие истинно, то в этой строке обновляется информация в соответствии с параметром cv.
- String[] args: массив с аргументами, которые подставляются в строку-шаблон where.
Database — Creation
In order to create a database you just need to call this method openOrCreateDatabase with your database name and mode as a parameter. It returns an instance of SQLite database which you have to receive in your own object.Its syntax is given below
SQLiteDatabase mydatabase = openOrCreateDatabase("your database name",MODE_PRIVATE,null);
Apart from this , there are other functions available in the database package , that does this job. They are listed below
Sr.No | Method & Description |
---|---|
1 |
openDatabase(String path, SQLiteDatabase.CursorFactory factory, int flags, DatabaseErrorHandler errorHandler) This method only opens the existing database with the appropriate flag mode. The common flags mode could be OPEN_READWRITE OPEN_READONLY |
2 |
openDatabase(String path, SQLiteDatabase.CursorFactory factory, int flags) It is similar to the above method as it also opens the existing database but it does not define any handler to handle the errors of databases |
3 |
openOrCreateDatabase(String path, SQLiteDatabase.CursorFactory factory) It not only opens but create the database if it not exists. This method is equivalent to openDatabase method. |
4 |
openOrCreateDatabase(File file, SQLiteDatabase.CursorFactory factory) This method is similar to above method but it takes the File object as a path rather then a string. It is equivalent to file.getPath() |
Работа с запросами к базе данных из приложения Flask.
Теперь в каждой функции-представлении можно получить доступ к функции , которая возвращает текущее открытое соединение с базой данных. Для упрощения работы с SQLite полезна высоко оптимизированная . Эта фабрика поддерживает доступ к результату запроса как к словарю, где ключ это имя столбца. Она выполняется для каждого результата, возвращаемого из базы данных. Вставим код ниже в функцию , которая была создана выше:
db.row_factory = sqlite3.Row
Это заставит модуль возвращать объекты . Эти объекты представляют собой , поэтому, к ним можно получить доступ либо по индексу, либо по ключу. Например, предположим, что есть объект , который называется с полями базы данных , , , и :
# Можно получить значения по имени поля >>> r'FirstName' # John # или по его индексу >>> r1 # John # объекты `Row` можно перебирать в цикле: >>> for value in r ... print(value) # 1 # John # Doe # M
Кроме того, рекомендуется создать функцию для запроса к БД, которая сочетает в себе получение курсора, выполнение запроса и получение результатов:
def query_db(query, args=(), one=False): cur = get_db().execute(query, args) rv = cur.fetchall() cur.close() return (rv if rv else None) if one else rv
Эта небольшая функция в сочетании с фабрикой делает работу с любой базой данных намного более приятной, чем при использовании простого курсора и объектов соединения.
Вот как это можно использовать:
for user in query_db('SELECT * FROM users'): print(user'username'], 'has the id', user'user_id'])
Или, если нужен только один результат:
user = query_db('SELECT * FROM users WHERE username = ?', the_username], one=True) if user is None print('No such user') else print(the_username, 'has the id', user'user_id'])
Чтобы передать переменные части в SQL запрос, необходимо использовать вопросительный знак и передавать параметры в виде списка. Никогда не добавляйте их напрямую в SQL запрос как форматированную строку, т.к. это позволяет атаковать приложение с помощью SQL-инъекций.
Database — Insertion
we can create table or insert data into table using execSQL method defined in SQLiteDatabase class. Its syntax is given below
mydatabase.execSQL("CREATE TABLE IF NOT EXISTS TutorialsPoint(Username VARCHAR,Password VARCHAR);"); mydatabase.execSQL("INSERT INTO TutorialsPoint VALUES('admin','admin');");
This will insert some values into our table in our database. Another method that also does the same job but take some additional parameter is given below
Sr.No | Method & Description |
---|---|
1 |
execSQL(String sql, Object[] bindArgs) This method not only insert data , but also used to update or modify already existing data in database using bind arguments |
Executing Queries
To execute queries, there are two methods:
- Execute method
- Execute method
To execute a raw query to retrieve all departments:
Java
Copy Code
Cursor getAllDepts() { SQLiteDatabase db=this.getReadableDatabase(); Cursor cur=db.rawQuery("SELECT "+colDeptID+" as _id, "+colDeptName+" from "+deptTable,new String [] {}); return cur; }
The method has two parameters:
- : The statement
- : The arguments if a clause is included in the statement
Notes
- The result of a query is returned in object.
- In a statement if the primary key column (the id column) of the table has a name other than , then you have to use an alias in the form as cause the object always expects that the primary key column has the name or it will throw an exception .
Another way to perform a query is to use a method. A query to select all employees in a certain department from a view would be like this:
Java
Copy Code
public Cursor getEmpByDept(String Dept) { SQLiteDatabase db=this.getReadableDatabase(); String [] columns=new String[]{"_id",colName,colAge,colDeptName}; Cursor c=db.query(viewEmps, columns, colDeptName+"=?", new String[]{Dept}, null, null, null); return c; }
The has the following parameters:
- : The name of the table to run the query against
- columns: The projection of the query, i.e., the columns to retrieve
- clause: clause, if none pass
- selection args: The parameters of the clause
- : A specifying group by clause
- : A specifying clause
- : A clause
2: Создание базы данных SQLite
На этом этапе мы создадим базу данных, содержащую фиктивные данные (в нашем случае это будет список различных видов акул и их свойств). Чтобы создать базу данных, откройте свой терминал и выполните эту команду sqlite3:
Это создаст новую базу данных по имени sharks. Если файл sharks.db уже существует, SQLite откроет его; если его не существует, SQLite создаст его.
Вы получите такой вывод:
SQLite version 3.31.1 2020-01-27 19:55:54 Enter ".help" for usage hints.
После этого ваша командная строка изменится. Появится новый префикс sqlite>.
Если файл sharks.db еще не существует и вы выйдете из строки sqlite без выполнения каких-либо запросов, файл sharks.db не будет создан. Чтобы убедиться, что файл создан, вы можете запустить пустой запрос, введя точку с запятой, а затем Enter. Таким образом вы убедитесь, что файл базы данных действительно был создан.
Подготовив базу данных Shark, вы можете создать новую таблицу и заполнить ее данными.
Транзакции в SQLite
Управление транзакциями — одна из функций баз данных SQL, и SQLite также обрабатывает их. Транзакция — это последовательность изменений, в которой вы можете безопасно изменить базу данных, выполнив запрос и затем разместив .
Если по какой-то причине непосредственно перед фиксацией вы не хотите завершать транзакцию, вы можете вернуться в предыдущее состояние перед фиксацией, используя .
Точно так же мы также можем просматривать состояние базы данных через эти типы изменений.
import sqlite3 db_filename = 'database.db' def display_table(conn): cursor = conn.cursor() cursor.execute('select name, size, date from images;') for name, size, date in cursor.fetchall(): print(name, size, date) with sqlite3.connect(db_filename) as conn1: print('Before changes:') display_table(conn1) cursor1 = conn1.cursor() cursor1.execute(""" insert into images (name, size, date) values ('JournalDev.png', 2000, '2020-02-20'); """) print('\nAfter changes in conn1:') display_table(conn1) print('\nBefore commit:') with sqlite3.connect(db_filename) as conn2: display_table(conn2) # Commit from the first connection conn1.commit() print('\nAfter commit:') with sqlite3.connect(db_filename) as conn3: display_table(conn3) cursor1.execute(""" insert into images (name, size, date) values ('Hello.png', 200, '2020-01-18'); """) print('\nBefore commit:') with sqlite3.connect(db_filename) as conn2: display_table(conn2) # Revert to changes before conn1's commit conn1.rollback() print('\nAfter connection 1 rollback:') with sqlite3.connect(db_filename) as conn4: display_table(conn4)
Выход
Before changes: sample.png 100 2019-10-10 ask_python.png 450 2019-05-02 class_room.jpeg 1200 2018-04-07 After changes in conn1: sample.png 100 2019-10-10 ask_python.png 450 2019-05-02 class_room.jpeg 1200 2018-04-07 JournalDev.png 2000 2020-02-20 Before commit: sample.png 100 2019-10-10 ask_python.png 450 2019-05-02 class_room.jpeg 1200 2018-04-07 After commit: sample.png 100 2019-10-10 ask_python.png 450 2019-05-02 class_room.jpeg 1200 2018-04-07 JournalDev.png 2000 2020-02-20 Before commit: sample.png 100 2019-10-10 ask_python.png 450 2019-05-02 class_room.jpeg 1200 2018-04-07 JournalDev.png 2000 2020-02-20 After connection 1 rollback: sample.png 100 2019-10-10 ask_python.png 450 2019-05-02 class_room.jpeg 1200 2018-04-07 JournalDev.png 2000 2020-02-20
Здесь, как видите, таблица изменяется только после того, как мы явно завершим транзакцию. Любые изменения до этого фактически не изменяют таблицу. Наконец, мы откатываем запись , чтобы она не вставлялась в таблицу.
Updating Values
To execute an statement, we have two ways:
- To execute
- To execute method:
Java
Copy Code
public int UpdateEmp(Employee emp) { SQLiteDatabase db=this.getWritableDatabase(); ContentValues cv=new ContentValues(); cv.put(colName, emp.getName()); cv.put(colAge, emp.getAge()); cv.put(colDept, emp.getDept()); return db.update(employeeTable, cv, colID+"=?", new String []{String.valueOf(emp.getID())}); }
The method has the following parameters:
- : The table to update a value in
- : The content values object that has the new values
- : The clause to specify which record to update
- : The arguments of the clause
Выборка данных из базы SQLite с помощью JOIN
Нельзя использовать метод SQLiteDatabase query() для выполнения запроса к нескольким таблицам. Для этого нужно составить собственный SQL-запрос. В приведенном ниже примере запрос определяется в классе SampleDBContract:
public static final String SELECT_EMPLOYEE_WITH_EMPLOYER = "SELECT * " + "FROM " + Employee.TABLE_NAME + " ee INNER JOIN " + Employer.TABLE_NAME + " er " + "ON ee." + Employee.COLUMN_EMPLOYER_ID + " = er." + Employer._ID + " WHERE " + "ee." + Employee.COLUMN_FIRSTNAME + " like ? AND ee." + Employee.COLUMN_LASTNAME + " like ?";
Обратите внимание, что в условии WHERE мы используем символ «?». Чтобы не нарушить синтаксис SQL нужно определить selectArgs String [] со значениями, которые будут заменять в предоставленном SQL-запросе символ «?»:
private void readFromDB() { String firstname = binding.firstnameEditText.getText().toString(); String lastname = binding.lastnameEditText.getText().toString(); SQLiteDatabase database = new SampleDBSQLiteHelper(this).getReadableDatabase(); String[] selectionArgs = {"%" + firstname + "%", "%" + lastname + "%"}; Log.d(TAG, SampleDBContract.Employee.QUERY_WITH_EMPLOYER); Cursor cursor = database.rawQuery(SampleDBContract.Employee.QUERY_WITH_EMPLOYER, selectionArgs); Log.d(TAG, "The total cursor count is " + cursor.getCount()); binding.recycleView.setAdapter(new SampleJoinRecyclerViewCursorAdapter(this, cursor)); }
Usage
Extend as you would normally do , providing the constructor with a database name and version number:
public class MyDatabase extends SQLiteAssetHelper { private static final String DATABASE_NAME = "northwind.db"; private static final int DATABASE_VERSION = 1; public MyDatabase(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } }
SQLiteAssetHelper relies upon asset file and folder naming conventions. Your folder will either be under your project root, or under if you are using the default gradle project structure. At minimum, you must provide the following:
- A folder inside
- A SQLite database inside the folder whose file name matches the database name you provide in code (including the file extension, if any)
For the example above, the project would contain the following:
Earlier versions of this library required the database asset to be compressed within a ZIP archive. This is no longer a requirement, but is still supported. Applications still targeting Gingerbread (API 10) or lower should continue to provide a compressed archive to ensure large database files are not corrupted during the packaging process. The more Linux friendly GZIP format is also supported. The naming conventions using the above example are as follows:
- ZIP: (a single SQLite database file must be the only file within the archive)
- GZIP:
The database will be extracted from the assets and copied into place within your application’s private data directory. If you prefer to store the database file somewhere else (such as external storage) you can use the alternate constructor to specify a storage path. You must ensure that this path is available and writable whenever your application needs to access the database.
super(context, DATABASE_NAME, context.getExternalFilesDir(null).getAbsolutePath(), null, DATABASE_VERSION);
The database is made available for use the first time either or is called.
The class will throw a if you do not provide the appropriately named file.
The SQLiteOpenHelper methods , and are not supported by this implementation and have been declared .
The samples:database-v1 project demonstrates a simple database creation and usage example using the classic Northwind database.
Управление внешними ключами
Давайте создадим триггер, который будет следить при добавлении нового сотрудника за тем, чтобы указанный в описании сотрудника департамент присутствовал в таблице Dept. SQL команда, создающая такой триггер, выглядит следующим образом:
CREATE TRIGGER fk_empdept_deptid Before INSERT ON Employees FOREACH ROW BEGIN SELECTCASE WHEN((SELECT DeptID FROM Dept WHERE DeptID=new.Dept) ISNULL) THEN RAISE(ABORT,'Foreign Key Violation')END; END Добавим в метод onCreate вызов метода execSQL с соответствующим запросом db.execSQL("CREATE TRIGGER fk_empdept_deptid "+ " BEFORE INSERT "+ " ON "+employeeTable+ " FOR EACH ROW BEGIN"+ " SELECT CASE WHEN ((SELECT "+colDeptID+" FROM "+deptTable+ " WHERE "+colDeptID+"=new."+colDept+" ) IS NULL)"+ " THEN RAISE (ABORT,'Foreign Key Violation') END;"+ " END;");
Более сложные запросы
Для выполнения других операций с данными можно использовать следующие методы.
-
INSERT — добавляет новый объект в базу данных.
-
Получить T > — пытается получить объект с помощью первичного ключа.
-
Таблица T > — возвращает все объекты в таблице.
-
Удалить — удаляет объект, используя его первичный ключ.
-
Запрос T > — выполнение SQL запроса, возвращающего несколько строк (в виде объектов).
-
Execute — используйте этот метод (а не ), если не предполагается, что строки возвращаются из SQL (например, инструкции INSERT, UPDATE и DELETE).
Выбор объекта с помощью LINQ
Методы, возвращающие поддержку коллекций, поэтому можно использовать LINQ для запроса или сортировки содержимого таблицы. В следующем коде показан пример использования LINQ для фильтрации всех записей, начинающихся с буквы «A»:
Выбор объекта с помощью SQL
Несмотря на то, что SQLite.Net может предоставлять доступ к данным на основе объектов, иногда может потребоваться более сложный запрос, чем разрешено LINQ (или может потребоваться более высокая производительность). с помощью команды SQL можно использовать метод Query, как показано ниже:
Примечание
при написании инструкций SQL напрямую вы создаете зависимость от имен таблиц и столбцов в базе данных, которые были созданы из классов и их атрибутов. при изменении этих имен в коде следует помнить, что необходимо обновить любые SQL инструкции, написанные вручную.
Удаление объекта
Первичный ключ используется для удаления строки, как показано ниже:
Вы можете проверить, сколько строк было затронуто (удалено в этом случае).
2. Использование базы данных SQLite
Каждое приложение для Android может создавать и использовать базы данных SQLite для хранения больших объемов структурированных данных. Как вы уже знаете, SQLite не только лёгкая, но и очень быстрая. Если у вас есть опыт работы с системами управления реляционными базами данных и вы знакомы как с SQL, что является сокращением для Structured Query Language, и JDBC, что является сокращением для Java Database Connectivity, это может быть предпочтительным вариантом хранения.
Чтобы создать новую базу данных SQLite или открыть уже существующую, вы можете использовать метод внутри своей активити или службы. В качестве аргументов вы должны передать имя своей базы данных и режим, в котором вы хотите её открыть. Наиболее часто используемый режим , который гарантирует, что база данных доступна только для вашего приложения. Например, вот как вы можете открыть или создать базу данных с именем my.db:
После создания базы данных вы можете использовать метод для запуска SQL-инструкций. В следующем коде показано, как использовать оператор SQL для создания таблицы названной user, которая имеет три столбца:
Хотя можно вставить новые строки в таблицу с помощью метода , лучше использовать метод . Метод ожидает объект , содержащий значения для каждого столбца таблицы. Объект очень похож на объект и содержит пары ключ-значение.
Вот два объекта , которые вы можете использовать с таблицей :
Как вы могли догадаться, ключи, которые вы передаете методу , должны соответствовать именам столбцов в таблице.
Когда объекты готовы, вы можете передать их методу вместе с именем таблицы.
Чтобы отправить запрос в базу данных, вы можете использовать метод , который возвращает объект , содержащий результаты запроса.
Объект может содержать ноль или несколько строк. Самый простой способ перебрать все его строки, так это вызвать метод внутри цикла .
Чтобы получить значение отдельного столбца, вы должны использовать такие методы, как и , которые ожидают индекс столбца. Например, вот как вы получите все значения, вставленные в таблице :
После того, как вы получите все результаты вашего запроса, убедитесь, что вы вызвали метод для объекта , чтобы освободить все ресурсы, которые он хранит.
Аналогичным образом, когда вы закончили все операции с базой данных, не забудьте вызвать метод для объекта .
Выполнение SQL запросов
Для выполнения запросов в Android используются два метода:db.rawQuery иdb.query. Давайте сделаем запрос к базе, с целью получения списка всех департаментов:
Cursor getAllDepts() { SQLiteDatabase db=this.getReadableDatabase(); Cursor cur=db.rawQuery("SELECT "+colDeptID+" as _id, "+ colDeptName+" from "+deptTable,new String{}); return cur; }
МетодrawQuery имеет два параметра:
- String query: Строка с SQL запросом SELECT.
- String[] selection args: массив аргументов where, если он используется в SELECT запросе.
Замечания! В качестве результата этого запроса возвращается объектCursor. Если в качестве ключевого поля в таблице используется колонка с именем, отличным от _id, Вам необходимо использовать alias в форме «SELECT as _id». Дело в том, что объектCursorвсегда считает, что ключевое поле имеет имя_id, и если это не так, генерируется исключение.Другим способом выполнения запроса к базе является вызов методаdb.query. Давайте напишем метод, который выдает всех сотрудников, работающих в каком-то конкретном департаменте:
public Cursor getEmpByDept(String Dept) { SQLiteDatabase db=this.getReadableDatabase(); String columns=new String{"_id",colName,colAge,colDeptName}; Cursor c=db.query(viewEmps, columns, colDeptName+"=?",new String{Dept},null,null,null); return c; }
Методdb.query имеет следующий набор параметров:
- String Table Name: Имя таблицы, из которой осуществляется выборка.
- String columns: список столбцов, которые войдут в результат.
- String WHERE clause: шаблон where-условия или null.
- String selection args: массив с аргументами where-условия.
- String Group by: условие группировки.
- String Having: условие HAVING.
- String Order By by: порядок сортировки.
Подключение GtkListStore для вывода таблицы
В GTK+ для работы со сложными данными используется GtkTreeModel — набор функций для хранения и отображения данных.
Существует две модели хранения GtkListStore и GtkTreeStore и один виджет отображения GtkTreeView, который поддерживает обе модели хранения.
Для работы с таблицами нужно сделать запрос к БД и поместить результат в структуру GtkListStore. Виджет GtkTreeView отобразит данные в виде таблицы.
Для работы с таблицей в GTK+ нужно:
- Создать буфер GtkListStore.
- Добавить строки в буфер.
- Создать таблицу GtkTreeView.
- Добавить столбцы в таблицу.
Для обращения к таблице используется:
- Итератор GtkTreeIter — текущая строка.
- Колонка GtkTreeViewColumn — текущий столбец.
- Рендер GtkCellRenderer — текущая ячейка.
Запускаем Glade и готовим виджет, для этого.
- Создаем буфер liststore1 для модели таблицы,
- Создаем виджет дерева treeview1.
- Указываем для этого виджета буфер liststore1.
Сохраняем интерфейс в файл main.glade. Виджет готов, теперь его надо настроить: указать столбцы и формат ячеек.