文章 "图形界面 X: 排序、重建表格和单元格中的控件 (集成编译 11)" - 页 7

 
Anatoli Kazharski:
我一定是在文章中插入了错误的示例。无论如何,请根据您的需要进行修改。

我不是在复制你的代码,我感兴趣的是SetImages 方法本身的工作原理,如果你在表格的任何一列中使用图片,是否有必要在每个单元格中都放入图片,还是你的示例有误,你只需要在使用图片的地方插入图片?
 
Konstantin:

我不是在复制您的代码,我感兴趣的是SetImages 方法本身的工作原理,如果您在表格的任何一列中使用图片,是否有必要将图片放入每个单元格中,还是您的示例中出现了错误,您应该只在使用图片的地方插入图片?

据我所知,您只需要在第一列的单元格中插入图片。

试着这样做

//+------------------------------------------------------------------+
// | 初始化表格|
//+------------------------------------------------------------------+
void CMainPanel::InitializingTable(void)
  {
//-- 头文件名称数组
   string text_headers[COLUMNS1_TOTAL]={"Symbol","Bid","Ask","!","Time"};
//--- 字符数组
   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); 
//--- 图片数组
   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++)
     {
      //--- 设置标头名称
      m_canvas_table.SetHeaderText(c,text_headers[c]);
      //---
      for(int r=0; r<ROWS1_TOTAL; r++)
        {
         //--- 在第一栏中设置图片和字符名称
         if(c<1)
            {
             m_canvas_table.SetImages(c,r,image_array);
             m_canvas_table.SetValue(c,r,text_array[r]);
            }
         //--- 在所有其他列中,所有单元格均为默认值且不带图片
         else
            m_canvas_table.SetValue(c,r,"-");
        }
     }
  }
 
Anatoli Kazharski:

据我所知,您只需要在第一列的单元格中插入图片。

试试这个:


)))))) 所以还是方法有误?我就是这么做的。

优化计算容量负载的最佳方法是什么?有些数据每隔一段时间计算一次(例如 M5),这些数据显示在 OnTimer 的表格中。每次重新计算时的行大小不能保证与上次计算的行大小相等。目前有两种选择:
1.每次重新计算后删除所有行并创建必要数量的行。在两次重新计算之间,只需更新数据即可。

2.每次重新计算后,更新表格现有行中的数据,如果行数不够,则添加新行,如果行数多于数据,则删除不需要的行。

对于基于CCanvasTable 的表格来说,哪种方案更容易接受?

 
Konstantin:

...

对于基于 CCanvasTable 的表格来说,哪一个选项更容易接受?

