Discussão do artigo "Interfaces gráficas X: Ordenação, reconstrução da tabela e controles nas células (build 11)" - página 7

 
Anatoli Kazharski:
Devo ter inserido o exemplo errado no artigo. De qualquer forma, corrija-o para suas tarefas, conforme sua necessidade.

Não estou copiando seu código, estou interessado no trabalho do método SetImages em si. É necessário colocar imagens em cada célula se você as usar em qualquer coluna da tabela, ou é um erro em seu exemplo e você deve inseri-las apenas onde as usa?
 
Konstantin:

Não estou copiando seu código, estou interessado no trabalho do método SetImages em si. É necessário colocar as imagens em cada célula se você as usar em qualquer coluna da tabela ou isso é um erro no seu exemplo e você só deve inseri-las onde as usar?

Pelo que entendi, você precisa inserir imagens somente nas células da primeira coluna.

Tente fazer o seguinte:

//+------------------------------------------------------------------+
//| Inicialização da tabela|
//+------------------------------------------------------------------+
void CMainPanel::InitializingTable(void)
  {
//--- Matriz de nomes de cabeçalho
   string text_headers[COLUMNS1_TOTAL]={"Symbol","Bid","Ask","!","Time"};
//--- Matriz de caracteres
   string text_str = "MFON SBER SBERP GAZP TATN LKOH ROSN NVTK SNGS SNGSP VTBR MOEX AFKS IRAO "
                     "AFLT FEES ALRS MAGN NLMK CHMF GMKN HYDR TATNP YNDX RTKM MGNT MTSS";
   string text_array[];
   int _size = CreateArray(text_str, text_array); 
//--- Matriz de imagens
   string image_array[3]=
     {
      "::Images\\EasyAndFastGUI\\Icons\\bmp16\\circle_gray.bmp",
      "::Images\\EasyAndFastGUI\\Icons\\bmp16\\arrow_up.bmp",
      "::Images\\EasyAndFastGUI\\Icons\\bmp16\\arrow_down.bmp"
     };
//---
   for(int c=0; c<COLUMNS1_TOTAL; c++)
     {
      //--- Definir os nomes dos cabeçalhos
      m_canvas_table.SetHeaderText(c,text_headers[c]);
      //---
      for(int r=0; r<ROWS1_TOTAL; r++)
        {
         //--- Definir imagens e nomes de caracteres na primeira coluna
         if(c<1)
            {
             m_canvas_table.SetImages(c,r,image_array);
             m_canvas_table.SetValue(c,r,text_array[r]);
            }
         //--- Em todas as outras colunas, para todas as células, o valor padrão e sem figuras
         else
            m_canvas_table.SetValue(c,r,"-");
        }
     }
  }
 
Anatoli Kazharski:

Pelo que entendi, você precisa inserir imagens somente nas células da primeira coluna.

Tente isso:


)))))) então ainda é um erro de digitação no método? foi assim que fiz.

E qual é a melhor maneira de otimizar a carga sobre as capacidades calculadas. Há dados que são contados uma vez por período (por exemplo, M5), os dados são exibidos em uma tabela do OnTimer. Não é garantido que o tamanho das linhas em cada recálculo seja igual ao do último cálculo. Até o momento, vejo duas opções:
1. Após cada recálculo, excluir todas as linhas e criar o número necessário de linhas. Entre os recálculos, os dados são simplesmente atualizados.

2. Após cada recálculo, atualizamos os dados nas linhas existentes da tabela; se não houver linhas suficientes, adicionamos novas linhas; se houver mais linhas do que dados, excluímos as que não são necessárias.

Qual dessas opções é mais aceitável para uma tabela baseada em CCanvasTable?

 
Konstantin:

...

Qual dessas opções é mais aceitável para uma tabela baseada em CCanvasTable?

Não poderei responder a isso imediatamente. Tente fazer testes com medições de tempo(GetTickCount() ou GetMicrosecondCount()) ou teste no modo de criação de perfil.
 
