Перейти до основного вмісту

Qt зависання процесу в Windows

Я лінуксоід, і вже натякав на це в інших постах. Але я роблю програми не тільки для використання в середовищі Linux, а й для Windows. Велика частина з того, що я робив первинно була написана саме в Linux, а вже потім перенесена в Windows. Тестуючи програми в обох системах, маю зазначити таку неприємну особливість Windows. При виконанні тривалого процесу, вікно програми зависає. Запускаючи той же самий процес в Linux, принаймні на Ubuntu, такого не трапляється.

Наведу невеличкий приклад. Потрібно витягнути з файлу декілька рядків.

Звичайно, читаючи 20 рядків користувач нічого не помітить. Але я стикався з завданнями, коли обробити потрібно 15 або навіть більше 40 тисяч рядків. І в такому процесі виникає тимчасове "зависання" вікна. Вікно на будь-які дії не відповідає, а іноді Windows просто показує, що програма зависла. Якщо прогресс не відображається, найчастіше, сторонній користувач в диспетчері задач просто "вбиває" процес. Насправді ж процес обробки даних триває в штатному режимі, і результат, незважаючи на тимчасове зависання, буде коректно відображено після виконання всіх дій.

Цікаво, що зависання таке, може і не виникнути. Але якщо в час виконання подібної операції ви вирішили змінити, скажімо, розмір вікна або перемістити його, у вас нічого не вийде.

Є два рішення подібної проблеми. Перша - це розділити операції на потоки, правильне рішення для масштабних, навантажених процесів. У нашому ж випадку, можна обійтися включенням QApplication :: processEvents () в основний цикл и все буде гаразд.



QList list;
for (int x = 0; x < list.count(); x++) {
   ...
   ui.progressBar->setValue(qFloor((x + 1) * 100 / list.count()));
   QApplication::processEvents();
}



Якщо ви уважно дивились відео, то мабуть помітили, що коли процесс не відображається він проходить скоріше ;)

Коментарі

Популярні дописи з цього блогу

QString в HEX и обратно

Спочатку з QString робимо QByteArray. Зауважимо, якщо у вас по тексту тільки латинські букви цілком підійде варіант з .toUtf8(). Якщо ж присутня і кирилиця - обов'язково використовуємо .toLocal8Bit(). QString strA = "Some text"; QByteArray bA = strA.toLocal8Bit().toHex(); Перетворення QByteArray в початковий текст має такий вигляд: QString strB = QString::fromLocal8Bit(QByteArray::fromHex(bA))); Цікаво, що якщо ми для зберігання записали отриманий Нех куди-небудь, наприклад, в файл або базу даних у вигляді текстового рядка, то для зворотного перетворення цей рядок потрібно додатково перетворити в QByteArray. QString strA2 = QString::fromUtf8(bA); QByteArray bB = strA2.toUtf8(); QString strB = QString::fromLocal8Bit(QByteArray::fromHex(bB)));

Qt та Excel. QTableWidget туди і назад.

У цій статті мова піде про те, як прийняти дані з Excel в QTableWidget і відправити назад в Excel. Візьмемо книгу Excel у якої є 2 листа, на першому розташована невелика таблиця (її ми і буде читати в QTableWidget), а в другій лист порожній, сюди ми віддамо таблицю з QTableWidget.   Ось так, як на малюнку праворуч, виглядає цільова таблиця. На формі розташуємо QTableWidget. Заздалегідь знаючи, якого розміру таблиця, можна відразу виставити кількість стовпців, рядків, прописати назви стовпців, але ми не будемо цього робити. Почнемо з читання таблиці. QAxObject * list;      list = sheets-> querySubObject ("Item (int)", 1); / / оголошуємо лист, на якому таблиця      int colEx = 6; / / оголошуємо кількість стовпців      QStringList headers; / / сюди запишемо заголовки стовпців      for (int a = 1; a <= colEx; a + +) {/ / вичитуємо заголовки        ...

Qt Округлення до певного розряду

Округлення - тривіальна задача в математиці, але в Qt немає функції округлення до певного розряду. Проте в QtMath є такі функції як qFloor (qreal) і QCeil (qreal), в результаті яких int. А також можна використовуючи round (double), отримати double. Дуже швидко я знайшов ось цей ресурс звідки взяв вихідну формулу. Вона без сумніву працює, але дає результати, які не відповідаю моїм очікуванням: toRound(187.156, 2); //187.15 toRound(187.156, 1); //187.1 toRound(187.156, 0); //187 toRound(187.156, -1); //180 toRound(187.156, -2); //100 Після невеликої корекції самої функції, її підсумковий варіант виглядає так: double wcsv::toRound(double val, int r) {   double outpValue;   double tempVal;   tempVal=val*pow(10,r);   if (double(int(tempVal))+0.5==tempVal){     int(tempVal)%2 == 0       ? outpValue=double(qFloor(tempVal))/pow(10,r)       :outpValue=d...