Просмотр сообщений
|
Страниц: [1] 2 3
|
3
|
Qt / Вопросы новичков / Re: Как QtCreator делает вывод в cout при запуске release сборки?
|
: Апрель 19, 2015, 02:08
|
В коде есть вывод данных в std::cout и std::cerr. Где? В моем коде C++ (Qt) #include <iostream> #include <exception> // std::set_terminate #include <QApplication> #include <QString> #include "Logic.h" void myMessageOutput(QtMsgType type, const QMessageLogContext & context, const QString & msg) { switch (type) { case QtDebugMsg: std::cerr << QString("Debug: %1 (%2:%3, %4)\n").arg(msg).arg(context.file).arg(context.line).arg(context.function).toStdString(); break; case QtWarningMsg: std::cerr << QString("Warning: %1 (%2:%3, %4)\n").arg(msg).arg(context.file).arg(context.line).arg(context.function).toStdString(); break; case QtCriticalMsg: std::cerr << QString("Critical: %1 (%2:%3, %4)\n").arg(msg).arg(context.file).arg(context.line).arg(context.function).toStdString(); break; case QtFatalMsg: std::cerr << QString("Fatal: %1 (%2:%3, %4)\n").arg(msg).arg(context.file).arg(context.line).arg(context.function).toStdString(); abort(); } } void myterminate() { std::cerr << "terminate handler called\n"; abort(); // forces abnormal termination } int main(int argc, char * argv[]) { qInstallMessageHandler(myMessageOutput); std::set_terminate(myterminate); QApplication a(argc, argv); Logic l; return a.exec(); }
И можно ли как-то при запуске приложения без Креатора открыть консоль, чтобы туда валился вывод этого приложения, предназначенный для стандартных потоков? Собрать GUI приложение с соответствующим флагом (например CONFIG += console для qmake). Тогда при запуске GUI приложения будет автоматом запускаться консоль куда и будут выводиться логи. Мне хотелось вот чего. Приложение собирается без консоли (CONFIG -= console). Но если есть желание посмотреть отладочную информацию, открывается консоль и какими-то манипуляциями туда выводится все, что должно выводится в std::cout и std::cerr. У Креаторе же это получается? Как? Но лучше логи выводить через QDebug и иже с ними (для Qt5 есть даже "logging framework"). В этом случае их можно посмотреть через утилиту DebugView. Но это все актуально для Windows. Спасибо. Кое-чего получилось. 1 вариант. Выполняем такой код, когда нужно вызвать консоль(это WinAPI функции): C++ (Qt) if (AllocConsole()) { AttachConsole(GetCurrentProcessId()); freopen( "CON", "w", stdout ); freopen( "CON", "w", stderr ); }
Ссылки по теме: https://support.microsoft.com/ru-ru/kb/58667https://bobobobo.wordpress.com/2009/03/01/how-to-attach-a-console-to-your-gui-app-in-c/2 вариант Отладочную информацию передаем в функцию OutputDebugString (тоже WinAPI). И смотрим программой DebugViewОстается вопрос - как QtCreator перенаправляет потоки вывода себе в Application Output, когда приложение запускается из него?
|
|
|
4
|
Qt / Вопросы новичков / Как QtCreator делает вывод в cout при запуске release сборки?
|
: Апрель 18, 2015, 20:21
|
Здравствуйте!
GUI-приложение, Windows 7. В коде есть вывод данных в std::cout и std::cerr. При запуске приложения из QtCreator вывод идет в консоль самого QtCreator, как на картинке. Как Креатор это делает?
И можно ли как-то при запуске приложения без Креатора открыть консоль, чтобы туда валился вывод этого приложения, предназначенный для стандартных потоков?
|
|
|
5
|
Qt / Общие вопросы / Re: Qt 4.7 или 5.
|
: Декабрь 29, 2014, 02:22
|
Новый синтаксис signal/slot, с проверкой на стадии компиляции. Сомнительная вещь, да и область применения очень узкая - когда сигнатуры сигналов/слотов совпадают 1:1 и нет перекрытых сигналов/слотов. Обойти оба случая можно, просто будет не очень красиво. Перегруженные сигналы. C++ (Qt) connect(ui->spinBox, static_cast<void(QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged), this, &MySuperClass::setFactor);
Несовпадение сигнатур. C++ (Qt) connect(ui->comboBox, &QComboBox::currentTextChanged, [this](const QString & text) { updateText(); });
Зато преимущества нового подхода очевидны - не нужно проверять на работоспособность каждое соединение сигнал/слот в приложении.
|
|
|
6
|
Qt / Общие вопросы / Re: Qt 4.7 или 5.
|
: Декабрь 28, 2014, 04:59
|
Баги правятся, фичи реализуются Чтобы не натыкаться на новые баги ждите версий 5.x.2. Новый синтаксис signal/slot, с проверкой на стадии компиляции. Если у вас приложение на виджетах, они мало развиваются, но немного есть развитие. Мне наоборот интересно, почему люди держаться за Qt4? Понятно, что часто это требование начальства, но интересны аргументы? Слишком большое и сложное приложение, что уже нет смысла портировать на Qt5?
|
|
|
7
|
Qt / Общие вопросы / Как в отладчике узнать адрес наследника QWidget?
|
: Декабрь 16, 2014, 23:44
|
Здравствуйте!
Почему в отладчике отображается адрес объекта, наследованного от QObject (см рис.1 и рис.2), а адрес объекта, наследованного от QWidget не отображается? Вместо него пишется имя класса. (см. рис.3 и рис.4). Это нормально или настало мое время запилить первый тикет в багтрекер?
|
|
|
8
|
Qt / Работа с сетью / Re: Почему такая большая задержка Ack по QTcpSocket?
|
: Октябрь 06, 2014, 00:25
|
Видимо придётся, ибо эта информация довольно специфична. На мой взгляд задержка в пределах нормы. Обычно для максимального быстродействия контролем доставки пренебрегают Быстрее запросить пакет, чем дожидаться доставки Сделал нативный сервер. Разницы с Qt-шным не заметил. У меня Core-i3 3220, ответ через 200 мс. C++ (Qt) #include <iostream> #include <winsock2.h> int main() { WSAData wsa; WORD Version = MAKEWORD(2, 1); WSAStartup(Version, &wsa); SOCKET Listen = socket(AF_INET, SOCK_STREAM, NULL); SOCKET Connect = socket(AF_INET, SOCK_STREAM, NULL); SOCKADDR_IN Server; Server.sin_addr.s_addr = inet_addr("192.168.0.15"); Server.sin_family = AF_INET; Server.sin_port = htons(10000); bind(Listen, (SOCKADDR*)&Server, sizeof(Server)); listen(Listen, 1); std::cout << "Listeninig..." << std::endl; int size = sizeof(Server); while(1) { if (Connect = accept(Listen, (SOCKADDR*)&Server, &size)) { std::cout << "Connection was reached" << std::endl; } } WSACleanup(); std::cin.get(); return 0; }
|
|
|
9
|
Qt / Работа с сетью / Re: Почему такая большая задержка Ack по QTcpSocket?
|
: Октябрь 05, 2014, 20:18
|
А почему вы думаете что это в Qt? Какая задержка при использовании платформозависимого кода?
Я не знаю, что и думать, поэтому и спрашиваю о типовом времени подтверждении на пакет. Не хотелось, но, видимо, придется сделать тест сокетов без Qt.
|
|
|
10
|
Qt / Работа с сетью / Почему такая большая задержка Ack по QTcpSocket?
|
: Октябрь 05, 2014, 18:44
|
Добрый день. Пишу программу для соединения с прибором по TCP. Программа на компьютере выступает сервером. Я обнаружил, что задержка подтверждения Tcp пакета 125 - 250 миллисекунд, в зависимости от мощности компьютера сервера. Создал тестовых клиента и сервера. Проекты прикладываю. Задержки подтверждения сохраняются. Это нормально? Какое должно быть типовое время Ack, при работе в одной сети (через роутер)? В сервере перенос сокета в отдельный поток не изменило ничего. Я обратил внимание на время подтверждения пакета Тcp т.к. в приборе стоит uIP стек https://ru.wikipedia.org/wiki/UIP_(micro_IP). Этот стек ждет Ack на пакет, и только после этого посылает следующий. Qt 5.3.1, Windows 7 Клиент. C++ (Qt) #include <iostream> #include <QCoreApplication> #include <QTcpSocket> #include <QTimer> #include <QHostAddress> int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QTcpSocket * socket = new QTcpSocket; QObject::connect(socket, static_cast<void(QTcpSocket::*)(QAbstractSocket::SocketError)>(&QTcpSocket::error), [=]() { std::cout << socket->errorString().toStdString() << std::endl; }); socket->connectToHost(QHostAddress("192.168.0.6"), 10000); QTimer * timer = new QTimer; timer->start(100); QObject::connect(timer, &QTimer::timeout, [=]() { QByteArray data = "Some data"; if (socket->write(data) != -1) { std::cout << "data sent ok" << std::endl; } }); return a.exec(); }
Сервер. C++ (Qt) #include <iostream> #include <QCoreApplication> #include <QTcpServer> #include <QTcpSocket> #include <QHostAddress> #include <QObject> int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QTcpSocket * socket = nullptr; QTcpServer * server = new QTcpServer; QObject::connect(server, &QTcpServer::newConnection, [&]() { if (socket) { delete socket; } socket = server->nextPendingConnection(); std::cout << "Connection established." << std::endl; if (socket) { QObject::connect(socket, &QTcpSocket::disconnected, []() { std::cout << "Connection lost." << std::endl; }); QObject::connect(socket, static_cast<void (QTcpSocket::*)(QAbstractSocket::SocketError)>(&QAbstractSocket::error), [&] (QAbstractSocket::SocketError) { std::cout << "Error " << socket->errorString().toStdString() << std::endl; }); } }); if (!server->listen(QHostAddress("192.168.0.6"), 10000)) { std::cout << "Can't start server:"; std::cout << server->errorString().toStdString() << std::endl; return 0; } std::cout << "Server started." << std::endl; //QThread * serverThread = new QThread; //server->moveToThread(serverThread); //serverThread->start(QThread::TimeCriticalPriority); return a.exec(); }
|
|
|
12
|
Qt / Вопросы новичков / Re: проектирование пользовательского интерфейса
|
: Июль 16, 2014, 16:42
|
Я тут подумал, что можно сделать так: 1. Создаем минимально необходимый пул виджетов, которые нужны для проектирования. Т.е. если форм всего 10, и на каждой не больше 2-х кнопок, значит в пуле всего 2 кнопки. При старте приложения заполняем пул. std::vector<QWidget *> widgets; widgets.push_back(new QPushButton); widgets.push_back(new QPushButton); widgets.push_back(new QComboBox); 2. Нужно создать классы-описания формы. Если при стандартном подходе эти классы генерит uic из *.ui файлов, тот тут их нужно создать самим. Первое что приходит в голову - копипастой. И заменить в методе динамическое создание виджетов на выбор их из пула. Самое ценное, что есть в файлах, созданных uic, это настройка виджетов. Для этого: Создаем вспомогательный проект. В нем создаем столько *.ui файлов, сколько форм в приложении. Редактируем их в Дизайнере до полного удовлетворения. После прохода uic по *.ui файлам получаем несколько ui_<имя_ui_файла>.h файлов. Далее копируем их в свой проект, изменяем создание виджетов на выбор из пула. Я бы просто в методе просто удалил строки с new. Выбор из пула сделал бы в конструкторе. Пока выглядит несложно. Как только форма скрывается - ее нужно удалять, которая появляется - создавать. Это будет работать быстро, ведь нет выделения памяти, только выбор из пула и настройка виджетов под новый вид.
|
|
|
13
|
Qt / Вопросы новичков / Re: проектирование пользовательского интерфейса
|
: Июль 15, 2014, 20:14
|
Вариант "создать форму и удалить ее сразу после использования" был предложен мной первым, в ответ было сказано, что будет медленно. (целевое устройство совсем слабенькое).
Сделайте тестовое приложение, две насыщенные формы. Поочереди их создавайте, показывайте и удаляйте. Замерьте время. Будут хоть какие-то данные.
|
|
|
14
|
Qt / Вопросы новичков / Re: проектирование пользовательского интерфейса
|
: Июль 15, 2014, 16:13
|
Расскажите подробнее, что конкретно не понятно? Пока такие советы: 1. Максимально отделить GUI от логики работы программы (ядра). GUI должен быть незатейливым проводником сигналов между пользователем и ядром. 2. Возможно, требования к программе еще не до конца сформировались и будут меняться по ходу разработки программы. Надо предусмотреть эту возможность. Если вы создадите динамическое изменение компонентов на одной форме, вас ждет много боли, когда требования к GUI будут меняться. Пишите программу со стандартным подходом, не запариваясь на экономию памяти и остального. Вот когда напишете, протестируете, тогда и будете оптимизировать GUI. У вас это легко получится, ведь вы GUI хорошо отделили от ядра по моему первому совету
|
|
|
15
|
Qt / Вопросы новичков / Посоветуйте паттерн для последовательности долгих вычислений.
|
: Май 02, 2014, 16:40
|
Здравствуйте! Над данными нужно произвести последовательно несколько длительных преобразований (2-3 секунды). Пусть преобразования обозначаются - A, B, C, D, E... Пользователь выбрал данные - преобразования начинают выполняться последовательно А->B->C... Пользователь не дожидаясь окончания всей последовательности меняет данные - последовательность должна прекратить выполнение и начать снова с А. У каждого преобразования есть параметры. Как только меняется параметр преобразования, например Е, последовательность должна прерваться и начать с Е с новым параметром. Т.е. все это меняется на лету, пользователю доступны параметры всех преобразований, то С поменял, то А. Подскажите, как это красиво реализовать? Некрасиво уже сделал Если нужно больше конкретики, напишу.
|
|
|
|
|