如何断开信号
How to disconnect a signal
我编写了一个程序来计算 window 形状的面积和体积。一切正常,除了关于 Gtk::Entry::signal_activate()
的一件事。在以下代码中:
sigc::connection c = elongueur.signal_activate().connect([this]() { calcul(); });
switch (forme)
{
case 1: //carré
cacheEntry();
c.connected();
labelForme.set_label(listeDeroulante.get_active_text());
labelLongueur.set_label("longueur");
break;
case 2: //rectangle
c.disconnect();
elargeur.set_sensitive(true);
labelForme.set_label(listeDeroulante.get_active_text());
labelLongueur.set_label("longueur");
labelLargeur.set_label("largeur");
elongueur.signal_activate().connect([this]() { elargeur.grab_focus(); });
elargeur.signal_activate().connect([this]() { calcul(); });
break;
// ...
如果我从选项案例 2 开始,一切正常。如果我先通过案例 1,然后再通过案例 2,按下回车键会将焦点转移到下一个 Gtk::Entry
,但也会启动 calculation()
函数,这是我试图避免的。我认为 Gtk::Entry::signal_activate()
处理程序在通过案例 1 后没有断开连接,但我不知道为什么,因为我在进入案例 2 时调用 sigc::connection::disconnect()
。
我怎样才能完成这项工作?
我写了一个小程序来复制你的问题:
#include <iostream>
#include <gtkmm.h>
class MyWindow : public Gtk::ApplicationWindow
{
public:
MyWindow()
{
m_btn1.signal_clicked().connect([this](){PerformAction1();});
m_btn2.signal_clicked().connect([this](){PerformAction2();});
m_btn1And2.signal_clicked().connect([this](){PerformActions1And2();});
m_entryA.set_text("Entry A");
m_entryB.set_text("Entry B");
m_layout.attach(m_entryA, 0, 0, 1, 1);
m_layout.attach(m_entryB, 1, 0, 1, 1);
m_layout.attach(m_btn1, 0, 1, 2, 1);
m_layout.attach(m_btn2, 0, 2, 2, 1);
m_layout.attach(m_btn1And2, 0, 3, 2, 1);
add(m_layout);
}
void Calcul()
{
std::cout << "calcul() called" << std::endl;
}
void PerformAction1()
{
// Add another handler here to amplify the problem:
// m_signalEntryA = m_entryA.signal_activate().connect([this](){std::cout << "Action 0 : "; Calcul();});
m_signalEntryA = m_entryA.signal_activate().connect([this](){std::cout << "Action 1 : "; Calcul();});
// Works if you uncomment here:
// m_signalEntryA.disconnect();
}
void PerformAction2()
{
m_signalEntryA = m_entryA.signal_activate().connect([this](){std::cout << "Action 2 : "; Calcul();});
m_signalEntryA.disconnect();
m_signalEntryA = m_entryA.signal_activate().connect([this](){m_entryB.grab_focus();});
m_entryB.signal_activate().connect([this](){Calcul();});
}
void PerformActions1And2()
{
PerformAction1();
PerformAction2();
}
private:
Gtk::Grid m_layout;
Gtk::Entry m_entryA;
Gtk::Entry m_entryB;
Gtk::Button m_btn1{"Action 1"};
Gtk::Button m_btn2{"Action 2"};
Gtk::Button m_btn1And2{"Actions 1 and 2"};
sigc::connection m_signalEntryA;
};
int main(int argc, char* argv[])
{
auto app = Gtk::Application::create(argc, argv, "so.question.q66320704");
MyWindow window;
window.show_all();
return app->run(window);
}
这个程序有两个案例,就像你的案例一样,对信号进行相同的基本操作。您可以使用按钮激活不同的场景:
运行 程序并单击按钮,然后按 Enter 键,产生以下输出:
- 操作 1:
Action 1 : calcul() called
- 操作 2:无
- 操作 1 和 2:
Action 1 : calcul() called
从我在这个程序中看到的情况来看,信号连接中似乎存在某种“堆叠”。取消注释此行:
m_signalEntryA = m_entryA.signal_activate().connect([this](){std::cout << "Action 0 : "; Calcul();});
产生以下输出:
Action 0 : calcul() called
Action 1 : calcul() called
这非常令人惊讶,因为 official documentation 中没有记录这种行为。无论如何,要解决您的问题,您似乎必须在 break
.
之前尽早调用 disconnect
sigc::connection c = elongueur.signal_activate().connect([this]() { calcul(); });
switch (forme)
{
case 1: //carré
cacheEntry();
c.connected();
labelForme.set_label(listeDeroulante.get_active_text());
labelLongueur.set_label("longueur");
c.disconnect(); // <-- Add this. The connection is no more needed.
break;
case 2: //rectangle
c.disconnect();
elargeur.set_sensitive(true);
labelForme.set_label(listeDeroulante.get_active_text());
labelLongueur.set_label("longueur");
labelLargeur.set_label("largeur");
elongueur.signal_activate().connect([this]() { elargeur.grab_focus(); });
elargeur.signal_activate().connect([this]() { calcul(); });
break;
注意:我的Gtkmm版本是3.22。
先加这个header。请参阅 sigc++
中的文档
#include <sigc++/connection.h>
我们必须断开信号并停止它
自己声明class
sigc::connection c;
然后在你的主程序中我们可以做类似的事情
switch (forme)
{
case 1: // carré
cacheEntry();
labelForme.set_label(listeDeroulante.get_active_text());
labelLongueur.set_label("longueur");
if (c.connected() == false)
{
c = elongueur.signal_activate().connect([this]() { calcul(); });
}
break;
case 2: // rectangle
c.disconnect();//disconnected signal
elargeur.set_sensitive(true);
labelForme.set_label(listeDeroulante.get_active_text());
labelLongueur.set_label("longueur");
labelLargeur.set_label("largeur");
elongueur.signal_activate().connect([this]() { elargeur.grab_focus(); });
elargeur.signal_activate().connect([this]() { calcul(); elargeur.signal_activate().emission_stop();/*stop signal*/ });
break;
我编写了一个程序来计算 window 形状的面积和体积。一切正常,除了关于 Gtk::Entry::signal_activate()
的一件事。在以下代码中:
sigc::connection c = elongueur.signal_activate().connect([this]() { calcul(); });
switch (forme)
{
case 1: //carré
cacheEntry();
c.connected();
labelForme.set_label(listeDeroulante.get_active_text());
labelLongueur.set_label("longueur");
break;
case 2: //rectangle
c.disconnect();
elargeur.set_sensitive(true);
labelForme.set_label(listeDeroulante.get_active_text());
labelLongueur.set_label("longueur");
labelLargeur.set_label("largeur");
elongueur.signal_activate().connect([this]() { elargeur.grab_focus(); });
elargeur.signal_activate().connect([this]() { calcul(); });
break;
// ...
如果我从选项案例 2 开始,一切正常。如果我先通过案例 1,然后再通过案例 2,按下回车键会将焦点转移到下一个 Gtk::Entry
,但也会启动 calculation()
函数,这是我试图避免的。我认为 Gtk::Entry::signal_activate()
处理程序在通过案例 1 后没有断开连接,但我不知道为什么,因为我在进入案例 2 时调用 sigc::connection::disconnect()
。
我怎样才能完成这项工作?
我写了一个小程序来复制你的问题:
#include <iostream>
#include <gtkmm.h>
class MyWindow : public Gtk::ApplicationWindow
{
public:
MyWindow()
{
m_btn1.signal_clicked().connect([this](){PerformAction1();});
m_btn2.signal_clicked().connect([this](){PerformAction2();});
m_btn1And2.signal_clicked().connect([this](){PerformActions1And2();});
m_entryA.set_text("Entry A");
m_entryB.set_text("Entry B");
m_layout.attach(m_entryA, 0, 0, 1, 1);
m_layout.attach(m_entryB, 1, 0, 1, 1);
m_layout.attach(m_btn1, 0, 1, 2, 1);
m_layout.attach(m_btn2, 0, 2, 2, 1);
m_layout.attach(m_btn1And2, 0, 3, 2, 1);
add(m_layout);
}
void Calcul()
{
std::cout << "calcul() called" << std::endl;
}
void PerformAction1()
{
// Add another handler here to amplify the problem:
// m_signalEntryA = m_entryA.signal_activate().connect([this](){std::cout << "Action 0 : "; Calcul();});
m_signalEntryA = m_entryA.signal_activate().connect([this](){std::cout << "Action 1 : "; Calcul();});
// Works if you uncomment here:
// m_signalEntryA.disconnect();
}
void PerformAction2()
{
m_signalEntryA = m_entryA.signal_activate().connect([this](){std::cout << "Action 2 : "; Calcul();});
m_signalEntryA.disconnect();
m_signalEntryA = m_entryA.signal_activate().connect([this](){m_entryB.grab_focus();});
m_entryB.signal_activate().connect([this](){Calcul();});
}
void PerformActions1And2()
{
PerformAction1();
PerformAction2();
}
private:
Gtk::Grid m_layout;
Gtk::Entry m_entryA;
Gtk::Entry m_entryB;
Gtk::Button m_btn1{"Action 1"};
Gtk::Button m_btn2{"Action 2"};
Gtk::Button m_btn1And2{"Actions 1 and 2"};
sigc::connection m_signalEntryA;
};
int main(int argc, char* argv[])
{
auto app = Gtk::Application::create(argc, argv, "so.question.q66320704");
MyWindow window;
window.show_all();
return app->run(window);
}
这个程序有两个案例,就像你的案例一样,对信号进行相同的基本操作。您可以使用按钮激活不同的场景:
运行 程序并单击按钮,然后按 Enter 键,产生以下输出:
- 操作 1:
Action 1 : calcul() called
- 操作 2:无
- 操作 1 和 2:
Action 1 : calcul() called
从我在这个程序中看到的情况来看,信号连接中似乎存在某种“堆叠”。取消注释此行:
m_signalEntryA = m_entryA.signal_activate().connect([this](){std::cout << "Action 0 : "; Calcul();});
产生以下输出:
Action 0 : calcul() called
Action 1 : calcul() called
这非常令人惊讶,因为 official documentation 中没有记录这种行为。无论如何,要解决您的问题,您似乎必须在 break
.
sigc::connection c = elongueur.signal_activate().connect([this]() { calcul(); });
switch (forme)
{
case 1: //carré
cacheEntry();
c.connected();
labelForme.set_label(listeDeroulante.get_active_text());
labelLongueur.set_label("longueur");
c.disconnect(); // <-- Add this. The connection is no more needed.
break;
case 2: //rectangle
c.disconnect();
elargeur.set_sensitive(true);
labelForme.set_label(listeDeroulante.get_active_text());
labelLongueur.set_label("longueur");
labelLargeur.set_label("largeur");
elongueur.signal_activate().connect([this]() { elargeur.grab_focus(); });
elargeur.signal_activate().connect([this]() { calcul(); });
break;
注意:我的Gtkmm版本是3.22。
先加这个header。请参阅 sigc++
中的文档#include <sigc++/connection.h>
我们必须断开信号并停止它
自己声明class
sigc::connection c;
然后在你的主程序中我们可以做类似的事情
switch (forme)
{
case 1: // carré
cacheEntry();
labelForme.set_label(listeDeroulante.get_active_text());
labelLongueur.set_label("longueur");
if (c.connected() == false)
{
c = elongueur.signal_activate().connect([this]() { calcul(); });
}
break;
case 2: // rectangle
c.disconnect();//disconnected signal
elargeur.set_sensitive(true);
labelForme.set_label(listeDeroulante.get_active_text());
labelLongueur.set_label("longueur");
labelLargeur.set_label("largeur");
elongueur.signal_activate().connect([this]() { elargeur.grab_focus(); });
elargeur.signal_activate().connect([this]() { calcul(); elargeur.signal_activate().emission_stop();/*stop signal*/ });
break;