Здравствуйте, B0FEE664, Вы писали:
BFE>Что значит, "изменим условние"? Название темы однозначно говорит о консольном приложении.
+1
BFE>Например, выход из приложения. Как корректно выйти из консольного приложения (с графическими окнами) ожидающего ввод пользователя при shutdown?
Установить обработчик на ctrl+c и спросить пользователья точно ли он хочет выйти
BFE>Проблемы могут быть связаны со скоростью: вывод в одно окно тормозит вывод во всех других окнах.
Сколько-нибудь вменяемый для человека вывод ничего тормозить не будет. Миллион записей из БД разом можно вывести, но зачем?
BFE>Так же и обратные сообщения от ввода в окнах: данные к отдельным ниткам проходят через общий цикл, если не делать специальных ухищрений.
И? Взаимодействие пользователя с окнами не может сгенерировать хоть сколько-нибудь значительное количество сигналов.
BFE>Так же могут возникнуть проблемы при завершении отдельных потоков.
Если криво писать — то да, наверное, могут.
Здравствуйте, imh0, Вы писали:
RW>>может, для визуальной части сделать отдельную gui-шную программу ненавистно висящую в трее? и пусть мониторит какой-нибудь файл в простейшем случае или обменивается с консольной по пайпу?
I>Нет тут, надо исходить и того, что такое как бы требование- надо чтобы было консольное приложене. На самом деле это библиотека и надо чтобы ее можно было использовать и в консольном приложении тоже. Все это под линукс, тут все горазло проще чем под виндой. То есть изначально нет разницы что это за приложение. Тут нет такого понятия как "подсистема" как в винде.
А что мешает установить X11 сессию, в нужный момент (а вдруг иксов не окажется, может лучше заранее?) и собственно отрисовать окно (второе, третье) когда нужно, а не на старте программы? В юниксе нет понятия "графическая программа" или "консольная" (как верно замечено, нет понятия подсистемы, как в виндах). Любая программа может сделать что угодно и когда попало.
Но практически, повторюсь, сессию начать наверное стоит на старте, и даже окна может быть создать сразу (чтоб потом не тупить). Просто делать эти окна видимыми по факту необходимости.
Здравствуйте, kov_serg, Вы писали:
_>гуй пускаеш в отдельном потоке и выдаёш ему подписку на источник данных.
Главное чтоб гуй случайно не стал многопоточным. Винда так может местами и может,
а X11 заклинит. Нет, что-то отослать (запрос на X11 сервер) ещё так можно, но ответы от сервера,
цикл обработки событий, неизбежно слушать нужно в одном потоке. На самом деле можно не в одном,
но синхронизироваться нужно и непонятно зачем тогда такое нужно. Читать иксовый сокет должен
строго один поток (ждать событий), да и писать одновременно не стоит (в сокете будет мешанина).
_>а консольное прложение пишет данные в этот самый источник.
Я бы просто в отдельном потоке запустил иксовую сессию, цикл обработки событий. И в нём
делал бы все гуёвые дела, событийным методом. И туда же накидывал события от негуёвых
частей системы.
_>С точки зрения архитектуры гуи и простое консольное не должны знать о существовании друг друга.
I>Уверен, что вешь трвиальная, но тем не менее... По эвентам это значит я не контролирую процесс выполнения приложения. То есть процесс обработки каких-то внешних по отношению к QT событиям идет лесом.
А всё остальное пускаешь в отдельных потоках. И они накидываюют эвенты в гуёвый евент-луп если
им что-то от него нужно. А он в свою очередь их может пинать через их евент-лупы, если у них
есть, напрямую вызывать их функци и т.п.
I> А мне как раз и надо чтобы по какому-то внешнему событию создавались окна и также ассинхронно по отношению к QT они могли закрываться.
Асинхронно по отношению к графической системе не получится. Цикл на самом деле не в Qt, а в X11.
Т.е. на самом деле в X11 его нет, там только несколько функций которые нужно вызывать в цикле, а
цикл действительно внешний и в Qt, но работать вне цикла не получится вообще тем не менее.
I> Тут даже не главное закрывать окна, тут главное чтобы не было потери уравления в результате передачи управления в app.exec... Когда я сам диспечеризирую события QT то я могу также диспечеризировать внешние события.
В отдельных потоках. По крайней мере в ещё одном отдельном потоке, по меньше мере ещё одном.
Потому, что GUI будет блокироваться на 1) ожидании своих событий, 2) отрисовке.
Здравствуйте, B0FEE664, Вы писали:
BFE>Здравствуйте, imh0, Вы писали:
I>>Смотрите, вопрос по теме форума, вопрос не простой, вопрос на самом деле актуальный... BFE>Вопрос слишком обширный и не понятно, чего хочет imh0. BFE>Если он хочет несколько консольных окон в одном приложении с одним(!) запущенным процессом — то это не возможно.
С хера ли невозможно? Запускай 10 штук xterm'ов и каким-то образом передавай от них файл-дескрипторы, от slave-конца псевдотерминала себе в аппликацию. Через, например, некий мелкий процесс который тебе их, файл-дескрипторы, через сокет обратно вышлет, например. Только я посмотрел, это тебе даже не нужно, т.к. xterm имеет опцию -S, т.е. может рабоать с уже созданным тобой и существующим псевдотерминалом. В общем говно вопрос. У тебя в итоге десяток псевдотерминалов и пиши/читай в любой. Сам, без printf только.
BFE>Есть ещё вариант, обеспечивать окна внутри консоли (псевдографикой).
Здравствуйте, Skorodum, Вы писали:
BFE>>Например, выход из приложения. Как корректно выйти из консольного приложения (с графическими окнами) ожидающего ввод пользователя при shutdown? S>Установить обработчик на ctrl+c и спросить пользователья точно ли он хочет выйти
А если пользователь выходит по Ctrl-\ ? А если по Ctrl-Z и Ctrl-D, Ctrl-D ?
А если пользователь мышкой закрывает xterm в котором программа?
А если зашёл через ssh и тут интернет оборвался?
А если сисадмина обидели, он уволился и в кронтаб вставил kill -11 $RANDOM ?
Re[11]: Создать окна в консольном приложении. Как?
I>Честно? Твой ответ вообще не по теме. Мне надо после a.exec() работать, ты мне привел пример того что и так ясно... Но я уже сказал — извини, но таким тоном можешь разговаривать дома. А лучше и там не надо.
Что именно нужно делать "после"? С точки зрения Qt ничего "после" быть не может. Если надо "после" — то в отдельном потоке. А лучше — вот этот весь код с QApplication в отдельный поток. Но я об этом уже писал выше.
S>>Тебе надо Qt хоть немного понять, и чтобы вопрос нормально сформулировать и чтобы ответы понимать. I>Ага еще раз спасибо )
Если хотите абстрактно от Qt — то вы должны понимать и уметь реализовывать в многопоточной среде такие паттерны как chain of responsibility и producer consumer. Иначе все объяснения бесполезны.
Ваша проблема — вы не можете понять где вам проинициализировать обработчик. Об этом я тоже выше писал — надо понимать что у вас за события. Без этого не получится предметного разговора.
P.S. ко всем участникам темы — давайте не переходить на личности и оскорбления, а то достану банхаммер.
Очень псевдокод:
class Handler : public QObject
{
Q_OBJECT
public:
// ...void on_my_event()
{
QTimer::singleShot(0, this, &Handler::show_gui);
}
void show_gui()
{
// Создаём окно. Это уже будет вызвано в Qt потоке
}
}
int qt_thread(conditional_variable& cv, Handler *h)
{
QApplication app;
h = new Handler;
h->setParent(&app);
cv.wake_all();
return app.exec();
}
void main_thread()
{
conditional_variable& cv;
Handler *h = nullptr;
std::thread t{&qt_thread, cv, h};
cv.wait();
// Прилетает сигнал - дёргаем наш прокси
h->on_my_event();
}
Здравствуйте, Skorodum, Вы писали:
S>Здравствуйте, SaZ, Вы писали:
SaZ>>В любом случае всё сводится к следующему: создаётся отдельный поток в котором делается инстанс QApplication. S>Обычно QApplication и все гуёвые события в основном потоке (собственно, QApplication::exec и стартуерт "main event loop"), а вот что-то типа работы с сетью — в отдельных потоках.
Там где-то проскакивало условие, что нужно из динамической библиотеки это делать. Всё сводится к тому, что считать "основным потоком". Если в Qt за последние 5 лет ничего не поменялось, то основной поток это тот, в котором инициализируются глобальные qtшные переменные и создаётся QCoreApplication. Делать это в разных потоках так себе идея, но у меня работало.
Re[12]: Создать окна в консольном приложении. Как?
Здравствуйте, SaZ, Вы писали:
SaZ>Ваша проблема — вы не можете понять где вам проинициализировать обработчик. Об этом я тоже выше писал — надо понимать что у вас за события. Без этого не получится предметного разговора.
Ага. Спасибо....
Но пока с Skorodum-умами пререкались, я все и сделал. Вроде архитектурно не плохо... Приводить код и подробно описывать неверное не имеет смысл, но кратко суть такая...
1) В main создаю поток через std::thread создаю поток П1.
2) В потоке П1 создаю обьект класс MYLIB отнаследованного от QApplication. В этом классе обьявленны сигналы и слоты CreateWindow, DestryWindow, и некоторыми функциями для вывода данных в окна.
3) В потоке П1 с помощью QObject::connect с транспортом через Qt::BlockingQueuedConnection, соединяю эти сигналы со слотами.
4) В потоке П1 через статический глобальный std::promise<MYLIB*> MyLib с помощью set_value устанавливаю значение для созданного в П1 обьекта.... Можно было ды обойтись и без глобальной переменной но мне это пока не критично.
5) В потоке П1 запускаю QT exec()... То есть QT поехала... )
5) В main через std::future <MYLIB*> на MyLib жду когда библиотека будет от-инициализирована в потоке П1.
6) В любой точке любого потока пользовательского кода, вызывается например функция (MYLIB*)->CreateWindow которая отрабатывает в SLOT соединенный с CreateWindow. И так как транспорт Qt::BlockingQueuedConnection то пока слот не отработает то пользовательский код висит и ждет.
То есть удалось сделать красиво — избежать диспечеризации событий, но при этом корректно вызывать создание окон из одного единственного потока. И блокировки X11 дисплея удалось избежать, и QT висит на своем exec() и все кросплатформенно.
Думал код тут выложить — там строк 200 вместе с двойной буферизацией черех QPIXMAP... Но думаю нет смысла, мало кому это покажеться интересным..
Здравствуйте, SaZ, Вы писали:
SaZ>Там где-то проскакивало условие, что нужно из динамической библиотеки это делать.
Какая разница какая линкова? Это ничего не меняет
Потоки сторонней библиотеки оборачиваются в QThreaed, события прокидываются в основной поток через стандартные сигналы/слоты.
Здравствуйте, imh0, Вы писали:
I>>>Как это все сделать с точки зрения архитектуры?
RW>>может, для визуальной части сделать отдельную gui-шную программу ненавистно висящую в трее? и пусть мониторит какой-нибудь файл в простейшем случае или обменивается с консольной по пайпу?
I>Нет тут, надо исходить и того, что такое как бы требование- надо чтобы было консольное приложене. На самом деле это библиотека и надо чтобы ее можно было использовать и в консольном приложении тоже. Все это под линукс, тут все горазло проще чем под виндой. То есть изначально нет разницы что это за приложение. Тут нет такого понятия как "подсистема" как в винде.
Раз библиотека — просто реализуешь нужные функции, и всё. А откуда они будут вызываться — проблема пользователя библиотеки
Здравствуйте, imh0, Вы писали:
BFE>>>>Насколько я знаю процесс может либо не иметь консоли, либо иметь ровно одну консоль. Так что все окна вам придётся рисовать внутри одной и той же консоли.
I>>>Ну во первых консолей можно открыть сколько хочешь, и в винде и в линуксе.... BFE>>И для каждого придётся запустить отдельный процесс.
I>Да ладно...
BFE>Елки-палки! Опять это секретное знание ускользнёт от меня. Ну намекните хотя бы, в какое из множества консольных окон будет направлен вывод printf?
Ну, если бы такое было бы возможно, то наверное printf выводил бы в ту консоль, к которой приаттачен STDOUT
Здравствуйте, fk0, Вы писали:
BFE>>Если он хочет несколько консольных окон в одном приложении с одним(!) запущенным процессом — то это не возможно.
fk0> С хера ли невозможно? Запускай 10 штук xterm'ов и каким-то образом передавай от них файл-дескрипторы, от slave-конца псевдотерминала себе в аппликацию. Через, например, некий мелкий процесс который тебе их, файл-дескрипторы, через сокет обратно вышлет, например. ...
Здравствуйте, Skorodum, Вы писали:
BFE>>Проблемы могут быть связаны со скоростью: вывод в одно окно тормозит вывод во всех других окнах. S>Сколько-нибудь вменяемый для человека вывод ничего тормозить не будет. Миллион записей из БД разом можно вывести, но зачем?
Здравствуйте, imh0, Вы писали:
BFE>>Т.е. сторонний процесс всё равно обязателен. I>)) Нет, не обязателен!! )
Вы сами себе противоречите.
I>Кончай уже офтопить. Где тут винда и консоли в форуме QT?
Я что-то писал про винду? Винда или линукса, так или иначе придётся создавать отдельный процесс для ввода-вывода.
Что же касается офтопа, то вполне может быть, что вся тема к Qt отношения не имеет, так как для того, чтобы создать приложение, которое запускает несколько общающихся друг с другом процессов с консольными окнами можно сделать как с использованием Qt, так и без Qt.
I>Как делать рассказывать не буду, и не проси. )
Жаль.
И каждый день — без права на ошибку...
Re[10]: Создать окна в консольном приложении. Как?
Здравствуйте, fk0, Вы писали:
S>>Установить обработчик на ctrl+c и спросить пользователья точно ли он хочет выйти fk0> А если пользователь выходит по Ctrl-\ ? А если по Ctrl-Z и Ctrl-D, Ctrl-D ?
Так же установить обработчик, если это желаемое поведение
fk0>А если пользователь мышкой закрывает xterm в котором программа? fk0>А если зашёл через ssh и тут интернет оборвался? fk0>А если сисадмина обидели, он уволился и в кронтаб вставил kill -11 $RANDOM ?
Ничего не делать. Стандартное поведение в таких случаях — умереть. Чтобы поведение было нестандартным должны быть очень веские причины.
I>Есть простое консольное приложение. I>Требуется в зависимости от каких-то событий, создавать окна.
Практически любая либа для гуйев тебе такую возможность предоставляет. Но если у тебя нет дисплея для окошек, то где эти окна ты будешь создавать?
Re[10]: Создать окна в консольном приложении. Как?