I struggled with the following code. My signal handler on_button_press_event() is never called but I have no idea why. Could someone have a look on it? Maybe someone is able to run through the gtkmm lib with debug infos. I only have the pre-installed gtkmm packages which could not be used for debugging into the library itself.
#include <iostream>
using namespace std;
#include <gtkmm.h>
#include <goocanvasmm.h>
bool MyExternalHandler( const Glib::RefPtr<Goocanvas::Item>& item, GdkEventButton* ev )
{
cout << "External Handler" << endl;
return false;
}
class MyRect : public Goocanvas::Rect
{
public:
MyRect( double x, double y, double w, double h)
//: Goocanvas::Rect( x,y,w,h)
{
property_x()=x;
property_y()=y;
property_width()=w;
property_height()=h;
}
public:
virtual void nonsens() {}
bool on_button_press_event(const Glib::RefPtr<Item>& target, GdkEventButton* event) override
{
cout << "override handler" << endl;
return false;
}
bool Handler( const Glib::RefPtr<Goocanvas::Item>& item, GdkEventButton* ev )
{
cout << "via mem_fun" << endl;
return false;
}
bool on_enter_notify_event(const Glib::RefPtr<Item>& target, GdkEventCrossing* event) override
{
cout << "override enter notify" << endl;
return false;
}
};
int main(int argc, char* argv[])
{
Gtk::Main app(&argc, &argv);
Goocanvas::init("example", "0.1", argc, argv);
Gtk::Window win;
Goocanvas::Canvas m_canvas;
m_canvas.set_size_request(640, 480);
m_canvas.set_bounds(0, 0, 1000, 1000);
MyRect* ptr;
Glib::RefPtr<MyRect> m_rect_own(ptr=new MyRect(225, 225, 150, 150));
m_rect_own->property_line_width() = 1.0;
m_rect_own->property_stroke_color() = "black";
m_rect_own->property_fill_color_rgba() = 0x555555ff;
Glib::RefPtr<Goocanvas::Item> root = m_canvas.get_root_item();
root->add_child( m_rect_own);
((Glib::RefPtr<Goocanvas::Item>&)m_rect_own)->signal_button_press_event().connect(sigc::ptr_fun(&MyExternalHandler));
((Glib::RefPtr<Goocanvas::Item>&)m_rect_own)->signal_button_press_event().connect(sigc::mem_fun(*ptr, &MyRect::Handler));
win.add(m_canvas);
win.show_all_children();
Gtk::Main::run(win);
return 0;
}
Your on_button_press_event() method is not an override, because it has the wrong parameters:
https://developer.gnome.org/gtkmm/unstable/classGtk_1_1Widget.html#aba72b7f8655d1a0eb1273a26894584e3
Related
I got this error on SystemC, and I don't understand why. The error is:
'write': is not a member of
'sc_core::sc_in' ConsoleApplication1
'write': is not a member of 'sc_core::sc_in'
class "sc_core::sc_in" has no member "write"
class "sc_core::sc_in" has no member "write"
Here I put together the code.
#include<systemc.h>
SC_MODULE(prin) {
sc_in<bool> a;
void print() {
cout << "Hello World\n";
}
SC_CTOR(prin) {
SC_METHOD(print);
sensitive << a;
}
};
SC_MODULE(input) {
prin b;
void in() {
b.a.write(false);
wait();
b.a.write(true);
wait();
}
SC_CTOR(input) : b("sds"){
SC_THREAD(in);
}
};
int sc_main(int argc, char* argv[]) {
input prin1("pint");
sc_start();
return 0;
}
If the error seems confusing, here I put together the picture of my error:
The port "a" is an input port so cannot be written to. If you make it an output port then you can write to it. Also, the port is not bound so you will also get an error for that so I have bound a signal to it just so it compiles.
#include <systemc.h>
SC_MODULE(prin) {
sc_out<bool> a; //output port
sc_signal<bool> sig; //something to bind port a to
void print() {
cout << "Hello World\n";
}
SC_CTOR(prin) {
SC_METHOD(print);
sensitive << a;
a(sig); //bind port a to s signal
}
};
SC_MODULE(input) {
prin b;
void in() {
b.a.write(false);
wait();
b.a.write(true);
wait();
}
SC_CTOR(input) : b("sds"){
SC_THREAD(in);
}
};
int sc_main(int argc, char* argv[]) {
input prin1("pint");
sc_start();
return 0;
}
Then
g++ -file.cpp -lsystemc
./a.out
Gives me the output
SystemC 2.3.2-Accellera --- Apr 16 2018 00:15:03
Copyright (c) 1996-2017 by all Contributors,
ALL RIGHTS RESERVED
Hello World
I have (sort of) copied (but with some modifications) the example in the GTKmm tutorials on keyboard events. (link)
https://developer.gnome.org/gtkmm-tutorial/stable/sec-keyboardevents-overview.html.en#keyboardevents-simple-example
Here is my code:
#include <gtkmm/application.h>
#include <gtkmm/window.h>
#include <gtkmm/textview.h>
#include <iostream>
class MainWindow
{
public:
MainWindow()
{
_window_.set_default_size(600, 400);
_window_.add(_textview_);
Glib::RefPtr<Gtk::TextBuffer> textbuffer_rp{_textview_.get_buffer()};
textbuffer_rp->set_text("some text here");
_textview_.set_monospace();
_window_.add_events(Gdk::KEY_PRESS_MASK);
_window_.show_all_children();
}
Gtk::Window &get_window()
{
return _window_;
}
protected:
bool on_key_press_event(GdkEventKey* event)
{
std::cout << "some keypress event" << std::endl;
if
(
(event->keyval == GDK_KEY_H) &&
((event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK) == GDK_CONTROL_MASK))
)
{
std::cout << "Hello world!" << std::endl;
}
if
(
(event->keyval == GDK_KEY_C) &&
((event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK) == GDK_CONTROL_MASK))
)
{
signal_textview_CTRL_C();
}
else if
(
(event->keyval == GDK_KEY_V) &&
((event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK) == GDK_CONTROL_MASK))
)
{
signal_textview_CTRL_V();
}
else
{
std::cout << "unhandled key" << std::endl;
}
return true;
}
void signal_textview_CTRL_C()
{
_text_register_0_ = "some text gets put here";
}
void signal_textview_CTRL_V()
{
Glib::RefPtr<Gtk::TextBuffer> textbuffer_rp{_textview_.get_buffer()};
textbuffer_rp->set_text(_text_register_0_);
}
private:
Gtk::Window _window_;
Gtk::TextView _textview_;
Glib::ustring _text_register_0_;
};
int main(int argc, char *argv[])
{
auto app = Gtk::Application::create(argc, argv, "org.gtkmm.examples.base");
MainWindow mainwindow;
return app->run(mainwindow.get_window());
}
However it is not working - none of the signal events appear to fire when I press the key sequences CTRL-C, CTRL-V, CTRL-H.
I think I have stripped all the irrelevant stuff from the code so this should be a working MWE.
Connect your handler as first.
_window_.signal_key_press_event().connect(sigc::mem_fun(*this, &MainWindow::on_key_press_event), false);
Return false to let _textview_ get the key.
Your conditions are contradictory.
GDK_KEY_H is keysym for shift+h. Then you check (event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK) == GDK_CONTROL_MASK). You are asking if state (which we know is with GDK_SHIFT_MASK) is ONLY GDK_CONTROL_MASK.
Code:
#include <gtkmm/application.h>
#include <gtkmm/window.h>
#include <gtkmm/textview.h>
#include <iostream>
class MainWindow
{
public:
MainWindow()
{
_window_.set_default_size(600, 400);
_window_.add(_textview_);
Glib::RefPtr<Gtk::TextBuffer> textbuffer_rp{_textview_.get_buffer()};
textbuffer_rp->set_text("some text here");
_textview_.set_monospace();
_window_.add_events(Gdk::KEY_PRESS_MASK);
_window_.signal_key_press_event().connect(sigc::mem_fun(*this, &MainWindow::on_key_press_event), false);
_window_.show_all_children();
}
Gtk::Window &get_window()
{
return _window_;
}
protected:
bool on_key_press_event(GdkEventKey* event)
{
std::cout << "some keypress event " << std::hex<<event->keyval<<" "<<std::hex<<event->state<<std::endl;
if
(
(event->keyval == GDK_KEY_h) &&
(event->state & GDK_CONTROL_MASK)
)
{
std::cout << "Hello world!" << std::endl;
return true;
}
if
(
(event->keyval == GDK_KEY_c) &&
(event->state & GDK_CONTROL_MASK)
)
{
std::cout<<"ctrl c"<<std::endl;
signal_textview_CTRL_C();
return true;
}
else if
(
(event->keyval == GDK_KEY_v) &&
(event->state & GDK_CONTROL_MASK)
)
{
std::cout<<"ctrl v"<<std::endl;
signal_textview_CTRL_V();
return true;
}
else
{
std::cout << "unhandled key" << std::endl;
}
return false;
}
void signal_textview_CTRL_C()
{
_text_register_0_ = "some text gets put here";
}
void signal_textview_CTRL_V()
{
Glib::RefPtr<Gtk::TextBuffer> textbuffer_rp{_textview_.get_buffer()};
textbuffer_rp->set_text(_text_register_0_);
}
private:
Gtk::Window _window_;
Gtk::TextView _textview_;
Glib::ustring _text_register_0_;
};
int main(int argc, char *argv[])
{
auto app = Gtk::Application::create(argc, argv, "org.gtkmm.examples.base");
MainWindow mainwindow;
return app->run(mainwindow.get_window());
}
I'd like to print out the name of sc_module to which sc_signal connected.
How can I get the module name, "module_a" in the following code, from "sig_out"?
#include "systemc.h"
class sig_if : virtual public sc_interface
{
};
class my_sig : public sc_module, public sig_if
{
public:
my_sig(sc_module_name nm) : sc_module(nm)
{
}
};
SC_MODULE(test_module)
{
sc_port<sig_if> out;
SC_CTOR(test_module)
{
}
};
int sc_main(int argc, char* argv[]) {
test_module module_a("module_a");
my_sig sig_out("sig_out");
module_a.out(sig_out);
// std::cout << sig_out.get_parent() << std::endl;
sc_start();
return 0;
}
You could override sc_interface::register_port() in the my_sig class to save a reference to the bound port. The parent of the bound port is the module that contains the port.
#include <iostream>
#include <cassert>
#include "systemc.h"
class sig_if : virtual public sc_interface
{
};
class my_sig : public sc_module, public sig_if
{
public:
my_sig(sc_module_name nm) : sc_module(nm), bound_port(NULL)
{
}
void register_port(sc_port_base& port, const char*) {
bound_port = &port;
}
sc_object* get_bound_module() const {
assert(bound_port);
return bound_port->get_parent_object();
};
sc_port_base* bound_port;
};
SC_MODULE(test_module)
{
sc_port<sig_if> out;
SC_CTOR(test_module)
{
}
};
int sc_main(int argc, char* argv[]) {
test_module module_a("module_a");
my_sig sig_out("sig_out");
module_a.out(sig_out);
sc_start(0, SC_NS);
std::cout << sig_out.get_bound_module()->name() << std::endl;
return 0;
}
The above code prints the name of module_a. Note that sig::get_bound_module() can only be called after elaboration, that is, after sc_start() has been called, because sc_interface::register_port() is only called during elaboration.
This is what I have so far and I want to save pcd file from it
I know I have to do something like this but not exactly sure
pcl::PointCloud::PointPointXYZRGBA> cloud;
pcl::io:;savePCDFileASCII("test.pcd",cloud);
what do i have to add in my current code that i will have test.pcd
Thanks
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/io/openni_grabber.h>
#include <pcl/visualization/cloud_viewer.h>
#include <pcl/common/time.h>
class SimpleOpenNIProcessor
{
public:
SimpleOpenNIProcessor () : viewer ("PCL OpenNI Viewer") {}
void cloud_cb_ (const pcl::PointCloud<pcl::PointXYZRGBA>::ConstPtr &cloud)
{
static unsigned count = 0;
static double last = pcl::getTime ();
if (++count == 30)
{
double now = pcl::getTime ();
std::cout << "distance of center pixel :" << cloud->points [(cloud->width >> 1) * (cloud->height + 1)].z << " mm. Average framerate: " << double(count)/double(now - last) << " Hz" << std::endl;
count = 0;
last = now;
}
if (!viewer.wasStopped())
viewer.showCloud (cloud);
}
void run ()
{
// create a new grabber for OpenNI devices
pcl::Grabber* interface = new pcl::OpenNIGrabber();
// make callback function from member function
boost::function<void (const pcl::PointCloud<pcl::PointXYZRGBA>::ConstPtr&)> f =
boost::bind (&SimpleOpenNIProcessor::cloud_cb_, this, _1);
// connect callback function for desired signal. In this case its a point cloud with color values
boost::signals2::connection c = interface->registerCallback (f);
// start receiving point clouds
interface->start ();
// wait until user quits program with Ctrl-C, but no busy-waiting -> sleep (1);
while (true)
boost::this_thread::sleep (boost::posix_time::seconds (1));
// stop the grabber
interface->stop ();
}
pcl::visualization::CloudViewer viewer;
};
int main ()
{
SimpleOpenNIProcessor v;
v.run ();
return (0);
}
#include <iostream>
#include <string>
#include <sstream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/io/openni_grabber.h>
#include <pcl/visualization/cloud_viewer.h>
using namespace std;
const string OUT_DIR = "D:\\frame_saver_output\\";
class SimpleOpenNIViewer
{
public:
SimpleOpenNIViewer () : viewer ("PCL Viewer")
{
frames_saved = 0;
save_one = false;
}
void cloud_cb_ (const pcl::PointCloud<pcl::PointXYZRGB>::ConstPtr &cloud)
{
if (!viewer.wasStopped()) {
viewer.showCloud (cloud);
if( save_one ) {
save_one = false;
std::stringstream out;
out << frames_saved;
std::string name = OUT_DIR + "cloud" + out.str() + ".pcd";
pcl::io::savePCDFileASCII( name, *cloud );
}
}
}
void run ()
{
pcl::Grabber* interface = new pcl::OpenNIGrabber();
boost::function<void (const pcl::PointCloud<pcl::PointXYZRGB>::ConstPtr&)> f =
boost::bind (&SimpleOpenNIViewer::cloud_cb_, this, _1);
interface->registerCallback (f);
interface->start ();
char c;
while (!viewer.wasStopped())
{
//sleep (1);
c = getchar();
if( c == 's' ) {
cout << "Saving frame " << frames_saved << ".\n";
frames_saved++;
save_one = true;
}
}
interface->stop ();
}
pcl::visualization::CloudViewer viewer;
private:
int frames_saved;
bool save_one;
};
int main ()
{
SimpleOpenNIViewer v;
v.run ();
return 0;
}
Here you go.
When I create a D-Bus server (via g_bus_own_name()) and the client to it (using g_dbus_proxy_new()) in the same process and then call g_dbus_proxy_call_sync(), it never returns. However, if server and client are in separate processes, everything is ok.
The following code illustrates my problem (I am using giomm C++ bindings here):
file main.cc:
#include <giomm.h>
#include <thread>
int server_main();
int client_main();
int main() {
Gio::init();
std::thread thr_server([](){ server_main(); });
sleep(1); // give some time to server to register
std::thread thr_client([](){ client_main(); });
sleep(10); // wait for the client to finish
}
file server.cc:
#include <giomm.h>
#include <iostream>
namespace {
static Glib::RefPtr<Gio::DBus::NodeInfo> introspection_data;
static Glib::ustring introspection_xml =
"<node name='/org/glibmm/DBusExample'>"
" <interface name='org.glibmm.DBusExample'>"
" <method name='Method'>"
" </method>"
" </interface>"
"</node>";
guint registered_id = 0;
}
static void on_method_call(const Glib::RefPtr<Gio::DBus::Connection>& /* connection */,
const Glib::ustring& /* sender */, const Glib::ustring& /* object_path */,
const Glib::ustring& /* interface_name */, const Glib::ustring& method_name,
const Glib::VariantContainerBase& parameters,
const Glib::RefPtr<Gio::DBus::MethodInvocation>& invocation)
{
if(method_name == "Method") {
std::cout << "Method was called\n";
}
}
const Gio::DBus::InterfaceVTable interface_vtable(sigc::ptr_fun(&on_method_call));
void on_bus_acquired(const Glib::RefPtr<Gio::DBus::Connection>& connection, const Glib::ustring& /* name */)
{
std::cout << "on_bus_acquired\n";
try {
registered_id = connection->register_object("/org/glibmm/DBusExample",
introspection_data->lookup_interface(),
interface_vtable);
}
catch(const Glib::Error& ex) {
std::cerr << "Registration of object failed." << std::endl;
}
return;
}
void on_name_acquired(const Glib::RefPtr<Gio::DBus::Connection>& /* connection */, const Glib::ustring& /* name */)
{}
void on_name_lost(const Glib::RefPtr<Gio::DBus::Connection>& connection, const Glib::ustring& /* name */) {
connection->unregister_object(registered_id);
}
int server_main()
{
try {
introspection_data = Gio::DBus::NodeInfo::create_for_xml(introspection_xml);
}
catch(const Glib::Error& ex) {
std::cerr << "Unable to create introspection data: " << ex.what() <<
"." << std::endl;
return 1;
}
const guint id = Gio::DBus::own_name(Gio::DBus::BUS_TYPE_SESSION,
"org.glibmm.DBusExample",
sigc::ptr_fun(&on_bus_acquired),
sigc::ptr_fun(&on_name_acquired),
sigc::ptr_fun(&on_name_lost));
//Keep the service running
auto loop = Glib::MainLoop::create();
loop->run();
Gio::DBus::unown_name(id);
return EXIT_SUCCESS;
}
file client.cc:
#include <giomm.h>
#include <iostream>
Glib::RefPtr<Glib::MainLoop> loop;
// A main loop idle callback to quit when the main loop is idle.
bool on_main_loop_idle() {
std::cout << "loop_idle\n";
loop->quit();
return false;
}
void on_dbus_proxy_available(Glib::RefPtr<Gio::AsyncResult>& result)
{
auto proxy = Gio::DBus::Proxy::create_finish(result);
if(!proxy) {
std::cerr << "The proxy to the user's session bus was not successfully "
"created." << std::endl;
loop->quit();
return;
}
try {
std::cout << "Calling...\n";
proxy->call_sync("Method");
std::cout << "It works!\n";
}
catch(const Glib::Error& error) {
std::cerr << "Got an error: '" << error.what() << "'." << std::endl;
}
// Connect an idle callback to the main loop to quit when the main loop is
// idle now that the method call is finished.
Glib::signal_idle().connect(sigc::ptr_fun(&on_main_loop_idle));
}
int client_main() {
loop = Glib::MainLoop::create();
auto connection =
Gio::DBus::Connection::get_sync(Gio::DBus::BUS_TYPE_SESSION);
if(!connection) {
std::cerr << "The user's session bus is not available." << std::endl;
return 1;
}
// Create the proxy to the bus asynchronously.
Gio::DBus::Proxy::create(connection, "org.glibmm.DBusExample",
"/org/glibmm/DBusExample", "org.glibmm.DBusExample",
sigc::ptr_fun(&on_dbus_proxy_available));
loop->run();
return EXIT_SUCCESS;
}
I compile the test with g++ -O2 -std=c++0x main.cc server.cc client.cc -o test $(pkg-config --cflags --libs giomm-2.4) and run:
./test
on_bus_acquired
Calling...
<it hangs>
However, when I change main.cc:
#include <giomm.h>
int server_main();
int client_main();
int main() {
Gio::init();
auto childid = fork();
if (childid == 0) {
server_main();
} else {
sleep(1);
client_main();
}
}
I get:
./test
on_bus_acquired
Calling...
Method was called
It works!
So call_sync() returns successfully.
I tried to exclude loops from server and client, and use a single-threaded main.cc:
#include <giomm.h>
#include <thread>
int server_main();
int client_main();
int main() {
Gio::init();
server_main();
client_main();
auto loop = Glib::MainLoop::create();
loop->run();
}
Nothing helps. The question is, what am I doing wrong? I want to use my d-bus server and client in one process.
I figured it out, the trick is to execute
Glib::VariantContainerBase result;
invocation->return_value(result);
in the end of on_method_call.