我在 Gtk::TreeView 中的自定义列不起作用

my custom column in a Gtk::TreeView doesn't work

我有一个 Gtk::TreeView,我在其中添加了一个模型和一个自定义列:

examplewindow.hh :

#ifndef GTKMM_EXAMPLEWINDOW_H
#define GTKMM_EXAMPLEWINDOW_H

#include <gtkmm.h>

class ExampleWindow
: public Gtk::Window
{
  public:
  ExampleWindow(void);
  virtual ~ExampleWindow(void);

  //My column
  class foocol
  : public Gtk::TreeView::Column
  {
    public:
    Gtk::CellRendererToggle fooRenderer;
    bool test;
    foocol(void);
    ~foocol(void);
    foocol(const foocol&);
    foocol &operator=(const foocol&);

    private:
    //signal
    void foocolData(Gtk::CellRenderer*,const Gtk::TreeModel::iterator&);
    void foocolToggled(const Glib::ustring&);
  };

  //Tree model columns:
  class ModelColumns : public Gtk::TreeModel::ColumnRecord
  {
    public:
    ModelColumns(void){ add(m_col_id); add(m_col_name); }

    Gtk::TreeModelColumn<unsigned int> m_col_id;
    Gtk::TreeModelColumn<Glib::ustring> m_col_name;
    Gtk::TreeModelColumn<ExampleWindow::foocol> m_col_foocol;
  };

  foocol m_foocol; // XXX
  ModelColumns m_Columns;

  //Child widgets:
  Gtk::TreeView m_TreeView;
  Glib::RefPtr<Gtk::ListStore> m_refTreeModel;
};

#endif //GTKMM_EXAMPLEWINDOW_H

examplewindow.cc :

#include <iostream>
#include "examplewindow.hh"

#define CB_FUNCTION(X) sigc::mem_fun( this, &ExampleWindow::foocol::X )
#define CONNECT(X) connect( sigc::mem_fun( this,\
                                          &ExampleWindow::foocol::X ) );

ExampleWindow::ExampleWindow()
{
  set_title("List of singers");
  set_border_width(5);
  set_default_size(400, 200);

  //Add the TreeView, inside the window
  add(m_TreeView);

  //Create the Tree model:
  m_refTreeModel = Gtk::ListStore::create(m_Columns);
  m_TreeView.set_model(m_refTreeModel);

  //Fill the TreeView's model
  Gtk::TreeModel::Row row = *(m_refTreeModel->append());
  row[m_Columns.m_col_id] = 1;
  row[m_Columns.m_col_name] = "Marilyn Manson";


  row = *(m_refTreeModel->append());
  row[m_Columns.m_col_id] = 2;
  row[m_Columns.m_col_name] = "David Vincent";


  row = *(m_refTreeModel->append());
  row[m_Columns.m_col_id] = 3;
  row[m_Columns.m_col_name] = "Yolandi Visser";


  //Add the TreeView's view columns:
  //This number will be shown with the default numeric formatting.
  m_TreeView.append_column( "ID", m_Columns.m_col_id );
  m_TreeView.append_column( "Name", m_Columns.m_col_name );
  m_TreeView.append_column( "model.m_col_foocol", m_Columns.m_col_foocol );
  m_TreeView.append_column( m_foocol ); // XXX

  show_all_children();

}

ExampleWindow::~ExampleWindow()
{

}


ExampleWindow::foocol::foocol(  )
{ 
  std::cout << "foocol constructor " << this << "\n";
  this->set_title( "foocol" );
  this->pack_start( fooRenderer );

  //Tell the view column how to render the model values
  this->set_cell_data_func( fooRenderer, CB_FUNCTION( foocolData ) );


  fooRenderer.property_sensitive() = true; // done by default
  fooRenderer.signal_toggled().CONNECT( foocolToggled );

}

ExampleWindow::foocol::~foocol(  )
{
  std::cout << "foocol destructor " << this << "\n"; 
}

ExampleWindow::foocol::foocol( const ExampleWindow::foocol& copyMe )
: test(copyMe.test)
{ 
  std::cout << "foocol copy constructor " << this << "\n";
}

