Java实现Qt的SIGNAL-SLOT机制(保存到Map中,从而将它们关联起来,收到信号进行解析,最后反射调用)
SIGNAL-SLOT是Qt的一大特色,使用起来十分方便。在传统的AWT和Swing编程中,我们都是为要在
- public static void connect(QObject sender, String signal, Object receiver, String slot) {
- if (sender.signalSlotMap == null)
- sender.signalSlotMap = new HashMap<String, List<ReceiverSlot>>();
- List<ReceiverSlot> slotList = sender.signalSlotMap.get(signal);
- if (slotList == null) {
- slotList = new LinkedList<ReceiverSlot>();
- sender.signalSlotMap.put(signal, slotList);
- }
- slotList.add(createReceiverSlot(receiver, slot));
- }
- static class ReceiverSlot {
- Object receiver;
- Method slot;
- Object[] args;
- }
- private static ReceiverSlot createReceiverSlot(Object receiver, String slot) {
- ReceiverSlot receiverSlot = new ReceiverSlot();
- receiverSlot.receiver = receiver;
- Pattern pattern = Pattern.compile("(\\w+)\\(([\\w+,]*)\\)");
- Matcher matcher = pattern.matcher(slot);
- if (matcher.matches() && matcher.groupCount() == 2) {
- // 1.Connect SIGNAL to SLOT
- try {
- String methodName = matcher.group(1);
- String argStr = matcher.group(2);
- ArrayList<String> argList = new ArrayList<String>();
- pattern = Pattern.compile("\\w+");
- matcher = pattern.matcher(argStr);
- while (matcher.find())
- argList.add(matcher.group());
- String[] arguments = argList.toArray(new String[0]);
- receiverSlot.slot = findMethod(receiver, methodName, arguments);
- receiverSlot.args = new Object[0];
- }
- catch (Exception e) {
- e.printStackTrace();
- }
- }
- else {
- // 2.Connect SIGNAL to SIGNAL
- if (receiver instanceof QObject) {
- receiverSlot.slot = emitMethod;
- receiverSlot.args = new Object[] { slot };
- }
- }
- return receiverSlot;
- }
- private static Method emitMethod;
- protected Map<String, List<ReceiverSlot>> signalSlotMap;
- static {
- try {
- emitMethod = QObject.class.getDeclaredMethod("emit", String.class, Object[].class);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- private static Method findMethod(Object receiver, String methodName, String[] arguments)
- throws NoSuchMethodException {
- Method slotMethod = null;
- if (arguments.length == 0)
- slotMethod = receiver.getClass().getMethod(methodName, new Class[0]);
- else {
- for (Method method : receiver.getClass().getMethods()) {
- // 1.Check method name
- if (!method.getName().equals(methodName))
- continue;
- // 2.Check parameter number
- Class<?>[] paramTypes = method.getParameterTypes();
- if (paramTypes.length != arguments.length)
- continue;
- // 3.Check parameter type
- boolean isMatch = true;
- for (int i = 0; i < paramTypes.length; i++) {
- if (!paramTypes[i].getSimpleName().equals(arguments[i])) {
- isMatch = false;
- break;
- }
- }
- if (isMatch) {
- slotMethod = method;
- break;
- }
- }
- if (slotMethod == null)
- throw new NoSuchMethodException("Cannot find method[" + methodName +
- "] with parameters: " + Arrays.toString(arguments));
- }
- return slotMethod;
- }
- protected void emit(String signal, Object... args) {
- System.out.println(getClass().getSimpleName() + " emit signal " + signal);
- if (signalSlotMap == null)
- return;
- List<ReceiverSlot> slotList = signalSlotMap.get(signal);
- if (slotList == null || slotList.isEmpty())
- return;
- for (ReceiverSlot objSlot : slotList) {
- try {
- if (objSlot.slot == emitMethod)
- objSlot.slot.invoke(objSlot.receiver, objSlot.args[0], args);
- else
- objSlot.slot.invoke(objSlot.receiver, args);
- }
- catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
- public class QWidget<T extends JComponent> extends QObject implements QSwing<T> {
- protected T widget;
- public QWidget(Class<T> clazz) {
- try {
- widget = clazz.newInstance();
- }
- catch (Exception e) {
- e.printStackTrace();
- }
- }
- @Override
- public T getSwingWidget() {
- return this.widget;
- }
- }
- public class QPushButton extends QWidget<JButton> {
- public static final String CLICKED = "clicked";
- public QPushButton(String text) {
- super(JButton.class);
- widget.setText(text);
- widget.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- emit(CLICKED);
- }
- });
- }
- }
- public class QLineEdit extends QWidget<JTextField> {
- public static final String RETURN_PRESSED = "returnPressed";
- public QLineEdit() {
- super(JTextField.class);
- widget.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- emit(RETURN_PRESSED);
- }
- });
- }
- }
- public class AddressBar extends QWidget<JPanel> {
- /**
- * SIGNAL
- */
- public static final String NEW_BUTTON_CLICKED = "newButtonClicked";
- public static final String GO_TO_ADDRESS = "goToAddress(String,String)";
- /**
- * SLOT
- */
- public static final String HANDLE_GO_TO_ADDRESS = "handleGoToAddress()";
- private QPushButton newButton;
- private QLineEdit addressEdit;
- private QPushButton goButton;
- public AddressBar() {
- super(JPanel.class);
- // 1.Create widget
- newButton = new QPushButton("New");
- addressEdit = new QLineEdit();
- goButton = new QPushButton("Go");
- // 2.Set property
- addressEdit.getSwingWidget().setColumns(10);
- // 3.Connect signal-slot
- connect(newButton, QPushButton.CLICKED, this, NEW_BUTTON_CLICKED);
- connect(addressEdit, QLineEdit.RETURN_PRESSED, this, HANDLE_GO_TO_ADDRESS);
- connect(goButton, QPushButton.CLICKED, this, HANDLE_GO_TO_ADDRESS);
- // 4.Add to layout
- getSwingWidget().add(newButton.getSwingWidget());
- getSwingWidget().add(addressEdit.getSwingWidget());
- getSwingWidget().add(goButton.getSwingWidget());
- }
- public void handleGoToAddress() {
- emit(GO_TO_ADDRESS, addressEdit.getSwingWidget().getText(), "test string");
- }
- }
- public class TabBar extends JTabbedPane {
- /**
- * SLOT
- */
- public static final String HANDLE_NEW_TAB = "handleNewTab()";
- public static final String HANDLE_GO_TO_SITE = "goToSite(String,String)";
- public TabBar() {
- handleNewTab();
- }
- public void handleNewTab() {
- WebView tab = new WebView();
- add("blank", tab);
- }
- public void goToSite(String url, String testStr) {
- System.out.println("Receive url: " + url + ", " + testStr);
- WebView tab = (WebView) getSelectedComponent();
- tab.load(url);
- }
- }
- public class MainWindow extends JFrame {
- public static void main(String[] args) {
- JFrame window = new MainWindow();
- window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
- window.setSize(320, 340);
- window.setVisible(true);
- }
- public MainWindow() {
- // 1.Create widget
- AddressBar addressBar = new AddressBar();
- TabBar tabBar = new TabBar();
- // 2.Set property
- // 3.Connect signal-slot
- QObject.connect(addressBar, AddressBar.NEW_BUTTON_CLICKED, tabBar, TabBar.HANDLE_NEW_TAB);
- QObject.connect(addressBar, AddressBar.GO_TO_ADDRESS, tabBar, TabBar.HANDLE_GO_TO_SITE);
- // 4.Add to layout
- GridBagLayout layout = new GridBagLayout();
- setLayout(layout);
- GridBagConstraints grid = new GridBagConstraints();
- grid.fill = GridBagConstraints.BOTH;
- grid.gridx = grid.gridy = 0;
- grid.weightx = 1.0;
- grid.weighty = 0.1;
- add(addressBar.getSwingWidget(), grid);
- grid.fill = GridBagConstraints.BOTH;
- grid.gridx = 0;
- grid.gridy = 1;
- grid.weightx = 1.0;
- grid.weighty = 0.9;
- add(tabBar, grid);
- }
- }
- @SuppressWarnings("serial")
- class WebView extends JEditorPane {
- public WebView() {
- setEditable(false);
- }
- public void load(final String url) {
- SwingUtilities.invokeLater(new Runnable() {
- @Override
- public void run() {
- try {
- WebView.this.setPage(url);
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- });
- }
- }

http://blog.csdn.net/dc_726/article/details/7632430
Java实现Qt的SIGNAL-SLOT机制(保存到Map中,从而将它们关联起来,收到信号进行解析,最后反射调用)的更多相关文章
- kafka flumn sparkstreaming java实现监听文件夹内容保存到Phoenix中
ps:具体Kafka Flumn SparkStreaming的使用 参考前几篇博客 2.4.6.4.1 配置启动Kafka (1) 在slave机器上配置broker 1) 点击CDH上的kafk ...
- 【redis,1】java操作redis: 将string、list、map、自己定义的对象保存到redis中
一.操作string .list .map 对象 1.引入jar: jedis-2.1.0.jar 2.代码 /** * @param args */ public s ...
- Redis使用场景一,查询出的数据保存到Redis中,下次查询的时候直接从Redis中拿到数据。不用和数据库进行交互。
maven使用: <!--redis jar包--> <dependency> <groupId>redis.clients</groupId> < ...
- ffmpeg从AVFrame取出yuv数据到保存到char*中
ffmpeg从AVFrame取出yuv数据到保存到char*中 很多人一直不知道怎么利用ffmpeg从AVFrame取出yuv数据到保存到char*中,下面代码将yuv420p和yuv422p的数 ...
- 将数字n转换为字符串并保存到s中
将数字n转换为字符串并保存到s中 参考 C程序设计语言 #include <stdio.h> #include <string.h> //reverse函数: 倒置字符串s中各 ...
- Android把图片保存到SQLite中
1.bitmap保存到SQLite 中 数据格式:Blob db.execSQL("Create table " + TABLE_NAME + "( _id INTEGE ...
- c# 抓取和解析网页,并将table数据保存到datatable中(其他格式也可以,自己去修改)
使用HtmlAgilityPack 基础请参考这篇博客:https://www.cnblogs.com/fishyues/p/10232822.html 下面是根据抓取的页面string 来解析并保存 ...
- Flask实战第43天:把图片验证码和短信验证码保存到memcached中
前面我们已经获取到图片验证码和短信验证码,但是我们还没有把它们保存起来.同样的,我们和之前的邮箱验证码一样,保存到memcached中 编辑commom.vews.py .. from utils i ...
- 1.scrapy爬取的数据保存到es中
先建立es的mapping,也就是建立在es中建立一个空的Index,代码如下:执行后就会在es建lagou 这个index. from datetime import datetime fr ...
随机推荐
- 【p094】道路游戏
Time Limit: 1 second Memory Limit: 128 MB [问题描述] 小新正在玩一个简单的电脑游戏. 游戏中有一条环形马路,马路上有n个机器人工厂,两个相邻机器人工厂之间由 ...
- Linux-shell脚本-mysql一键安装
转自: https://blog.csdn.net/zmken497300/article/details/51615678 安装环境 CentOS-7-x86_64-DVD-1511.iso mys ...
- Android菜鸟的成长笔记(22)——Android进程间传递复杂数据(AIDL)
在上一篇中介绍了Andorid中的进程间的通信方式AIDL,本篇文章将介绍传递复杂数据的AIDL Service 下面通过一个示例说明: 本例子中用到了两个自定义类型:Person与Pet, 其中Pe ...
- 一个自己犯的react错误
在看<react小书>高阶组件一节的时候,看到如下代码 import React, { Component } from 'react' export default (WrappedCo ...
- Apache POI Word基本使用
Apache POI Word 1.什么是Apache POI? Apache POI是一个流行的API,使用Java程序创建,修改和显示MS-Office文件. 它是由Apache Software ...
- Linode跨节点迁移:从Tokyo到Fremont
背景 上一篇博客交代了如何在 Linode 上搭建邮件服务器,并配置好各种协议.记录来投入实际使用. 由于实践过程中,曾经尝试使用明文协议与服务器交流数据,可能泄露了账号.密码信息,造成之后被攻击发送 ...
- matlab 小波处理工具箱
1. wavedec:多尺度(multilevel)一维小波分解 [C,L] = wavedec(X,N,'wname') [C,L] = wavedec(X,N,Lo_D,Hi_D) 返回值 L(b ...
- Spring boot+RabbitMQ环境
Spring boot+RabbitMQ环境 消息队列在目前分布式系统下具备非常重要的地位,如下的场景是比较适合消息队列的: 跨系统的调用,异步性质的调用最佳. 高并发问题,利用队列串行特点. 订阅模 ...
- jQuery中的Deferred和promise
promise:http://www.alloyteam.com/2014/05/javascript-promise-mode/ 1 jQuery 中的 Deferred 和 Promises : ...
- python 两个链表的第一个公共结点
题目描述 输入两个链表,找出它们的第一个公共结点. 看到这道题的时候,很多人的第一反应就是采用蛮力的方法:在第一个链表上顺序遍历每个节点,每遍历到一个节点的时候,在第二个链表上顺序遍历每个节点.如 ...