Russian Qt Forum

Qt => Пользовательский интерфейс (GUI) => Тема начата: lighting от Октябрь 28, 2010, 10:04



Название: setMask и тормоза.
Отправлено: 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


Название: Re: setMask и тормоза.
Отправлено: GreatSnake от Октябрь 28, 2010, 10:30
Давай код.
Да и в чём необходимость использования стилей, тем более динамически?


Название: Re: setMask и тормоза.
Отправлено: pastor от Октябрь 28, 2010, 11:31
Да, лучше взглянуть на код.


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


Название: Re: setMask и тормоза.
Отправлено: lighting от Октябрь 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 то тормоза исчезают.


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


Название: Re: setMask и тормоза.
Отправлено: lighting от Октябрь 28, 2010, 12:54
Зачем вы используете стили для изменения цвета кнопки?
Чем вам QPalette не угодил?
Иконки не мешало бы закешировать, чтобы постоянно их не грузить.
Почему не пользуетесь лейаутами?! Изменится фонт или разрешение и все ваши лейблы с кнопками поедут к чёртовой маме...
Стили используются так сказать исторически - весь интерфейс кастомизируется стилями, поэтому и в данном случае стиль используем. Попробую setPalette.


Название: Re: setMask и тормоза.
Отправлено: ufna от Октябрь 28, 2010, 16:44
никогда, никогда на медленных компьютерах не грузите мелкие изображения пачками с диска! Это просто тормозища! Коммуникаторы, мобилки, старые компы и прочее. У них жеский диск и доступ к памяти - не такой быстрый как у современнх компов.

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

ну и QSS - медленная штука опять же. Оно строится динамически, это на медленном железе требует времени, поэтому для мобилок отказался почти сразу.


Название: Re: setMask и тормоза.
Отправлено: lighting от Октябрь 28, 2010, 20:51
а уж тем более 30 с чем-то иконок подряд. Только из контейнера следует это делать.
А можно про контейнер поподробнее?


Название: Re: setMask и тормоза.
Отправлено: ufna от Октябрь 28, 2010, 21:01
нужно упаковать их в один файл, и уже из него считывать. Как это сделать - вопрос конкретной реализации. Я пакую все в через QDataStream, потом уже считываю.


Название: Re: setMask и тормоза.
Отправлено: lighting от Ноябрь 09, 2010, 09:59
как я и предполагал все тормоза были связаны с setMask - как только заменил их на прямоугольные кнопки все сразу залетало, и загрузка большого количества картинок без контейнера заметного тормозящего эффекта не оказала.