Russian Qt Forum
Апрель 19, 2024, 02:29 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало Форум WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  
  Просмотр сообщений
Страниц: [1] 2 3
1  Qt / Вопросы новичков / Re: Статическая сборка 5.14 , сохранение юникода в файле : Июнь 25, 2020, 12:54
Наверное вы добавили библиотеки только тех объектов, которые были использованы в программе. У меня так много всего, что придется долго отбирать, что использовано а что нет.
В соответствии с LGPL лицензией, я, кажется, должен буду добавить к демке не только библиотеки, но и исходники Qt. Мне бы хотелось запихнуть все в один исполняемый файл. Демка не для всеобщего обозрения, а будет высылаться по запросу, в ответ на проявленный интерес. Так что вопросы о нарушении лицензии в данном случае вряд ли уместны... Демка абсолютно бесплатна, а платной версии программы не существует и вряд ли она появится раньше, чем будет куплена коммерческая версия Qt.

Нет не только, я ничего не менял в добавляемых модулях, потому-что боялся, что что-нибудь не будет работать, а статическая сборка создается мягко говоря не быстро... Там было немало лишнего, что по идее можно было убрать, но как я ранее объяснил не стал этого делать, для меня не критично было сколько весит экзэшник 15 Мб, или 9 Мб... Единственное добавил модуль ms-sql, так-как мне нужен был функционал работающий с ms sql server.
2  Qt / Вопросы новичков / Re: Статическая сборка 5.14 , сохранение юникода в файле : Июнь 25, 2020, 12:48

Мне просто интересно - зачем всем именно 1 исполняемый файл? Не проще ли сделасть инсталлятор - он заодно и избавит от вопросов "где та программа, которую я зачем то ставил на прошлой неделе?"


Это риторический вопрос, у каждого свои причины, так же можно спросить, зачем кому-то нужны портабл версии ПО?
3  Qt / Вопросы новичков / Re: Статическая сборка 5.14 , сохранение юникода в файле : Июнь 24, 2020, 10:57

Да, так можно. Я так делал 3 года назад с какой-то из 5-х версий, но получится пакет размером 1.5 гиг.  Грустный А при статической компиляции (правда, на 4-ке) получился экзешник 20 мегабайт со всеми нужными либами внутри + несколько мелких файлов.

У меня программа скомпилированная на Qt 5.3 получилась 15 Мб (программа содержит разные виджеты, диалоговые окна, есть справка, работает с БД MSSQL и большими текстовыми файлами, и т.д.)
4  Qt / Вопросы новичков / Re: Статическая сборка 5.14 , сохранение юникода в файле : Июнь 23, 2020, 13:02
1) Вот настройка статической сборки - https://yourdevice.net/forum/viewtopic.php?f=19&t=1943#p2931, проверял в Qt ver. 5.3 у меня работало, не знаю как будет в 5.14...
2) Не подскажу, надо интернет листать, но если погуглить, то можно много инфы на эту тему найти. Думаю в сторону этого класса надо копать - https://doc.qt.io/qt-5/qtextcodec.html
5  Qt / Вопросы новичков / Re: TableView одна модель, два представления : Июнь 16, 2020, 03:44
Может поможет QAbstractProxyModel - https://doc.qt.io/qt-5/qabstractproxymodel.html
6  Qt / Вопросы новичков / Re: Как проверить, пуста ли EditLine? : Июнь 13, 2020, 15:52
Либо как посоветовал kambala метод setPlaceholderText(const QString &), минимум кода будет...
7  Qt / Вопросы новичков / Re: Как проверить, пуста ли EditLine? : Июнь 13, 2020, 15:39
И что этот рабочий пример делает? Насколько я понял, добавляет виджет, но судя по h файлу, виджет мышки которая может удалять.
Цитировать
Рабочий пример:
....