Anatoli Kazharski:
Não poderei lhe dar uma resposta imediata. Tente fazer testes com medições de tempo(GetTickCount() ou GetMicrosecondCount()) ou teste no modo de criação de perfil.
Por algum motivo, a imagem é inserida somente na coluna com índice 0, não é inserida em outras colunas.
 
Konstantin:
Por algum motivo, a imagem é inserida somente na coluna com índice 0, em outras colunas ela não é colocada.

E que resultado você deseja obter? Descreva em detalhes.

E qual é o problema de fazer isso você mesmo? Todos os métodos necessários são fornecidos para isso.

P.S. Mostre capturas de tela e código para entender melhor o que você precisa.

 
Anatoli Kazharski:

E qual é o resultado que você deseja? Descreva-o em detalhes.

E qual é o problema de fazer isso você mesmo? Todos os métodos necessários são fornecidos para isso.

P.S. Mostre capturas de tela e código para entender melhor o que você precisa.


Se eu usar seu exemplo, mudarei o índice de 0 para 1:

void CProgram::UpdateTable(void)
  {
   MqlDateTime check_time;
   ::TimeToStruct(::TimeTradeServer(),check_time);
//--- Sair se for sábado ou domingo
   if(check_time.day_of_week==0 || check_time.day_of_week==6)
      return;
//---
   for(uint c=0; c < m_canvas_table.ColumnsTotal(); c++)
     {
      for(uint r=0; r < m_canvas_table.RowsTotal(); r++)
        {
         //--- Para qual caractere obtemos dados
         string symbol = m_canvas_table.GetValue(0, r);
         //--- Obter os dados dos dois últimos ticks
         MqlTick ticks[];
         if(::CopyTicks(symbol, ticks, COPY_TICKS_ALL, 0, 2) < 2)
            continue;
         //--- Definir a matriz como uma série temporal
         ::ArraySetAsSeries(ticks, true);
         //--- Coluna Symbol - Symbol. Vamos determinar a direção do preço.
         if(c==1)
           {
            int index=0;
            //--- Se os preços não foram alterados
            if(ticks[0].ask==ticks[1].ask && ticks[0].bid==ticks[1].bid)
               index=0;
            //--- Se o preço do lance tiver mudado para cima
            else if(ticks[0].bid>ticks[1].bid)
               index=1;
            //--- Se o preço do lance tiver mudado para baixo
            else if(ticks[0].bid<ticks[1].bid)
               index=2;
            //--- Definir a imagem correspondente
            m_canvas_table.ChangeImage(c,r,index,true);
           }
         else
           {
            //--- Coluna de diferença de preço - Spread (!)
            if(c==3)
              {
               //--- Obter e definir o tamanho do spread em pips
               int spread=(int)::SymbolInfoInteger(symbol,SYMBOL_SPREAD);
               m_canvas_table.SetValue(c,r,string(spread),true);
               continue;
              }
            //--- Obter o número de casas decimais
            int digit=(int)::SymbolInfoInteger(symbol,SYMBOL_DIGITS);
            //--- Coluna de preço Lance
            if(c==1)
              {
               m_canvas_table.SetValue(c,r,::DoubleToString(ticks[0].bid,digit));
               //--- Se o preço tiver mudado, defina a cor correspondente à direção
               if(ticks[0].bid!=ticks[1].bid)
                  m_canvas_table.TextColor(c,r,(ticks[0].bid<ticks[1].bid)? clrRed : clrBlue,true);
               //---
               continue;
              }
            //--- Coluna de preço de venda
            if(c==2)
              {
               m_canvas_table.SetValue(c,r,::DoubleToString(ticks[0].ask,digit));
               //--- Se o preço tiver mudado, defina a cor correspondente à direção
               if(ticks[0].ask!=ticks[1].ask)
                  m_canvas_table.TextColor(c,r,(ticks[0].ask<ticks[1].ask)? clrRed : clrBlue,true);
               //---
               continue;
              }
            //--- Coluna da última hora de chegada dos preços do símbolo
            if(c==4)
              {
               long   time     =::SymbolInfoInteger(symbol,SYMBOL_TIME);
               string time_msc =::IntegerToString(ticks[0].time_msc);
               int    length   =::StringLen(time_msc);
               string msc      =::StringSubstr(time_msc,length-3,3);
               string str      =::TimeToString(time,TIME_MINUTES|TIME_SECONDS)+"."+msc;
               //---
               color clr=clrBlack;
               //--- Se os preços não foram alterados
               if(ticks[0].ask==ticks[1].ask && ticks[0].bid==ticks[1].bid)
                  clr=clrBlack;
               //--- Se o preço do lance tiver mudado para cima
               else if(ticks[0].bid>ticks[1].bid)
                  clr=clrBlue;
               //--- Se o preço do lance tiver mudado para baixo
               else if(ticks[0].bid<ticks[1].bid)
                  clr=clrRed;
               //--- Definir o valor e a cor do texto
               m_canvas_table.SetValue(c,r,str);
               m_canvas_table.TextColor(c,r,clr,true);
               continue;
              }
           }
        }
     }

   int _height = int(m_chart.HeightInPixels(0) * .30);
   m_canvas_table.AutoYResizeBottomOffset(_height);

//--- Atualizar a tabela
   m_canvas_table.UpdateTable();
  }