ExampleWindow::foocol&
ExampleWindow::foocol::operator=( const ExampleWindow::foocol& copyMe )
{
  std::cout << "assignement " << this << " = " << &copyMe << "\n";

  return *this;
}

                   /********* SIGNALS ******/

void
ExampleWindow::foocol::foocolData( Gtk::CellRenderer* renderer
                                 , const Gtk::TreeModel::iterator& 
                                                                  iter )
{
  std::cout << "foocolData " << this << "\n";
}

void
ExampleWindow::foocol::foocolToggled( const Glib::ustring& path )
{
  std::cout << "foocolToggled " << this << "\n";
}

main.cc :

#include <iostream>
#include "examplewindow.hh"
#include <gtkmm/application.h>

int main( int argc
        , char *argv[] )
{
  Glib::RefPtr<Gtk::Application> app 
            = Gtk::Application::create( argc, argv
                                                , "org.gtkmm.example" );

  ExampleWindow window;

  //Shows the window and returns when it is closed.
  return app->run( window );
}

在 linux 上编译:

g++ examplewindow.cc main.cc `pkg-config gtkmm-3.0 --cflags --libs` -std=c++11

在 windows 上编译:

我不是种族主义者,我只是不知道如何在 windows 上编译。

截图:

问题:

好的,正如您所看到的,我花了一些时间来为我的问题举一个很好的例子。在屏幕截图上,您可以看到一个名为 foocol 的列,您可以在其中看到一个切换按钮,在左侧,您可以看到一个名为 model.mcolfoocol.

的列

第二列是我的问题所在,我根本看不到切换。我不知道为什么,我花了好几个小时都没能解决这个问题...

两列相同,不同的结果来自作为列添加的一列,而第二列(不起作用的列)是通过 Gtk::TreeModel::ColumnRecord 添加的。当然要用第二种方法了...

最好在我添加 // XXX 的行添加注释,这样控制台中的所有消息都会与问题相关。

可能的输出:

foocol constructor 0xbfda6e70

(a.out:12545): Gtk-CRITICAL **: gtk_cell_layout_add_attribute: assertion 'column >= 0' failed
foocolData 0xbfda6e70
foocolData 0xbfda6e70
foocolData 0xbfda6e70
foocolData 0xbfda6e70
foocolData 0xbfda6e70
foocolData 0xbfda6e70
foocolData 0xbfda6e70
foocolData 0xbfda6e70
foocolData 0xbfda6e70
foocol destructor 0xbfda6e70

不幸的是,我不知道如何调试使用多个库的程序。我什至不确定我的计算机是否有足够的内存来执行此操作...


真心觉得gtkmm这部分不直观...

您可能不想使用 ExampleWindow::foocal 作为模型支持类型(在 Gtk::TreeModelColumn m_col_foocol; 中);您正在混合使用 TreeModel 和 TreeView 类型。

我不确定您的意图(您为什么不只使用 TreeModelColumn,它会自动呈现一个复选框)。 下面我强制您的专栏注册 Model 的 ColumnRecord,并注册 View,并显示(并生成切换事件,但未正确切换);注意我需要改变它的类型;希望这会帮助您朝着理想的方向前进。 我已经注释掉标有 // XXX 的行,并且还修改了:

  • examplewindow.h 变化

       //My column
       class foocol
    -  : public Gtk::TreeView::Column
    +  : public Gtk::TreeView::Column, public Gtk::TreeModelColumn<bool>
       {
    ...
    -    ModelColumns(void){ add(m_col_id); add(m_col_name); }
    +    ModelColumns(void){ add(m_col_id); add(m_col_name); add (m_col_foocol); }
    ...
    -    Gtk::TreeModelColumn<ExampleWindow::foocol> m_col_foocol;
    +    foocol m_col_foocol;
    
  • examplewindow.cc

    -  m_TreeView.append_column( "model.m_col_foocol", m_Columns.m_col_foocol );
    +  m_TreeView.append_column( m_Columns.m_col_foocol );