Мне просто нужно, когда пользователь в первый раз нажимал на это поле с него стиралось фраза "Введите название". Естественно. я надеялся, что в момент нажатия на поле ввода, посылается сигнал. что поле стало активным, что с ним начали работать или что то в этом духе, чтобы потом слотом сделать settext(""); и всё.
Не понимаю, что даёт переопределение mouseЕvent'a.


Если создать два файла lineed.h и main.cpp и добавить их в проект, удалив при этом лишние файлы (если они были созданы), то сразу станет понятно, что этот пример делает. Я не поленился этот пример написать, а ты не поленись сделать пару раз копипаст.

Код этого примера избыточен, main можно так написать:

main.cpp:
Код
C++ (Qt)
#include <QtWidgets>
#include "lineed.h"
 
int main(int argc, char** argv) {
 
   QApplication app(argc, argv);
 
   LineEd LnEd;
 
   LnEd.show();
 
   return app.exec();
}
 

А чтобы не удалялось всё, что написано в поле QLineEdit, можно в методе mousePressEvent() задать дополнительное условие:

lineed.h:
Код
C++ (Qt)
#ifndef LINEED_H
#define LINEED_H
 
#include <QtWidgets>
 
class LineEd : public QLineEdit {
 
protected:
   virtual void mousePressEvent(QMouseEvent*) {
     if(text() == "My Text") clear();
   }
 
public:
   LineEd(QWidget *wgt = 0) : QLineEdit(wgt) {}
 
};
 
#endif // LINEED_H
 

P.S.: поясню, в файле lineed.h происходит создание класса LineEd, наследуемого от QLineEdit. Это необходимо для того, чтобы переопределить метод mousePressEvent(), для работы с событиями мыши, а именно "клика" по полю QLineEdit. "My Text" - это текст, который будет удаляться из поля LineEd при клике по полю мышкой (другой текст удаляться не будет). Думаю подробно объяснил. А, вообще, по-моему, это геморрой так программировать, не зная азы C++, но за настойчивость и терпение респект  Улыбающийся
8  Qt / Вопросы новичков / Re: QTableWidget - вопрос по insert, remove rows : Июнь 09, 2020, 12:31
Да, там все реализовано, с параметрами только разобраться надо

((QAbstractItemModel*)tbl_channels)->removeRows(RowNums);

((QAbstractItemModel*)tbl_channels)->insertRows(Count, NewRowCount - Count);

Изначально вопрос стоял про QTableWidget, при чем тут концепция "модель-представление"? В QTableWidget есть два слота о которых я выше писал. С их помощью можно реализовать приведенный вами код. Единственное нужны будут дополнительные циклы по вектору (для удаления/вставки нужных строк).
9  Qt / Вопросы новичков / Re: QTableWidget - вопрос по insert, remove rows : Июнь 09, 2020, 11:49

Вопрос: никак не могу понять, как сейчас использовать removeRows (сейчас removeRow не подходит), и insertRows (insertRow тоже не подходит)... RowNums - у меня QVector. Мысли только, что надо взять контейнер и чистить - удалять по одной строке...

В классе QTableWidget есть public слоты void insertRow(int row) и void removeRow(int row)
https://doc.qt.io/qt-5/qtablewidget.html#insertRow
https://doc.qt.io/qt-5/qtablewidget.html#removeRow
10  Qt / Вопросы новичков / Re: Combobox и БД : Июнь 07, 2020, 14:20
Со старого проекта дернул подключение к БД и накидал вариант решения задачи с использованием QMultiHash ("Multi" на случай, если значения поля Name в таблице повторяются).
С помощью QtDesigner создал виджет и "кинул" на него QComboBox и QPushButton.