os ícones deveriam ser movidos para a coluna com índice 1, ou seja, a segunda, mas isso não acontece. O exemplo foi extraído do arquivo TestLibrary10.mqh. Não encontrei nenhum método para posicionar as figuras. Se houver algum, por favor, me informe.

 
Em geral, não consigo entender o princípio de carregar imagens nas células da tabela. No exemplo TestLibrary09.mqh, os desenhos são carregados em colunas diferentes e, no exemplo TestLibrary10.mqh, somente na coluna com índice 0; quando definidos em outras colunas, os desenhos não são carregados. Você pode me dizer qual é a sutileza disso?
 
Konstantin:
Em geral, não consigo entender o princípio de carregar imagens nas células da tabela. No exemplo TestLibrary09.mqh, os desenhos são carregados em colunas diferentes e, no exemplo TestLibrary10.mqh, somente na coluna com índice 0; quando definidos em outras colunas, os desenhos não são carregados. Você pode me dizer qual é a sutileza disso?

Para cada célula da tabela, que deve conter figuras, você precisa de sua própria matriz de figuras. Se a célula for do tipo CELL_BUTTON, será suficiente um mínimo de uma imagem por célula; se for do tipo CELL_CHECKBOX, será necessário um mínimo de duas.

Por exemplo:

A imagem com índice 0 - corresponde ao estado "pressionado" da caixa de seleção (botão), os outros índices correspondem ao estado "selecionado" da caixa de seleção (botão).

(não está terminado, mas servirá para o entendimento):

Capturas de tela da plataforma de negociação MetaTrader

EURUSD, M1, 2017.04.21

MetaQuotes Software Corp., MetaTrader 4, Demonstração

EURUSD, M1, 2017.04.21, MetaQuotes Software Corp., MetaTrader 4, Demonstração

Há apenas uma coluna na tabela da direita com a lista de símbolos, e ela é do tipo CELL_CHECKBOX - ela requer um tamanho de matriz de imagem de pelo menos 2:
arr_chk[2]; arr_chk[0]=m_img_chk_off; (imagem de uma caixa de seleção com a caixa de seleção desmarcada) arr_chk[1]=m_img_chk_on; (imagem de uma caixa de seleção com a caixa de seleção marcada)


Na tabela principal:

A célula 0 contém a imagem de abertura do gráfico - ela tem o tipo CELL_BUTTON, você pode ter uma matriz de imagens com dimensão 1: arr_img0[1]; arr_img0[0]=m_image_graph;

A célula 8 contém a figura de abertura Comprar - seu tipo é CELL_BUTTON, a matriz de imagens pode ter dimensão 1: arr_img8[1]; arr_img8[0]=m_image_buy;