我无法立即回答这个问题。请尝试使用时间测量(GetTickCount()GetMicrosecondCount() 在剖析模式下 进行测试。
 
Anatoli Kazharski:
我无法立即给出答案。请尝试使用时间测量(GetTickCount()GetMicrosecondCount() 进行测试,或在剖析模式下 进行测试。
由于某些原因,图片只插入到索引为 0 的列中,而没有插入到其他列中,这是一种特殊情况还是出了什么问题?
 
Konstantin:
出于某种原因,图片只插入到索引为 0 的列中,其他列没有插入,这是一种特殊情况还是出了什么问题?

您希望得到什么结果?请详细说明。

自己操作有什么问题?我们提供了所有必要的方法。

附: 请展示截图和代码,以便更好地理解您的需求。

 
Anatoli Kazharski:

你想要什么结果?请详细描述。

自己做有什么问题?我们将为此提供所有必要的方法。

另外,请 显示截图和代码,以便更好地理解您的需求。


如果使用您的示例,我将索引从 0 改为 1

void CProgram::UpdateTable(void)
  {
   MqlDateTime check_time;
   ::TimeToStruct(::TimeTradeServer(),check_time);
//--- 如果是周六或周日,则退出
   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++)
        {
         //--- 我们为哪个字符获取数据
         string symbol = m_canvas_table.GetValue(0, r);
         //--- 获取最后两个刻度的数据
         MqlTick ticks[];
         if(::CopyTicks(symbol, ticks, COPY_TICKS_ALL, 0, 2) < 2)
            continue;
         //--- 将数组设置为时间序列
         ::ArraySetAsSeries(ticks, true);
         //--- 符号列 - 符号。让我们来确定价格方向。
         if(c==1)
           {
            int index=0;
            //--- 如果价格没有变化
            if(ticks[0].ask==ticks[1].ask && ticks[0].bid==ticks[1].bid)
               index=0;
            //--- 如果出价向上变动
            else if(ticks[0].bid>ticks[1].bid)
               index=1;
            //--- 如果出价向下变动
            else if(ticks[0].bid<ticks[1].bid)
               index=2;
            //--- 设置相应的图片
            m_canvas_table.ChangeImage(c,r,index,true);
           }
         else
           {
            //--- 价差栏 - 价差 (!)
            if(c==3)
              {
               //--- 以点为单位获取和设置点差大小
               int spread=(int)::SymbolInfoInteger(symbol,SYMBOL_SPREAD);
               m_canvas_table.SetValue(c,r,string(spread),true);
               continue;
              }
            //--- 获得小数位数
            int digit=(int)::SymbolInfoInteger(symbol,SYMBOL_DIGITS);
            //--- 价格栏 投标
            if(c==1)
              {
               m_canvas_table.SetValue(c,r,::DoubleToString(ticks[0].bid,digit));
               //--- 如果价格发生变化,则设置与方向相对应的颜色
               if(ticks[0].bid!=ticks[1].bid)
                  m_canvas_table.TextColor(c,r,(ticks[0].bid<ticks[1].bid)? clrRed : clrBlue,true);
               //---
               continue;
              }
            //--- 售价栏
            if(c==2)
              {
               m_canvas_table.SetValue(c,r,::DoubleToString(ticks[0].ask,digit));
               //--- 如果价格发生变化,则设置与方向相对应的颜色
               if(ticks[0].ask!=ticks[1].ask)
                  m_canvas_table.TextColor(c,r,(ticks[0].ask<ticks[1].ask)? clrRed : clrBlue,true);
               //---
               continue;
              }
            //--- 符号价格最后到达时间列
            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;
               //--- 如果价格没有变化
               if(ticks[0].ask==ticks[1].ask && ticks[0].bid==ticks[1].bid)
                  clr=clrBlack;
               //--- 如果出价向上变动
               else if(ticks[0].bid>ticks[1].bid)
                  clr=clrBlue;
               //--- 如果出价向下变动
               else if(ticks[0].bid<ticks[1].bid)
                  clr=clrRed;
               //--- 设置文本的值和颜色
               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);

//-- 更新表格
   m_canvas_table.UpdateTable();
  }

图标应该移动到索引为 1 的列,即第二列,但这并没有发生。该示例来自TestLibrary10.mqh。我没有找到任何定位数字的方法,如果有,请告诉我。

 
总的来说,我无法理解将图片加载到表格单元格 中的原理。在TestLibrary09.mqh 示例中,图片被加载到不同的列中,而在TestLibrary10.mqh 示例中,图片只被加载到索引为 0 的列中,当设置到其他列时,图片不会被加载。您能告诉我其中的奥妙吗?
 
Konstantin:
总的来说,我无法理解将图片加载到表格单元格中的原理。在TestLibrary09.mqh 示例中,图片被加载到不同的列中,而在TestLibrary10.mqh 示例中,图片只被加载到索引为 0 的列中,当设置到其他列时,图片不会被加载。您能告诉我其中的奥妙吗?

表格的每个单元格都应包含图片,您需要有自己的图片数组。如果单元格的类型为 CELL_BUTTON,则每个单元格至少需要一张图片即可;如果类型为 CELL_CHECKBOX,则至少需要两张图片。

例如

索引为 0 的图片对应复选框(按钮)的 "按下 "状态,其他索引对应复选框(按钮)的 "选中 "状态。

(未完成,但可用于理解):

MetaTrader 交易平台截图

EURUSD, M1, 2017.04.21

MetaQuotes Software Corp., MetaTrader 4, 演示版

欧元兑美元, M1, 2017.04.21, MetaQuotes Software Corp., MetaTrader 4, 演示版

右表中只有一列符号列表,其类型为 CELL_CHECKBOX--它要求图像数组大小至少为 2:
arr_chk[2]; arr_chk[0]=m_img_chk_off; (未选中复选框的复选框图像) arr_chk[1]=m_img_chk_on; (选中复选框的复选框图像)


在主表中:

单元格 0 包含图表开头图片 - 其类型为 CELL_BUTTON,您可以使用维数为 1 的图片数组:arr_img0[1]; arr_img0[0]=m_image_graph;

单元格 8 包含 "买 "开头的图片 - 其类型为 CELL_BUTTON,图片数组的维数可以是 1: arr_img8[1]; arr_img8[0]=m_image_buy;

单元格 9 包含卖方开盘图片 - 其类型为 CELL_BUTTON,图片数组的维数可以是 1: arr_img9[1]; arr_img9[0]=m_image_sell;

创建表格后,您可以用所需值对其进行初始化,设置所需的单元格类型,并为它们设置自己的图像数组。


 
Artyom Trishkin:

表格的每个单元格都应包含图片,因此需要有自己的图片数组。如果单元格的类型是 CELL_BUTTON,那么每个单元格至少包含一张图片即可;如果单元格的类型是 CELL_CHECKBOX,那么每个单元格至少包含两张图片。索引为 0 的图片对应复选框(按钮)的 "按下 "状态,其他索引对应复选框(按钮)的 "选中 "状态。

举例说明(虽然没有完成,但可以帮助理解):

在右表的符号列表中,只有一列,其类型为 CELL_CHECKBOX--它要求图像数组的大小至少为 2:
arr_chk[2]; arr_chk[0]=m_img_chk0; arr_chk[1]=m_img_chk1;


在主表中:

单元格 0 包含图表开头图片 - 其类型为 CELL_BUTTON,您可以使用维数为 1 的图片数组: arr_img0[1]; arr_img0[0]=m_image_graph;

单元格 8 包含 "买 "开头的图片 - 其类型为 CELL_BUTTON,图片数组的维数可以是 1: arr_img8[1]; arr_img8[0]=m_image_buy;

单元格 9 包含卖方开盘图片 - 其类型为 CELL_BUTTON,图片数组的维数可以是 1: arr_img9[1]; arr_img9[0]=m_image_sell;

创建表格后,您可以使用所需的值对其进行初始化,设置所需的单元格类型,并为其设置图像数组。


我真的不明白问题出在哪里))在第一个屏幕中,换到索引为 1 的列时,图像消失了,而在第二个屏幕中,换回索引为 0 的列时,图像又出现了。这些都是示例代码TestLibrary10. mqh 中 的内容。