P.S.: Единственное не сделал проверку на повторяющиеся значения. Надо будет использовать метод QHash::values(), который возвращают QList(). И уже с этим списком работать... В данном случае будет возвращено только одно значение Id (последнее в QMultiHash). Если точно повторений в таблице нет, то достаточно метода QHash::value(). И совет от новичка в Qt новичку: старайся почаще заглядывать в справку, сначала будет сложно разобраться, придется все-равно часто обращаться к интернету, но со временем станет легче разбираться с материалом и это скажется на быстроте кодинга и эффективности. И не забывай смотреть методы родителей класса, там много интересного Улыбающийся
И еще, советую простые окна (формы) создавать вручную (без QtDesigner) так зачастую проще и меньше лишнего кода. Наследуешься от QWidget, создаешь нужные элементы управления, создаешь нужный Layout, добавляешь в него эти элементы управления и устанавливаешь Layout на данный виджет.
Спасибо за помощь, но мне все-таки не нравится вариант с хранением пары <QString, int> в каком-либо контейнере. Это требует написания лишнего кода, например, как вы уже отметили, в случае, если значения могут повторяться.
Я воспользовался вариантом, который написал demal:
Код:
model = new QSqlQueryModel();
model->setQuery(QString("SELECT -1 as Id, '(Выберите категорию)' as Name UNION SELECT Id, Name FROM Cat WHERE Cat.Art=%1").arg(articleId));
ui->chooseCategory->setModel(model);
ui->chooseCategory->setModelColumn(1);//В комбобоксе отображается содержимое столбца Name
//Если нужно получить Id:
int id = model->record(ui->chooseCategory->currentIndex()).value(0).toInt();
Все просто и лаконично, как мне кажется. К БД обращаемся всего один раз)

Пожалуйста. Если вариант demal подходит больше и код меньше, то он лучший. Просто, как правило, технология "модель - представление" используется для "больших" данных, а в вашем случае, как я понял, их немного (раз помещаете результат запроса в QComboBox). Но самое главное чтобы код корректно и быстро работал, и был достаточно лаконичен  Улыбающийся
11  Qt / Вопросы новичков / Re: Combobox и БД : Июнь 07, 2020, 08:23
Со старого проекта дернул подключение к БД и накидал вариант решения задачи с использованием QMultiHash ("Multi" на случай, если значения поля Name в таблице повторяются).
С помощью QtDesigner создал виджет и "кинул" на него QComboBox и QPushButton.


widget.h:
Код
C++ (Qt)
#ifndef WIDGET_H
#define WIDGET_H
 
#include <QWidget>
#include <QMultiHash>
 
class QSqlQuery;
 
namespace Ui {
 class Widget;
}
 
class Widget : public QWidget
{
 Q_OBJECT
 
public:
 bool createConnection();
 explicit Widget(QWidget *parent = 0);
 ~Widget();
 
private slots:
 void on_pushButton_clicked();
 
private:
 Ui::Widget *ui;
 QSqlQuery *query;
 QMultiHash<QString, int> *queryHash;
 
};
 
#endif // WIDGET_H
 


widget.cpp:
Код
C++ (Qt)
#include <QtWidgets>
#include <QSqlDatabase>
#include <QSqlError>
#include <QSqlQuery>
#include <QMultiHash>
#include "widget.h"
#include "ui_widget.h"
 
Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) {
 
 ui->setupUi(this);
 
 if(!createConnection()) {
   // connection don't create
   return;
 }
 
 query = new QSqlQuery;
 
 QString strQuery =  "SELECT Id, Art, Name "
                     "FROM MyTable ";
 
 query->setForwardOnly(true); // faster
 
 if(!query->exec(strQuery)) {
   QMessageBox::critical(this, "Error",
                                         QString("Query error")
                                             + query->lastError().driverText() + "; "
                                             + query->lastError().databaseText());
   return;
 }
 
 queryHash = new QMultiHash<QString, int>();
 // insert items to queryHash and comboBox from field "Name"
 while(query->next()) {
   queryHash->insert(query->value("Name").toString(), query->value("Id").toInt());
 
   ui->comboBox->addItem(QString(query->value("Name").toString()));
 }
 
}
 