A célula 9 contém a imagem de abertura da venda - seu tipo é CELL_BUTTON, a matriz de imagens pode ser de dimensão 1: arr_img9[1]; arr_img9[0]=m_image_sell;

Depois de criar a tabela, você pode inicializá-la com os valores necessários, definir os tipos de células necessários e definir suas próprias matrizes de imagens para elas.


 
Artyom Trishkin:

Para cada célula da tabela, que deve conter imagens, você precisa de sua própria matriz de imagens. Se a célula for do tipo CELL_BUTTON, será suficiente um mínimo de uma imagem por célula; se o tipo for CELL_CHECKBOX, será suficiente um mínimo de duas. A imagem com índice 0 corresponde ao estado "pressionado" da caixa de seleção (botão), e os outros índices correspondem ao estado "selecionado" da caixa de seleção (botão).

Por exemplo (não está terminado, mas serve para entender):

Na tabela da direita com a lista de símbolos, há apenas uma coluna, e ela é do tipo CELL_CHECKBOX - ela exige um tamanho de matriz de imagem de pelo menos 2:
arr_chk[2]; arr_chk[0]=m_img_chk0; arr_chk[1]=m_img_chk1;


Na tabela principal:

A célula 0 contém a imagem de abertura do gráfico - ela tem o tipo CELL_BUTTON, você pode ter uma matriz de imagens com dimensão 1: arr_img0[1]; arr_img0[0]=m_image_graph;

A célula 8 contém a imagem de abertura Comprar - seu tipo é CELL_BUTTON, a matriz de imagem pode ter dimensão 1: arr_img8[1]; arr_img8[0]=m_image_buy;

A célula 9 contém a imagem de abertura da venda - ela tem o tipo CELL_BUTTON, a matriz de imagens pode ser de dimensão 1: arr_img9[1]; arr_img9[0]=m_image_sell;

Depois que a tabela for criada, você poderá inicializá-la com os valores desejados, definir os tipos de células desejados e definir suas matrizes de imagens para elas.


Eu realmente não entendo qual é o problema. )) Na primeira tela, ao mudar para a coluna com índice 1, as imagens desapareceram e, na segunda tela, ao voltar para a coluna com índice 0, as imagens apareceram. Isso tudo está no código de exemplo TestLibrary10. mqh

Aqui estão os métodos de criação da tabela:

bool CProgram::CreateCanvasTable(const int x_gap,const int y_gap)
  {
#define  COLUMNS1_TOTAL 5
#define  ROWS1_TOTAL    27
//--- Salvar o ponteiro no formulário
   m_canvas_table.WindowPointer(m_window);
//--- Matriz de larguras de coluna
   int width[COLUMNS1_TOTAL]={75, 60, 60, 60, 75};
//--- Matriz de recuo de texto em colunas no eixo X
   int text_x_offset[COLUMNS1_TOTAL];
   ::ArrayInitialize(text_x_offset,5);
   text_x_offset[0]=25;
//--- Matriz de alinhamento de texto em colunas
   ENUM_ALIGN_MODE align[COLUMNS1_TOTAL];
   ::ArrayInitialize(align,ALIGN_RIGHT);
   align[0]=ALIGN_LEFT;
//--- Definir propriedades antes da criação
   m_canvas_table.XSize(345);
   m_canvas_table.YSize(289);
   m_canvas_table.TableSize(COLUMNS1_TOTAL, ROWS1_TOTAL);
   m_canvas_table.TextAlign(align);
   m_canvas_table.TextXOffset(text_x_offset);
   m_canvas_table.ColumnsWidth(width);
   m_canvas_table.TextXOffset(5);
   m_canvas_table.TextYOffset(4);
   m_canvas_table.CellYSize(20);
   //m_canvas_table.ImageXOffset(8);//
   //m_canvas_table.ImageYOffset(6);//
   m_canvas_table.ShowHeaders(true);
   m_canvas_table.HeaderYSize(30);
   m_canvas_table.HeadersColor(C'255,244,213');
   m_canvas_table.CellColorHover(C'255,244,213');
   m_canvas_table.LightsHover(true);
   m_canvas_table.SelectableRow(true);
   m_canvas_table.ColumnResizeMode(true);
   m_canvas_table.IsZebraFormatRows(clrWhiteSmoke);
   //m_canvas_table.AutoXResizeMode(true);
   m_canvas_table.AutoXResizeRightOffset(1);
   m_canvas_table.AutoYResizeMode(true);
   int _height = int(m_chart.HeightInPixels(0) * .30);
   m_canvas_table.AutoYResizeBottomOffset(/*25 + */_height);
//--- Preencher a tabela com dados
   InitializingTable();
//--- Criar um controle
   if(!m_canvas_table.CreateTable(m_chart_id,m_subwin,x_gap,y_gap))
      return(false);
//--- Adicione o objeto à matriz comum de grupos de objetos
   CWndContainer::AddToElementsArray(0,m_canvas_table);
   return(true);
  }

