我想要一个 gtkmm 拖放目标,以便在拖放发生之前根据来自源的数据做出决定。是否可以从“拖动动作”回调中请求数据?我在文档中看到了它的提示,但没有明确的例子。
signal_drag_data_received 的 gtkmm 3.24 文档说
signal_drag_data_received() 信号在拖拽数据被接收到时在放置点发出。如果接收到数据以确定是否接受放置,则处理程序应调用 gdk_drag_status() 并且不完成拖动。
好像在暗示可以在drop之前请求数据。但我不确定这是否可能或如何去做。以下是连接了
signal_drag_data_get
、signal_drag_data_received
和 signal_drag_motion
信号的拖放的工作示例。
main.cpp
#include <gtkmm.h>
#include "test_window.h"
int
main (int argc,
char **argv)
{
int result = 0;
argc = 1;
Glib::RefPtr<Gtk::Application> app = Gtk::Application::create(argc, argv, "org.gtkmm.test_app");
app->set_flags(Gio::APPLICATION_NON_UNIQUE);
test_window test_window_i;
result = app->run(test_window_i);
return result;
}
test_window.h
#ifndef SRC_TEST_WINDOW_H_
#define SRC_TEST_WINDOW_H_
#include <gtkmm.h>
class test_window: public Gtk::Window
{
public:
test_window();
void source_get_data(
const Glib::RefPtr<Gdk::DragContext>& context,
Gtk::SelectionData& selection_data,
guint info,
guint time);
void destination_received_data(
const Glib::RefPtr<Gdk::DragContext>& context,
int x,
int y,
const Gtk::SelectionData & selection_data,
guint info,
guint time);
bool destination_drag_motion_event(
const Glib::RefPtr<Gdk::DragContext>& context,
int x,
int y,
guint time);
private:
Gtk::Box m_box;
Gtk::Button m_source;
Gtk::Button m_destination;
};
#endif
test_window.cpp
#include "test_window.h"
#include <iostream>
test_window::test_window()
{
show_all();
set_border_width(1);
set_type_hint(Gdk::WINDOW_TYPE_HINT_NORMAL);
resize(800, 800);
add(m_box);
m_box.set_orientation(Gtk::ORIENTATION_VERTICAL);
m_box.pack_start(m_source, true, false);
m_box.pack_start(m_destination, true, false);
m_source.set_label("source");
m_destination.set_label("destination");
std::vector<Gtk::TargetEntry> drag_targets = {
Gtk::TargetEntry("STRING"),
Gtk::TargetEntry("text/plain")};
m_source.drag_source_set(drag_targets);
m_destination.drag_dest_set(drag_targets);
m_source.signal_drag_data_get().connect(sigc::mem_fun(*this, &test_window::source_get_data));
m_destination.signal_drag_data_received().connect(sigc::mem_fun(*this, &test_window::destination_received_data));
m_destination.signal_drag_motion ().connect(sigc::mem_fun(*this, &test_window::destination_drag_motion_event));
show_all();
}
void test_window::source_get_data(
const Glib::RefPtr<Gdk::DragContext>& context,
Gtk::SelectionData& selection_data,
guint info,
guint time)
{
std::string source_message = "Hello from source.";
selection_data.set(
selection_data.get_target(),
8 /* 8 bits format */,
(const guchar*)source_message.c_str(),
source_message.size());
}
void test_window::destination_received_data(
const Glib::RefPtr<Gdk::DragContext>& context,
int x,
int y,
const Gtk::SelectionData & selection_data,
guint info,
guint time)
{
if ((selection_data.get_length() >= 0) && (selection_data.get_format() == 8))
{
std::string message = selection_data.get_data_as_string();
std::cout << message << std::endl;
}
context->drag_finish(false, false, time);
}
bool test_window::destination_drag_motion_event(
const Glib::RefPtr<Gdk::DragContext>& context,
int x,
int y,
guint time)
{
std::cout << "Destination drag motion event." << std::endl;
return true;
}
制作文件
EXECUTABLE=test_app
CFLAGS=-c -Wall -g
CC=g++
#
SOURCES= src/main.cpp src/test_window.cpp
OBJECTS=$(SOURCES:.cpp=.o)
all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(OBJECTS) -o $@ `pkg-config gtkmm-3.0 --libs`
.cpp.o:
$(CC) $(CFLAGS) $< -o $@ `pkg-config gtkmm-3.0 --cflags`
clean:
rm -rf src/*.o $(EXECUTABLE)