bool Widget::createConnection() {
 // create connection to DB
 QSqlDatabase db = QSqlDatabase::addDatabase("QODBC3");
 
 QString host = "SERVER\\SQL2008SRV";
 QString dataBase= "MyBase";
 QString userName = "sa";
 QString password = "password";
 
 db.setDatabaseName(QString("Driver={SQL Server};"
                     "Server=%1;Database=%2; Persist Security Info=true;"
                     "uid=%3;pwd=%4").arg(host).arg(dataBase).arg(userName).arg(password));
 
 if(!db.open()) {
   QMessageBox::critical(this, "Error",
                         QString("Connection error"));
 
   return false;
 }
 
 
 return true;
}
 
 
void Widget::on_pushButton_clicked() {
 
  if(queryHash->contains(ui->comboBox->currentText())) {
 
     QMessageBox::information(this,
                               "Value",
                               QString("Id = <b>" +
                               QString().setNum(queryHash->value(ui->comboBox->currentText())) + "</b>")
                              );
  }
}
 
 
Widget::~Widget()
{
 delete ui;
 delete query;
 delete queryHash;
}
 



main.cpp:
Код
C++ (Qt)
#include "widget.h"
#include <QApplication>
 
int main(int argc, char *argv[])
{
 QApplication a(argc, argv);
 Widget w;
 w.show();
 
 return a.exec();
}
 



Нужный результат выдается в слоте on_pushButton_clicked() при сигнале clicked() кнопки pushButton.
Код
C++ (Qt)
void Widget::on_pushButton_clicked() {
 
  if(queryHash->contains(ui->comboBox->currentText())) {
 
     QMessageBox::information(this,
                               "Value",
                               QString("Id = <b>" +
                               QString().setNum(queryHash->value(ui->comboBox->currentText())) + "</b>")
                              );
  }
}
 


P.S.: Единственное не сделал проверку на повторяющиеся значения. Надо будет использовать метод QHash::values(), который возвращают QList(). И уже с этим списком работать... В данном случае будет возвращено только одно значение Id (последнее в QMultiHash). Если точно повторений в таблице нет, то достаточно метода QHash::value(). И совет от новичка в Qt новичку: старайся почаще заглядывать в справку, сначала будет сложно разобраться, придется все-равно часто обращаться к интернету, но со временем станет легче разбираться с материалом и это скажется на быстроте кодинга и эффективности. И не забывай смотреть методы родителей класса, там много интересного Улыбающийся
И еще, советую простые окна (формы) создавать вручную (без QtDesigner) так зачастую проще и меньше лишнего кода. Наследуешься от QWidget, создаешь нужные элементы управления, создаешь нужный Layout, добавляешь в него эти элементы управления и устанавливаешь Layout на данный виджет.
12  Qt / Вопросы новичков / Re: Combobox и БД : Июнь 07, 2020, 07:34
Доброго времени суток, уважаемые форумчане. Qt начал заниматься недавно. Разрабатываю приложение для ведения расходов.
В моем приложении используется БД SQLITE. В ней есть следующая таблица:

Это Названия категорий расходов. Id - внешний ключ.
На графическом интерфейсе у меня есть Combobox. В него я заношу имена категорий таким образом:
1) Создаю объект QSqlQuery и выполняю запрос в БД на выборку всех имен продуктов.
2) Далее с помощью addItem добавляю это в Combobox.

Далее, в некотором месте программы я хочу получить Id категории в соответствии с тем, что в данный момент выбрано в combobox'е. И вот тут из-за того, что в Qt я новичок, я не совсем понимаю, как грамотно это сделать. В голову приходят следующие идеи:
1) Выполнять SQL-запрос на поиск Id категории по ее имени.
2) Либо где-то в таблице хранить map<Name,Id>. И в нужный момент получить нужный Id по имени.
Очевидно, что оба эти подхода плохие, хочется какого-то более элегантного решения.
Т.е., грубо говоря, чтобы я мог написать ui->combobox->currentText() и получить не имя категории, а именно ее Id.
Надеюсь на вашу помощь.