é a inicialização:

void CProgram::InitializingTable(void)
  {
//--- Matriz de nomes de cabeçalho
   string text_headers[COLUMNS1_TOTAL]={"Symbol","Bid","Ask","!","Time"};
//--- Matriz de caracteres
   //string text_array[25]=
   // {
   // "AUDUSD", "GBPUSD", "EURUSD", "USDCAD", "USDCHF", "USDJPY", "NZDUSD", "USDSEK", "USDHKD", "USDMXN",
   // "USDZAR", "USDTRY", "GBPAUD", "AUDCAD", "CADCHF", "EURAUD", "GBPCHF", "GBPJPY", "NZDJPY", "AUDJPY",
   // "EURJPY", "EURCHF", "EURGBP", "AUDCHF", "CHFJPY"
   // };
   string text_str = "MFON SBER SBERP GAZP TATN LKOH ROSN NVTK SNGS SNGSP VTBR MOEX AFKS IRAO "
                     "AFLT FEES ALRS MAGN NLMK CHMF GMKN HYDR TATNP YNDX RTKM MGNT MTSS";
   string text_array[];
   int _size = CreateArray(text_str, text_array); 
//--- Matriz de imagens
   string image_array[3]=
     {
      "::Images\\EasyAndFastGUI\\Icons\\bmp16\\circle_gray.bmp",//circle_gray_t32.bmp",
      "::Images\\EasyAndFastGUI\\Icons\\bmp16\\arrow_up.bmp",
      "::Images\\EasyAndFastGUI\\Icons\\bmp16\\arrow_down.bmp"
     };
//---
   for(int c=0; c<COLUMNS1_TOTAL; c++)
     {
      //--- Definir os nomes dos cabeçalhos
      m_canvas_table.SetHeaderText(c,text_headers[c]);
      //---
      for(int r=0; r<ROWS1_TOTAL; r++)
        {
         //--- Definir as imagens
         if(c == 1) {
            m_canvas_table.CellType(c, r, CELL_BUTTON);
            m_canvas_table.SetImages(c,r,image_array);
         }
         //--- Definir nomes de caracteres
         if(c<1)
            m_canvas_table.SetValue(c,r,text_array[r]);
         //--- Valor padrão para todas as células
         else
            m_canvas_table.SetValue(c,r,"-");
        }
     }
  }

é a atualização:

