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

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: setMask и тормоза.  (Прочитано 6488 раз)
lighting
Гость
« : Октябрь 28, 2010, 10:04 »

Пишу приложение оформенное в виде интерактивной карты. Для правильной кликабельности границы регионов(QPushButton) ограничиваю маской:
    region1.setMask(QPixmap("./img/region1.png"));
где png - черно-белая маска без градаций и альфа-канала. Позже в процессе работы к регионам применяются stylesheet:
QPushButton { background-color: #AEF3B6; }
Приложение работает на достаточно скромных ресурсах (компьютер на базе microITX, Intel Celeron M 1ГГц). При 33 регионах и регулярном обновлении их стилей система настолько занята применением стилей что на несколько секунд (до минуты) перестает реагировать на события мышки и клавиатуры. При отключении setMask тормоза пропадают.
Подскажите, есть-ли пути оптимизации обработки масок, если нужны исходные коды могу выложить, но там вообщем-то при старте накладываются маски, которые отрабатывается достаточно быстро, а потом достаточно часто(опрос раз в 15 сек.) применяются стиль наподобие вышеприведенного.
Qt 4.5, Ubuntu 9.4
« Последнее редактирование: Октябрь 28, 2010, 10:25 от lighting » Записан
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #1 : Октябрь 28, 2010, 10:30 »

Давай код.
Да и в чём необходимость использования стилей, тем более динамически?
Записан

Qt 5.11/4.8.7 (X11/Win)
pastor
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 2901



Просмотр профиля WWW
« Ответ #2 : Октябрь 28, 2010, 11:31 »

Да, лучше взглянуть на код.


А при каких событиях вызываетя
Код:
region1.setMask(QPixmap("./img/region1.png")); 
Записан

Integrated Computer Solutions, Inc. (ICS)
http://www.ics.com/
lighting
Гость
« Ответ #3 : Октябрь 28, 2010, 12:04 »

Опишу подробнее:
в этих самых регионах есть оборудование, состояние которого мониторится программой. Если оборудование выключилось - вызывается функция которая соответствующему региону меняет цвет на красный через setStylesheet.

mainwindow.h
Код
C++ (Qt)
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
 
#include <QtGui/QMainWindow>
#include <QLabel>
#include <QPushButton>
#include <QBitmap>
#include <QFile>
#include <QTextStream>
#include <QTextCodec>
#include <QRegExp>
#include <QtGlobal>
#include "mapdetaildialog.h"
#include "realtronixcu2000m.h"
#include "tclmonmap.h"
 
enum REGSTATES {STATE_UNKNOWN, STATE_ERROR, STATE_WARNING, STATE_OK, STATE_OK_MIC_ON, STATE_UNACTIVE, STATE_WARNING_MIC_ON};
 
struct RegionProp
{
   int     realtronixPortNum, realtronixMicsCount;
   QString regionName, regionCaption, upsIP, realtronixIP, hdxIP,
           hdxPassword, ciscoName, upsName, realtronixName, hdxName;
 
   int autoFocus;
 
   int state; // 0 - grey, 1 - red, 2 - yellow, 3 - green, 4 - green with mic
   int cisco;
   int ups;
   int realtronix;
   int hdx;
   int mic1, mic2, mic3, mic4, mic5, mic6, mic7;
};
 
class MainWindow : public QMainWindow
{
   Q_OBJECT
 
public:
   MainWindow(QWidget *parent = 0);
   ~MainWindow();
 
private slots:
   void showVeil();
   void hideVeil();
 
   void showRegionDetail(int reg_num);
   void hideRegionDetail();
 
   void muteAll();
 
   void autoFocusToggled(bool enabled);
 
   void RealtronixMicOn(int mic_num);
   void RealtronixMicOff(int mic_num);
 
...
   void repyovka_selected();
   void hohol_selected();
   void ostrogozhsk_selected();
...
 
   void object_state_changed(int reg_num, QString object_name, int object_state);
 
 
...
   void repyovka_mic_state_changed(int port_num, int mic_num, bool active);
   void hohol_mic_state_changed(int port_num, int mic_num, bool active);
   void ostrogozhsk_mic_state_changed(int port_num, int mic_num, bool active);
...
 
private:
   void ParseRegionConfig();
   void FillRealtronixMicsOnPorts(int reg_num, QList<int> *mics_on_ports);
   void StartTclmonMap();
   void StartRealtronixControls();
   void StartHDXControls();
   void RegionMicStateChanged(int reg_num, int port_num, int mic_num, bool active);
 
   void updateRegionState(int reg_num);
 
   QLabel                    monPanel;
   QLabel                 l_repyovka, l_hohol, l_ostrogozhsk, ... ;
   QPushButton         repyovka, hohol, ostrogozhsk, ...;
   QLabel                    map, legendPanel, legendCaption, legendNone, legendNoneCaption, legendOk, legendOkCaption, legendUnactive,
                             legendUnactiveCaption, legendWarning, legendWarningCaption, legendError, legendErrorCaption,
                             legendMic, legendMicCaption;
   MapDetailDialog           mapDetail;
   QPushButton               btnMuteAll;
   QLabel                    lbVeil;
   TclMonMap                 tclmonMap;
   QList<RegionProp>         regionProperties;
   QList<RealtronixCU2000M*> realtronixControls;
   QList<PolycomHDX*>        hdxControls;
   int                       selectedRegionIndex;
};
 
#endif // MAINWINDOW_H

mainwindow.cpp
Код
C++ (Qt)
#include "mainwindow.h"
 
...
MainWindow::MainWindow(QWidget *parent)
   : QMainWindow(parent)
{
   setWindowState(Qt::WindowFullScreen);
 
   QFile file("./qss/main.qss");
   file.open(QFile::ReadOnly);
   QString styleSheet = QLatin1String(file.readAll());
   setStyleSheet(styleSheet);
   mapDetail.setStyleSheet(styleSheet);
   file.close();
 
   map.setParent(&monPanel);
   map.setGeometry(0, 0, 1280, 1024);
   map.setObjectName("map");
 
...
 
   repyovka.setParent(&monPanel);
   repyovka.setGeometry(89, 325, 137, 120);
   repyovka.setMask(QPixmap("./img/repyovka.png"));
   connect(&repyovka, SIGNAL(clicked()), this, SLOT(repyovka_selected()));
   hohol.setParent(&monPanel);
   hohol.setGeometry(130, 205, 137, 166);
   hohol.setMask(QPixmap("./img/hohol.png"));
   connect(&hohol, SIGNAL(clicked()), this, SLOT(hohol_selected()));
   ostrogozhsk.setParent(&monPanel);
   ostrogozhsk.setGeometry(155, 353, 149, 211);
   ostrogozhsk.setMask(QPixmap("./img/ostrogozhsk.png"));
   connect(&ostrogozhsk, SIGNAL(clicked()), this, SLOT(ostrogozhsk_selected()));
   l_repyovka.setParent(&monPanel);
   l_repyovka.setGeometry(110, 380, 100, 30);
   l_repyovka.setText(tr("Репьевка"));
   l_repyovka.setObjectName("mapItem");
   l_repyovka.setAttribute(Qt::WA_TransparentForMouseEvents, true);
   l_hohol.setParent(&monPanel);
   l_hohol.setGeometry(160, 290, 135, 30);
   l_hohol.setText(tr("Хохол"));
   l_hohol.setObjectName("mapItem");
   l_hohol.setAttribute(Qt::WA_TransparentForMouseEvents, true);
   l_ostrogozhsk.setParent(&monPanel);
   l_ostrogozhsk.setGeometry(170, 470, 120, 30);
   l_ostrogozhsk.setText(tr("Острогожск"));
   l_ostrogozhsk.setObjectName("mapItem");
   l_ostrogozhsk.setAttribute(Qt::WA_TransparentForMouseEvents, true);
...
 
void MainWindow::updateRegionState(int reg_num)
{
   int        state;
   RegionProp region = regionProperties.at(reg_num);
 
   if (reg_num == 0) {
       state = STATE_UNKNOWN;
   } else if (region.cisco == 0) {
       state = STATE_ERROR;
   } else if (region.ups == 0 && region.realtronix == 0 && region.hdx == 0) {
       state = STATE_UNACTIVE;
   } else if (region.ups == 0 && region.realtronix == 1 ) {
       state = STATE_WARNING_MIC_ON;
   } else if (region.ups == 0 || region.realtronix == 0 || region.hdx == 0) {
       state = STATE_WARNING;
   } else if (region.mic1 || region.mic2 || region.mic3 || region.mic4 || region.mic5 ||
              region.mic6 || region.mic7) {
       state = STATE_OK_MIC_ON;
   } else {
       state = STATE_OK;
   }
 
       region.state = state;
 
       regionProperties.replace(reg_num, region);
 
       QString stylesheet;
       QString icon;
 
       if (state == STATE_UNKNOWN)         {stylesheet = "QPushButton { background-color: #DDDCDB; }"; icon = "";}
       if (state == STATE_ERROR)           {stylesheet = "QPushButton { background-color: #FFBBBB; }"; icon = "";}
       if (state == STATE_WARNING)         {stylesheet = "QPushButton { background-color: #F4FB88; }"; icon = "";}
       if (state == STATE_OK)              {stylesheet = "QPushButton { background-color: #AEF3B6; }"; icon = "";}
       if (state == STATE_OK_MIC_ON)       {stylesheet = "QPushButton { background-color: #AEF3B6; }"; icon = "./img/micb.png";}
       if (state == STATE_UNACTIVE)        {stylesheet = "QPushButton { background-color: #4D639F; }"; icon = "";}
       if (state == STATE_WARNING_MIC_ON)  {stylesheet = "QPushButton { background-color: #F4FB88; }"; icon = "./img/micb.png";}
 
       switch (reg_num)
       {
...
           case 3: {
                     repyovka.setStyleSheet(stylesheet);
                     repyovka.setIcon(QIcon(icon));
                     break;
           }
           case 4: {
                     hohol.setStyleSheet(stylesheet);
                     hohol.setIcon(QIcon(icon));
                     break;
           }
           case 5: {
                     ostrogozhsk.setStyleSheet(stylesheet);
                     ostrogozhsk.setIcon(QIcon(icon));
                     break;
           }
...
       }
 
 
   if (mapDetail.isVisible() && reg_num == selectedRegionIndex) {
       mapDetail.updateStates(region.autoFocus,  region.cisco, region.ups,
                              region.realtronix, region.hdx,   region.mic1,
                              region.mic2,       region.mic3,  region.mic4,
                              region.mic5,       region.mic6,  region.mic7);
   }
 
 
Вся инициализация происходит в MainWindow::MainWindow где добавляются все маски (инициализация остальных 30 регионов опущена, она аналогична), затем запускается регулярный опрос оборудования (раз в 15 сек). который при необходимости вызывает updateRegionState. Ввиду того что контролируемых устройств порядка 10 в каждом регионе и вызов updateRegionState происходит при изменении состояния любого из устройств любого региона, вызов этой функции может происходить достаточно часто.
Если есть необходимость могу выложить полные исходники, но они достаточно объемные, а вся суть обработки приведена здесь. Плюс к этому, если закомментировать setMask в MainWindow::MainWindow то тормоза исчезают.
Записан
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #4 : Октябрь 28, 2010, 12:21 »

Зачем вы используете стили для изменения цвета кнопки?
Чем вам QPalette не угодил?
Иконки не мешало бы закешировать, чтобы постоянно их не грузить.
Почему не пользуетесь лейаутами?! Изменится фонт или разрешение и все ваши лейблы с кнопками поедут к чёртовой маме...
« Последнее редактирование: Октябрь 28, 2010, 12:26 от GreatSnake » Записан

Qt 5.11/4.8.7 (X11/Win)
lighting
Гость
« Ответ #5 : Октябрь 28, 2010, 12:54 »

Зачем вы используете стили для изменения цвета кнопки?
Чем вам QPalette не угодил?
Иконки не мешало бы закешировать, чтобы постоянно их не грузить.
Почему не пользуетесь лейаутами?! Изменится фонт или разрешение и все ваши лейблы с кнопками поедут к чёртовой маме...
Стили используются так сказать исторически - весь интерфейс кастомизируется стилями, поэтому и в данном случае стиль используем. Попробую setPalette.
Записан
ufna
Гость
« Ответ #6 : Октябрь 28, 2010, 16:44 »

никогда, никогда на медленных компьютерах не грузите мелкие изображения пачками с диска! Это просто тормозища! Коммуникаторы, мобилки, старые компы и прочее. У них жеский диск и доступ к памяти - не такой быстрый как у современнх компов.

а уж тем более 30 с чем-то иконок подряд. Только из контейнера следует это делать.

ну и QSS - медленная штука опять же. Оно строится динамически, это на медленном железе требует времени, поэтому для мобилок отказался почти сразу.
Записан
lighting
Гость
« Ответ #7 : Октябрь 28, 2010, 20:51 »

а уж тем более 30 с чем-то иконок подряд. Только из контейнера следует это делать.
А можно про контейнер поподробнее?
Записан
ufna
Гость
« Ответ #8 : Октябрь 28, 2010, 21:01 »

нужно упаковать их в один файл, и уже из него считывать. Как это сделать - вопрос конкретной реализации. Я пакую все в через QDataStream, потом уже считываю.
Записан
lighting
Гость
« Ответ #9 : Ноябрь 09, 2010, 09:59 »

как я и предполагал все тормоза были связаны с setMask - как только заменил их на прямоугольные кнопки все сразу залетало, и загрузка большого количества картинок без контейнера заметного тормозящего эффекта не оказала.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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