下面是创建表格的方法:

bool CProgram::CreateCanvasTable(const int x_gap,const int y_gap)
  {
#define  COLUMNS1_TOTAL 5
#define  ROWS1_TOTAL    27
//--- 保存指向表单的指针
   m_canvas_table.WindowPointer(m_window);
//-- 列宽数组
   int width[COLUMNS1_TOTAL]={75, 60, 60, 60, 75};
//--- X 轴各栏文字缩进数组
   int text_x_offset[COLUMNS1_TOTAL];
   ::ArrayInitialize(text_x_offset,5);
   text_x_offset[0]=25;
//-- 列中文本对齐方式数组
   ENUM_ALIGN_MODE align[COLUMNS1_TOTAL];
   ::ArrayInitialize(align,ALIGN_RIGHT);
   align[0]=ALIGN_LEFT;
//--- 创建前设置属性
   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);
//-- 将数据填入表格
   InitializingTable();
//--- 创建一个控件
   if(!m_canvas_table.CreateTable(m_chart_id,m_subwin,x_gap,y_gap))
      return(false);
//--- 将对象添加到对象组的通用数组中
   CWndContainer::AddToElementsArray(0,m_canvas_table);
   return(true);
  }

是初始化:

void CProgram::InitializingTable(void)
  {
//-- 头文件名称数组
   string text_headers[COLUMNS1_TOTAL]={"Symbol","Bid","Ask","!","Time"};
//--- 字符数组
   //字符串 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); 
//--- 图片数组
   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++)
     {
      //--- 设置标头名称
      m_canvas_table.SetHeaderText(c,text_headers[c]);
      //---
      for(int r=0; r<ROWS1_TOTAL; r++)
        {
         //--- 设置图片
         if(c == 1) {
            m_canvas_table.CellType(c, r, CELL_BUTTON);
            m_canvas_table.SetImages(c,r,image_array);
         }
         //--- 设置字符名称
         if(c<1)
            m_canvas_table.SetValue(c,r,text_array[r]);
         //-- 所有单元格的默认值
         else
            m_canvas_table.SetValue(c,r,"-");
        }
     }
  }