void CProgram::UpdateTable(void)
  {
   MqlDateTime check_time;
   ::TimeToStruct(::TimeTradeServer(),check_time);
//--- Sair se for sábado ou domingo
   if(check_time.day_of_week==0 || check_time.day_of_week==6)
      return;
//---
   for(uint c=0; c < m_canvas_table.ColumnsTotal(); c++)
     {
      for(uint r=0; r < m_canvas_table.RowsTotal(); r++)
        {
         //--- Para qual caractere obtemos dados
         string symbol = m_canvas_table.GetValue(0, r);
         //--- Obter os dados dos dois últimos ticks
         MqlTick ticks[];
         if(::CopyTicks(symbol, ticks, COPY_TICKS_ALL, 0, 2) < 2)
            continue;
         //--- Definir a matriz como uma série temporal
         ::ArraySetAsSeries(ticks, true);
         //--- Coluna Symbol - Symbol. Vamos determinar a direção do preço.
         if(c==1)
           {
            int index=0;
            //--- Se os preços não foram alterados
            if(ticks[0].ask==ticks[1].ask && ticks[0].bid==ticks[1].bid)
               index=0;
            //--- Se o preço do lance tiver mudado para cima
            else if(ticks[0].bid > ticks[1].bid)
               index=1;
            //--- Se o preço do lance tiver mudado para baixo
            else if(ticks[0].bid < ticks[1].bid)
               index=2;
            //--- Definir a imagem correspondente
            m_canvas_table.ChangeImage(c,r,index,true);
           }
         else
           {
            //--- Coluna de diferença de preço - Spread (!)
            if(c==3)
              {
               //--- Obter e definir o tamanho do spread em pips
               int spread=(int)::SymbolInfoInteger(symbol,SYMBOL_SPREAD);
               m_canvas_table.SetValue(c,r,string(spread),true);
               continue;
              }
            //--- Obter o número de casas decimais
            int digit=(int)::SymbolInfoInteger(symbol,SYMBOL_DIGITS);
            //--- Coluna de preço Lance
            if(c==1)
              {
               m_canvas_table.SetValue(c,r,::DoubleToString(ticks[0].bid,digit));
               //--- Se o preço tiver mudado, defina a cor correspondente à direção
               if(ticks[0].bid!=ticks[1].bid)
                  m_canvas_table.TextColor(c,r,(ticks[0].bid<ticks[1].bid)? clrRed : clrBlue,true);
               //---
               continue;
              }
            //--- Coluna de preço de venda
            if(c==2)
              {
               m_canvas_table.SetValue(c,r,::DoubleToString(ticks[0].ask,digit));
               //--- Se o preço tiver mudado, defina a cor correspondente à direção
               if(ticks[0].ask!=ticks[1].ask)
                  m_canvas_table.TextColor(c,r,(ticks[0].ask<ticks[1].ask)? clrRed : clrBlue,true);
               //---
               continue;
              }
            //--- Coluna da última hora de chegada dos preços do símbolo
            if(c==4)
              {
               long   time     =::SymbolInfoInteger(symbol,SYMBOL_TIME);
               string time_msc =::IntegerToString(ticks[0].time_msc);
               int    length   =::StringLen(time_msc);
               string msc      =::StringSubstr(time_msc,length-3,3);
               string str      =::TimeToString(time,TIME_MINUTES|TIME_SECONDS)+"."+msc;
               //---
               color clr=clrBlack;
               //--- Se os preços não foram alterados
               if(ticks[0].ask==ticks[1].ask && ticks[0].bid==ticks[1].bid)
                  clr=clrBlack;
               //--- Se o preço do lance tiver mudado para cima
               else if(ticks[0].bid>ticks[1].bid)
                  clr=clrBlue;
               //--- Se o preço do lance tiver mudado para baixo
               else if(ticks[0].bid<ticks[1].bid)
                  clr=clrRed;
               //--- Definir o valor e a cor do texto
               m_canvas_table.SetValue(c,r,str);
               m_canvas_table.TextColor(c,r,clr,true);
               continue;
              }
           }
        }
     }

   int _height = int(m_chart.HeightInPixels(0) * .30);
   m_canvas_table.AutoYResizeBottomOffset(_height);

//--- Atualizar a tabela
   m_canvas_table.UpdateTable();
  }
destacado mudou de 0 para 1, ou seja, mudou a inserção da imagem na coluna do número 0 para o número 1, onde está o erro?
Arquivos anexados:
07.png  163 kb
00.png  161 kb