【问题标题】:Gtkmm scroll_event do not work when a button is pressed按下按钮时 Gtkmm scroll_event 不起作用
【发布时间】:2013-04-20 11:40:46
【问题描述】:

我有一个 Gtk::EventBox 连接了两个事件:button_press_event 和 scroll_event。 这两个事件都可以正常工作,但是当我按住鼠标按钮时,不会发出滚动事件。

我在课堂上实现了bool on_button_press_event (GdkEventButton *e)bool on_scroll_event (GdkEventScroll *e) 这两个函数。这两个函数返回false 以进一步传播事件。

我正在使用 gtkmm3。

我该如何解决这个问题?

重现问题的代码示例:

#include <gtkmm.h>
#include <iostream>

class MyWindow : public Gtk::Window
{
  Gtk::EventBox event_box;
  Gtk::ScrolledWindow scrolled;
public:
  bool on_button_press_event(GdkEventButton *b)
  {
    std::cout << "button press" << std::endl;
    return false;
  }

  bool on_scroll_event(GdkEventScroll *e)
  {
    std::cout << "scrollEvent" << std::endl;
    return false;
  }

  MyWindow ()
  {
    add(scrolled);
    scrolled.add(event_box);
    set_default_size(640, 480);
    show_all();
  }
};

int main(int argc, char** argv)
{
  Gtk::Main kit(argc, argv);
  MyWindow window;
  kit.run(window);
  return 0;
}

【问题讨论】:

    标签: c++ events gtk signals gtkmm


    【解决方案1】:

    您展示的示例代码有两个问题。

    • 首先,您说“我有一个连接了两个事件的 Gtk::EventBox”。但在您的示例中,您连接到 MyWindow 的事件,而未连接 EventBox 的事件。

    • EventBox 允许您接收事件,但您仍然必须明确说明要接收哪些事件。

    这是更正后的代码:

    #include <gtkmm.h>
    #include <iostream>
    
    class MyWindow : public Gtk::Window
    {
      Gtk::EventBox event_box;
    
      bool event_box_button_press(GdkEventButton *b)
      {
        std::cout << "button press" << std::endl;
        return false;
      }
    
      bool event_box_scroll(GdkEventScroll *e)
      {
        std::cout << "scrollEvent" << std::endl;
        return false;
      }
    
    public:
      MyWindow ()
      {
        event_box.add_events(Gdk::BUTTON_MOTION_MASK);
        event_box.add_events(Gdk::SCROLL_MASK);
    
        event_box.signal_button_press_event().connect(
            sigc::mem_fun(*this, &MyWindow::event_box_button_press));
        event_box.signal_scroll_event().connect(
            sigc::mem_fun(*this, &MyWindow::event_box_scroll));
    
        add(event_box);
    
        set_default_size(640, 480);
        show_all();
      }
    };
    
    int main(int argc, char** argv)
    {
      Gtk::Main kit(argc, argv);
      MyWindow window;
      kit.run(window);
      return 0;
    }
    

    关于此代码的一些注释:

    • 我省略了 ScrolledWindow,因为它与示例无关。您不需要它来捕获滚动事件。如果您的应用程序确实需要滚动窗口,您可以将其添加回来。

    • 如果您派生具有所需行为的自定义 EventBox,代码可能会更简洁。我这样做不是为了更接近您的原始代码。

    • 有关连接信号和 sigc::mem_fun 的信息,请参阅 this documentation

    【讨论】:

      【解决方案2】:

      看起来在 windows 上,scrolledWindow 是监视滚动事件而不是主窗口的正确位置。

      使用以下修改,我能够在 Windows 7 上处理滚动事件。

      #include <gtkmm.h>
      #include <iostream>
      
      class MyScrolledWindow : public Gtk::ScrolledWindow
      {
      public:
        bool on_scroll_event(GdkEventScroll *e)
        {
          std::cout << "scrollEvent" << std::endl;
          return false;
        }
      
        MyScrolledWindow()
        {
        }
      };
      
      class MyWindow : public Gtk::Window
      {
        Gtk::EventBox event_box;
        MyScrolledWindow scrolled;
      public:
        bool on_button_press_event(GdkEventButton *b)
        {
          std::cout << "button press" << std::endl;
          return false;
        }
      
        MyWindow ()
        {
          add(scrolled);
          scrolled.add(event_box);
          set_default_size(640, 480);
          show_all();
        }
      };
      
      int main(int argc, char** argv)
      {
        Gtk::Main kit(argc, argv);
        MyWindow window;
        kit.run(window);
        return 0;
      }
      

      ====== 旧答案:=================

      我无法重现您的问题。这是我用来重现您的问题的代码:

      #include <gtkmm.h>
      #include <iostream>
      
      class MyEventBox : public Gtk::EventBox
      {
        bool on_button_press_event(GdkEventButton *b)
        {
          std::cout << "button press" << std::endl;
      
          return false;
        }
      
        bool on_scroll_event(GdkEventScroll *e)
        {
          std::cout << "scrollEvent" << std::endl;
      
          return false;
        }
      };
      
      
      int main(int argc, char** argv)
      {
        Gtk::Main kit(argc, argv);
        Gtk::Window window;
        MyEventBox eventBox;
      
        eventBox.show();
        window.add(eventBox);
      
        kit.run(window);
      
        return 0;
      }
      

      为了编译,我使用了以下命令行(使用 Linux):

      g++ main.cpp $(pkg-config --cflags --libs gtkmm-3.0)

      • 如果您可以使用此最小示例重现您的问题,则该问题可能是特定于平台的,并且可能需要使用窗口/事件框'Gdk::Window 的解决方法。
      • 如果您无法使用此代码重现您的问题,则该问题是由您的代码中的其他地方引起的,您需要发布更多信息。

      【讨论】:

      • 对不起,我没有在您的原始帖子中添加评论,但我没有足够的声誉来这样做
      • 在哪些操作系统上您能够重现您的问题?
      • 好的,我已经用示例代码更新了问题以重现问题。我将在 Linux/Debian 下测试。
      • 我刚刚在 Linux Mint 上测试了示例代码,但无法重现。看起来好像是平台特定的问题
      • 我已经在 macosx 上测试了这个例子并且工作正常。看来你是对的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-26
      • 1970-01-01
      相关资源
      最近更新 更多