Постоянно выполнять из программы SQL-запросы, это не очень хорошая идея, тем более всё можно реализовать только средствами Qt (выполнив прежде один запрос к БД). Я бы работал не с моделью в данном случае (если база небольшая) а с QSqlQuery. Выполняешь запрос с необходимыми для задачи полями, "помещаешь" его в объект QSqlQuery. Метод next() для итерирования (прохода) по всем строкам запроса и методы: value(int), value(const QString &), для выбора нужного поля в таблице БД. Результат запроса можно поместить в QMultiHash, например (на случай совпадений в базе значений поля Name). И далее работать с хэш-таблицей...
13  Qt / Вопросы новичков / Re: заполнить таблицу ответом на sql-запрос : Май 30, 2020, 15:12
Это если связанные таблицы по ключу, а если у него более сложный запрос, то не получится использовать QSqlRelationalTableModel.

Ну всегда можно связать таблицы через другие, а если нельзя, то в этом нет смысла, по крайней мере если база спроектирована грамотно...  Улыбающийся
14  Qt / Вопросы новичков / Re: Как проверить, пуста ли EditLine? : Май 30, 2020, 05:02

А вообще, в случае. если у меня число в поле по умолчанию есть, а я хочу, чтобы при наведении на поле и нажатию по нему, текст исчезал, это какой сигнал?(понятно, что после этого, можно просто ui->settext(""); сделать).
Проверка нужна чтобы после этого, пользователь может ввести в поле, что нибудь ещё, передумать, стереть и написать ещё раз.


Это не сигнал, а слот. Сигнал просто сигнализирует о чем-то, а слот уже производит какое-то действие.Слот - void QLineEdit::clear(), а подходящего сигнала для QLineEdit нет. Поэтому самое простое перегрузить метод события. Помогут классы событий. Например класс события мыши. Можно перегрузить метод mousePressEvent(QMouseEvent *e) -  https://doc.qt.io/qt-5/qlineedit.html#mousePressEvent. Либо focusInEvent(QFocusEvent *e) - https://doc.qt.io/qt-5/qlineedit.html#focusInEvent, но в этом случае фокус элементом может быть получен, не только по нажатию мыши.

Рабочий пример:

lineed.h:
Код
C++ (Qt)
#ifndef LINEED_H
#define LINEED_H
 
#include <QtWidgets>
 
class LineEd : public QLineEdit {
 
protected:
   virtual void mousePressEvent(QMouseEvent*) {
       clear();
   }
 
public:
   LineEd(QWidget *wgt = 0) : QLineEdit(wgt) {}
 
};
 
#endif // LINEED_H
 

main.cpp:
Код
C++ (Qt)
#include <QtWidgets>
#include "lineed.h"
 
int main(int argc, char** argv) {
 
   QApplication app(argc, argv);
   QWidget      wgt;
 
   LineEd *LnEd = new LineEd;
 
   QVBoxLayout* vLayout = new QVBoxLayout;
   vLayout->addWidget(LnEd);
   wgt.setLayout(vLayout);
 
   wgt.show();
 
   return app.exec();
 
}
 
15  Qt / Вопросы новичков / Re: заполнить таблицу ответом на sql-запрос : Май 29, 2020, 15:07
если я правильно прочитал описание QSqlQueryModel, эта модель выводит 1 таблицу, тогда как у меня более сложный запрос, чем просто вывод таблицы

https://doc.qt.io/qt-5/qsqlrelationaltablemodel.html - класс QSqlRelationalTableModel является наследником QSqlTableModel и обладает более высоким уровнем реализации. Она как раз для более сложных запросов, позволяет работать с несколькими связанными таблицами БД.
Страниц: [1] 2 3

Страница сгенерирована за 0.21 секунд. Запросов: 23.