这是更新:

void CProgram::UpdateTable(void)
  {
   MqlDateTime check_time;
   ::TimeToStruct(::TimeTradeServer(),check_time);
//--- 如果是周六或周日,则退出
   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++)
        {
         //--- 我们为哪个字符获取数据
         string symbol = m_canvas_table.GetValue(0, r);
         //--- 获取最后两个刻度的数据
         MqlTick ticks[];
         if(::CopyTicks(symbol, ticks, COPY_TICKS_ALL, 0, 2) < 2)
            continue;
         //--- 将数组设置为时间序列
         ::ArraySetAsSeries(ticks, true);
         //--- 符号列 - 符号。让我们来确定价格方向。
         if(c==1)
           {
            int index=0;
            //--- 如果价格没有变化
            if(ticks[0].ask==ticks[1].ask && ticks[0].bid==ticks[1].bid)
               index=0;
            //--- 如果出价向上变动
            else if(ticks[0].bid > ticks[1].bid)
               index=1;
            //--- 如果出价向下变动
            else if(ticks[0].bid < ticks[1].bid)
               index=2;
            //--- 设置相应的图片
            m_canvas_table.ChangeImage(c,r,index,true);
           }
         else
           {
            //--- 价差栏 - 价差 (!)
            if(c==3)
              {
               //--- 以点为单位获取和设置点差大小
               int spread=(int)::SymbolInfoInteger(symbol,SYMBOL_SPREAD);
               m_canvas_table.SetValue(c,r,string(spread),true);
               continue;
              }
            //--- 获取小数位数
            int digit=(int)::SymbolInfoInteger(symbol,SYMBOL_DIGITS);
            //--- 价格栏 投标
            if(c==1)
              {
               m_canvas_table.SetValue(c,r,::DoubleToString(ticks[0].bid,digit));
               //--- 如果价格发生变化,则设置与方向相对应的颜色
               if(ticks[0].bid!=ticks[1].bid)
                  m_canvas_table.TextColor(c,r,(ticks[0].bid<ticks[1].bid)? clrRed : clrBlue,true);
               //---
               continue;
              }
            //--- 售价栏
            if(c==2)
              {
               m_canvas_table.SetValue(c,r,::DoubleToString(ticks[0].ask,digit));
               //--- 如果价格发生变化,则设置与方向相对应的颜色
               if(ticks[0].ask!=ticks[1].ask)
                  m_canvas_table.TextColor(c,r,(ticks[0].ask<ticks[1].ask)? clrRed : clrBlue,true);
               //---
               continue;
              }
            //--- 符号价格最后到达时间列
            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;
               //--- 如果价格没有变化
               if(ticks[0].ask==ticks[1].ask && ticks[0].bid==ticks[1].bid)
                  clr=clrBlack;
               //--- 如果出价向上变动
               else if(ticks[0].bid>ticks[1].bid)
                  clr=clrBlue;
               //--- 如果出价向下变动
               else if(ticks[0].bid<ticks[1].bid)
                  clr=clrRed;
               //--- 设置文本的值和颜色
               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);

//-- 更新表格
   m_canvas_table.UpdateTable();
  }
突出显示从 0 变为 1,即列中插入的图片 从 0 变为 1,这里的错误出在哪里?
附加的文件:
07.png  163 kb
00.png  161 kb