-
Java微信二次开发之15-自定义菜单的类型
2016-09-06 15:47:22距离写上一篇文章《自定义菜单的创建及菜单事件响应》整整过了两个月的时间,那时公众平台还没有开放view类型的菜单。在不久前,微信公众平台悄悄开放了view类型... 用户点击view类型按钮后,会直接跳转到开发者指定的距离写上一篇文章《自定义菜单的创建及菜单事件响应》整整过了两个月的时间,那时公众平台还没有开放view类型的菜单。在不久前,微信公众平台悄悄开放了view类型的菜单,却没有在首页发布任何通知,貌似微信团队很喜欢这么干。一个偶然的机会,我留意到API文档的自定义菜单接口发生了变化,增加了对菜单view类型的说明:
view(访问网页):
用户点击view类型按钮后,会直接跳转到开发者指定的url中。
于是我在第一时间更新了小q机器人(微信号:xiaoqrobot)的菜单,在一级菜单“更多”下增加了二级菜单“使用帮助”,点击该菜单项会直接跳转到网页,如下图所示。
最近也有不少网友问起这种类型的菜单是如何创建的,本篇文章就为大家介绍下view类型的自定义菜单该如何创建。
自定义菜单的两种类型(click和view)
公众平台API文档中给出了自定义菜单的json结构示例,我从中截取两个菜单项的json代码,一个是click类型,另一个是view类型,如下所示。
- {
- "type":"click",
- "name":"今日歌曲",
- "key":"V1001_TODAY_MUSIC"
- },
- {
- "type":"view",
- "name":"歌手简介",
- "url":"http://www.qq.com/"
- }
建立view类型的菜单对象
View类型的菜单有3个属性:type、name和url。在上一篇文章中,我们创建了菜单项的基类Button,Button类只有一个属性name。View类型的菜单对象也需要继承Button类,代码如下:
- package org.liufeng.weixin.pojo;
- /**
- * view类型的菜单
- *
- * @author liuyq
- * @date 2013-04-10
- */
- public class ViewButton extends Button {
- private String type;
- private String url;
- public String getType() {
- return type;
- }
- public void setType(String type) {
- this.type = type;
- }
- public String getUrl() {
- return url;
- }
- public void setUrl(String url) {
- this.url = url;
- }
- }
创建带view类型的菜单示例
我们对前一篇文章中给出的菜单创建代码进行调整,增加view类型的菜单项,完整的菜单创建代码如下:
- package org.liufeng.weixin.main;
- import org.liufeng.weixin.pojo.AccessToken;
- import org.liufeng.weixin.pojo.Button;
- import org.liufeng.weixin.pojo.CommonButton;
- import org.liufeng.weixin.pojo.ComplexButton;
- import org.liufeng.weixin.pojo.Menu;
- import org.liufeng.weixin.pojo.ViewButton;
- import org.liufeng.weixin.util.WeixinUtil;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- /**
- * 菜单管理器类
- *
- * @author liufeng
- * @date 2013-08-08
- */
- public class MenuManager {
- private static Logger log = LoggerFactory.getLogger(MenuManager.class);
- public static void main(String[] args) {
- // 第三方用户唯一凭证
- String appId = "000000000000000000";
- // 第三方用户唯一凭证密钥
- String appSecret = "00000000000000000000000000000000";
- // 调用接口获取access_token
- AccessToken at = WeixinUtil.getAccessToken(appId, appSecret);
- if (null != at) {
- // 调用接口创建菜单
- int result = WeixinUtil.createMenu(getMenu(), at.getToken());
- // 判断菜单创建结果
- if (0 == result)
- log.info("菜单创建成功!");
- else
- log.info("菜单创建失败,错误码:" + result);
- }
- }
- /**
- * 组装菜单数据
- *
- * @return
- */
- private static Menu getMenu() {
- CommonButton btn11 = new CommonButton();
- btn11.setName("天气预报");
- btn11.setType("click");
- btn11.setKey("11");
- CommonButton btn12 = new CommonButton();
- btn12.setName("公交查询");
- btn12.setType("click");
- btn12.setKey("12");
- CommonButton btn13 = new CommonButton();
- btn13.setName("周边搜索");
- btn13.setType("click");
- btn13.setKey("13");
- CommonButton btn14 = new CommonButton();
- btn14.setName("历史上的今天");
- btn14.setType("click");
- btn14.setKey("14");
- CommonButton btn15 = new CommonButton();
- btn15.setName("电影排行榜");
- btn15.setType("click");
- btn15.setKey("32");
- CommonButton btn21 = new CommonButton();
- btn21.setName("歌曲点播");
- btn21.setType("click");
- btn21.setKey("21");
- CommonButton btn22 = new CommonButton();
- btn22.setName("经典游戏");
- btn22.setType("click");
- btn22.setKey("22");
- CommonButton btn23 = new CommonButton();
- btn23.setName("美女电台");
- btn23.setType("click");
- btn23.setKey("23");
- CommonButton btn24 = new CommonButton();
- btn24.setName("人脸识别");
- btn24.setType("click");
- btn24.setKey("24");
- CommonButton btn25 = new CommonButton();
- btn25.setName("聊天唠嗑");
- btn25.setType("click");
- btn25.setKey("25");
- CommonButton btn31 = new CommonButton();
- btn31.setName("Q友圈");
- btn31.setType("click");
- btn31.setKey("31");
- CommonButton btn33 = new CommonButton();
- btn33.setName("幽默笑话");
- btn33.setType("click");
- btn33.setKey("33");
- CommonButton btn34 = new CommonButton();
- btn34.setName("用户反馈");
- btn34.setType("click");
- btn34.setKey("34");
- CommonButton btn35 = new CommonButton();
- btn35.setName("关于我们");
- btn35.setType("click");
- btn35.setKey("35");
- ViewButton btn32 = new ViewButton();
- btn32.setName("使用帮助");
- btn32.setType("view");
- btn32.setUrl("http://liufeng.gotoip2.com/xiaoqrobot/help.jsp");
- ComplexButton mainBtn1 = new ComplexButton();
- mainBtn1.setName("生活助手");
- mainBtn1.setSub_button(new Button[] { btn11, btn12, btn13, btn14, btn15 });
- ComplexButton mainBtn2 = new ComplexButton();
- mainBtn2.setName("休闲驿站");
- mainBtn2.setSub_button(new Button[] { btn21, btn22, btn23, btn24, btn25 });
- ComplexButton mainBtn3 = new ComplexButton();
- mainBtn3.setName("更多");
- mainBtn3.setSub_button(new Button[] { btn31, btn33, btn34, btn35, btn32 });
- /**
- * 这是公众号xiaoqrobot目前的菜单结构,每个一级菜单都有二级菜单项<br>
- *
- * 在某个一级菜单下没有二级菜单的情况,menu该如何定义呢?<br>
- * 比如,第三个一级菜单项不是“更多体验”,而直接是“幽默笑话”,那么menu应该这样定义:<br>
- * menu.setButton(new Button[] { mainBtn1, mainBtn2, btn33 });
- */
- Menu menu = new Menu();
- menu.setButton(new Button[] { mainBtn1, mainBtn2, mainBtn3 });
- return menu;
- }
- }
119~122行代码就是用于创建view类型菜单项的。上面的菜单结构也是小q机器人(微信号:xiaoqrobot)目前在使用的,读者可以对照着理解。
补充:居然还有些网友问我上面的自定义菜单创建代码在哪里调用,问我为什么不把调用的代码也公开?搞的我都有点不好意思了。上面的菜单创建代码是写在main方法中,直接在开发工具中运行一下就可以了,这应该是最最基础的Java知识了。另外,菜单只要创建一次,会一直存在的,不需要每次启动应用程序都去创建菜单。当然,你也可以把菜单的创建代码集成到项目中,并非一定要放在main方法中。程序是死的,人是活的,解决方法往往有很多种,怎么方便实用就怎么来!
-
Java微信公众平台开发之自定义菜单
2018-10-08 09:04:27一、自定义菜单的说明和按钮类型 1、菜单说明 1)自定义菜单最多包括3个一级菜单,每个一级菜单最多包含5个二级菜单。 2)一级菜单最多4个汉字,二级菜单最多7个汉字,多出来的部分将会以“...”代替。 3)创建...一、自定义菜单的说明和按钮类型
1、菜单说明
1)自定义菜单最多包括3个一级菜单,每个一级菜单最多包含5个二级菜单。
2)一级菜单最多4个汉字,二级菜单最多7个汉字,多出来的部分将会以“...”代替。
3)创建自定义菜单后,菜单的刷新策略是,在用户进入公众号会话页或公众号profile页时,如果发现上一次拉取菜单的请求在5分钟以前,就会拉取一下菜单,如果菜单有更新,就会刷新客户端的菜单。测试时可以尝试取消关注公众账号后再次关注,则可以看到创建后的效果。
2、自定义菜单接口可实现多种类型按钮
1)click:点击推事件用户点击click类型按钮后,微信服务器会通过消息接口推送消息类型为event的结构给开发者(参考消息接口指南),并且带上按钮中开发者填写的key值,开发者可以通过自定义的key值与用户进行交互;
2)view:跳转URL用户点击view类型按钮后,微信客户端将会打开开发者在按钮中填写的网页URL,可与网页授权获取用户基本信息接口结合,获得用户基本信息。
3)scancode_push:扫码推事件用户点击按钮后,微信客户端将调起扫一扫工具,完成扫码操作后显示扫描结果(如果是URL,将进入URL),且会将扫码的结果传给开发者,开发者可以下发消息。
4)scancode_waitmsg:扫码推事件且弹出“消息接收中”提示框用户点击按钮后,微信客户端将调起扫一扫工具,完成扫码操作后,将扫码的结果传给开发者,同时收起扫一扫工具,然后弹出“消息接收中”提示框,随后可能会收到开发者下发的消息。
5)pic_sysphoto:弹出系统拍照发图用户点击按钮后,微信客户端将调起系统相机,完成拍照操作后,会将拍摄的相片发送给开发者,并推送事件给开发者,同时收起系统相机,随后可能会收到开发者下发的消息。
6)pic_photo_or_album:弹出拍照或者相册发图用户点击按钮后,微信客户端将弹出选择器供用户选择“拍照”或者“从手机相册选择”。用户选择后即走其他两种流程。
7)pic_weixin:弹出微信相册发图器用户点击按钮后,微信客户端将调起微信相册,完成选择操作后,将选择的相片发送给开发者的服务器,并推送事件给开发者,同时收起相册,随后可能会收到开发者下发的消息。
8)location_select:弹出地理位置选择器用户点击按钮后,微信客户端将调起地理位置选择工具,完成选择操作后,将选择的地理位置发送给开发者的服务器,同时收起位置选择工具,随后可能会收到开发者下发的消息。
9)media_id:下发消息(除文本消息)用户点击media_id类型按钮后,微信服务器会将开发者填写的永久素材id对应的素材下发给用户,永久素材类型可以是图片、音频、视频、图文消息。请注意:永久素材id必须是在“素材管理/新增永久素材”接口上传后获得的合法id。
10)view_limited:跳转图文消息URL用户点击view_limited类型按钮后,微信客户端将打开开发者在按钮中填写的永久素材id对应的图文消息URL,永久素材类型只支持图文消息。请注意:永久素材id必须是在“素材管理/新增永久素材”接口上传后获得的合法id。说明:3到8的所有事件,仅支持微信iPhone5.4.1以上版本,和Android5.4以上版本的微信用户,旧版本微信用户点击后将没有回应,开发者也不能正常接收到事件推送。9和10,是专门给第三方平台旗下未微信认证(具体而言,是资质认证未通过)的订阅号准备的事件类型,它们是没有事件推送的,能力相对受限,其他类型的公众号不必使用。
二、菜单的创建/查询/删除
官方的click和view事件demo
-
{
-
"button":[
-
{
-
"type":"click",
-
"name":"今日歌曲",
-
"key":"V1001_TODAY_MUSIC"
-
},
-
{
-
"name":"菜单",
-
"sub_button":[
-
{
-
"type":"view",
-
"name":"搜索",
-
"url":"http://www.soso.com/"
-
},
-
{
-
"type":"miniprogram",
-
"name":"wxa",
-
"url":"http://mp.weixin.qq.com",
-
"appid":"wx286b93c14bbf93aa",
-
"pagepath":"pages/lunar/index"
-
},
-
{
-
"type":"click",
-
"name":"赞一下我们",
-
"key":"V1001_GOOD"
-
}]
-
}]
-
}
其他类型(包括9、10)
-
{
-
"button": [
-
{
-
"name": "扫码",
-
"sub_button": [
-
{
-
"type": "scancode_waitmsg",
-
"name": "扫码带提示",
-
"key": "rselfmenu_0_0",
-
"sub_button": [ ]
-
},
-
{
-
"type": "scancode_push",
-
"name": "扫码推事件",
-
"key": "rselfmenu_0_1",
-
"sub_button": [ ]
-
}
-
]
-
},
-
{
-
"name": "发图",
-
"sub_button": [
-
{
-
"type": "pic_sysphoto",
-
"name": "系统拍照发图",
-
"key": "rselfmenu_1_0",
-
"sub_button": [ ]
-
},
-
{
-
"type": "pic_photo_or_album",
-
"name": "拍照或者相册发图",
-
"key": "rselfmenu_1_1",
-
"sub_button": [ ]
-
},
-
{
-
"type": "pic_weixin",
-
"name": "微信相册发图",
-
"key": "rselfmenu_1_2",
-
"sub_button": [ ]
-
}
-
]
-
},
-
{
-
"name": "发送位置",
-
"type": "location_select",
-
"key": "rselfmenu_2_0"
-
},
-
{
-
"type": "media_id",
-
"name": "图片",
-
"media_id": "MEDIA_ID1"
-
},
-
{
-
"type": "view_limited",
-
"name": "图文消息",
-
"media_id": "MEDIA_ID2"
-
}
-
]
-
}
1、根据实例开始封装实体类
菜单按钮基类BasicButton.java
-
public class BasicButton {
-
private String name;
-
public String getName() {
-
return name;
-
}
-
public void setName(String name) {
-
this.name = name;
-
}
-
}
菜单Menu.java
-
public class Menu {
-
public final static String CLICK = "click"; // click菜单
-
public final static String VIEW = "view"; // url菜单
-
public final static String SCANCODE_WAITMSG = "scancode_waitmsg"; // 扫码带提示
-
public final static String SCANCODE_PUSH = "scancode_push"; // 扫码推事件
-
public final static String PIC_SYSPHOTO = "pic_sysphoto"; // 系统拍照发图
-
public final static String PIC_PHOTO_OR_ALBUM = "pic_photo_or_album"; // 拍照或者相册发图
-
public final static String PIC_WEIXIN = "pic_weixin"; // 微信相册发图
-
public final static String LOCATION_SELECT = "location_select"; // 发送位置
-
private BasicButton[] button;
-
public BasicButton[] getButton() {
-
return button;
-
}
-
public void setButton(BasicButton[] button) {
-
this.button = button;
-
}
-
}
view类型按钮类ViewButton.java,其他的类型可以照此一一封装
-
public class ViewButton extends BasicButton {
-
private String type = Menu.VIEW;
-
private String url;
-
public String getType() {
-
return type;
-
}
-
public void setType(String type) {
-
this.type = type;
-
}
-
public String getUrl() {
-
return url;
-
}
-
public void setUrl(String url) {
-
this.url = url;
-
}
-
}
一级菜单包含二级菜单的封装ComplexMenu.java
-
public class ComplexMenu extends BasicButton {
-
private BasicButton[] sub_button;
-
public BasicButton[] getSub_button() {
-
return sub_button;
-
}
-
public void setSub_button(BasicButton[] sub_button) {
-
this.sub_button = sub_button;
-
}
-
}
2.封装完毕,组装菜单
-
private static Menu getMenu() {
-
ViewButton btn11 = new ViewButton();
-
btn11.setName("测试11");
-
btn11.setUrl("http://www.qq.com");
-
ClickButton btn21 = new ClickButton();
-
btn21.setName("测试21");
-
btn21.setKey("21");
-
ClickButton btn22 = new ClickButton();
-
btn22.setName("测试22");
-
btn22.setKey("22");
-
//一级菜单(没有二级菜单)
-
ComplexMenu mainBtn1 = new ComplexMenu();
-
mainBtn1.setName("测试1");
-
mainBtn1.setSub_button(new BasicButton[] { btn11});
-
//一级菜单(有二级菜单)
-
ComplexMenu mainBtn2 = new ComplexMenu();
-
mainBtn2.setName("测试2");
-
mainBtn2.setSub_button(new BasicButton[] { btn21, btn22 });
-
Menu menu = new Menu();
-
menu.setButton(new BasicButton[] { mainBtn1, mainBtn2 });
-
return menu;
-
}
3.自定义菜单的创建
-
/**
-
* 创建的菜单
-
*
-
* @param menu 菜单项
-
* @param token 授权token
-
* @return {"errcode":0,"errmsg":"ok"}
-
*/
-
public ResultState createMenu(Menu menu, String token) {
-
TreeMap<String, String> map = new TreeMap<String, String>();
-
map.put("access_token", token);
-
String jsonData = JsonUtil.toJson(menu).toString();
-
String result = HttpReqUtil.HttpsDefaultExecute(HttpReqUtil.POST_METHOD, WechatConfig.MENU_CREATE_URL, map, jsonData);
-
return JsonUtil.fromJson(result, ResultState.class);
-
}
4、自定义菜单的查询
返回的实例
-
对应创建接口,正确的Json返回结果:
-
{
-
"menu": {
-
"button": [
-
{
-
"type": "click",
-
"name": "今日歌曲",
-
"key": "V1001_TODAY_MUSIC",
-
"sub_button": [ ]
-
},
-
{
-
"type": "click",
-
"name": "歌手简介",
-
"key": "V1001_TODAY_SINGER",
-
"sub_button": [ ]
-
},
-
{
-
"name": "菜单",
-
"sub_button": [
-
{
-
"type": "view",
-
"name": "搜索",
-
"url": "http://www.soso.com/",
-
"sub_button": [ ]
-
},
-
{
-
"type": "view",
-
"name": "视频",
-
"url": "http://v.qq.com/",
-
"sub_button": [ ]
-
},
-
{
-
"type": "click",
-
"name": "赞一下我们",
-
"key": "V1001_GOOD",
-
"sub_button": [ ]
-
}
-
]
-
}
-
]
-
}
-
}
-
/**
-
* 获取自定义菜单
-
*
-
* @param token
-
* @return
-
*/
-
public String getMenu(String token) {
-
TreeMap<String, String> map = new TreeMap<String, String>();
-
map.put("access_token", token);
-
String result = HttpReqUtil.HttpsDefaultExecute(HttpReqUtil.GET_METHOD, WechatConfig.MENU_GET_URL, map, "");
-
return result;
-
}
菜单所有属性MenuAttr.java
-
/**
-
* 菜单所有属性
-
* @author phil
-
*
-
*/
-
public class MenuAttr extends BasicMenu {
-
private String type;
-
private String url;
-
private String key;
-
private String sub_button;
-
get/set方法
-
}
返回的菜单类MenuReturn.java
-
/**
-
* 返回的菜单类
-
* @author phil
-
*
-
*/
-
public class MenuReturn extends BasicMenu{
-
private MenuAttr[] sub_button;
-
public MenuAttr[] getSub_button() {
-
return sub_button;
-
}
-
public void setSub_button(MenuAttr[] subButton) {
-
sub_button = subButton;
-
}
-
}
将json格式的字符串转换为Menu对象
-
/**
-
* 将json格式的字符串转换为Menu对象
-
* @param json
-
* @return
-
*/
-
public List<MenuReturn> converMenu(String json) {
-
List<MenuReturn> list = new ArrayList<MenuReturn>();
-
if (json!= null && !"".equals(json)) {
-
JSONObject object = JSONObject.parseObject(json);
-
JSONArray array = object.getJSONObject("menu").getJSONArray("button");
-
for (int i = 0; i < array.size(); i++) {
-
MenuReturn mr= new MenuReturn();
-
mr= array.getObject(i, MenuReturn.class);
-
list.add(mr);
-
}
-
}
-
return list;
-
}
注:此处用的fastjson
此处方法待改进,有更好的请指教一二
5、自定义菜单的删除
-
/**
-
* 删除自定义菜单
-
*
-
* @param token
-
* @return
-
*/
-
public boolean deleteMenu(String token) {
-
boolean falg = true;
-
TreeMap<String, String> map = new TreeMap<String, String>();
-
map.put("access_token", token);
-
String result = HttpReqUtil.HttpsDefaultExecute(HttpReqUtil.GET_METHOD, WechatConfig.MENU_DELTE_URL, map, "");
-
ResultState state = JsonUtil.fromJson(result, ResultState.class);
-
if (state.getErrcode()!= 0|| state.getErrmsg() != "ok") {
-
falg = false;
-
}
-
return falg;
-
}
三、自定义菜单事件推送
用户点击自定义菜单后,微信会把点击事件推送给开发者,请注意,点击菜单弹出子菜单,不会产生上报。请注意,第3个到第8个的所有事件,仅支持微信iPhone5.4.1以上版本,和Android5.4以上版本的微信用户,旧版本微信用户点击后将没有回应,开发者也不能正常接收到事件推送。
1、解析微信推送的xml数据包
-
/**
-
* 解析微信发来的请求(XML)
-
* xml示例
-
* <xml>
-
<ToUserName><![CDATA[toUser]]></ToUserName>
-
<FromUserName><![CDATA[FromUser]]></FromUserName>
-
<CreateTime>123456789</CreateTime>
-
<MsgType><![CDATA[event]]></MsgType>
-
<Event><![CDATA[CLICK]]></Event>
-
<EventKey><![CDATA[EVENTKEY]]></EventKey>
-
</xml>
-
* @param request
-
* @return
-
* @throws Exception
-
*/
-
public static Map<String, String> parseXml(HttpServletRequest request) throws Exception {
-
// 将解析结果存储在HashMap中
-
Map<String, String> map = new HashMap<String, String>();
-
// 从request中取得输入流
-
InputStream inputStream = request.getInputStream();
-
// 读取输入流
-
SAXReader reader = new SAXReader();
-
Document document = reader.read(inputStream);
-
// 得到xml根元素
-
Element root = document.getRootElement();
-
// 得到根元素的所有子节点
-
List<Element> elementList = root.elements();
-
// 遍历所有子节点
-
for (Element e : elementList)
-
map.put(e.getName(), e.getText());
-
// 释放资源
-
inputStream.close();
-
inputStream = null;
-
return map;
-
}
2、利用map的get(key)获取value
MsgType 消息类型,event
Event 事件类型,CLICK
EventKey 事件KEY值,与自定义菜单接口中KEY值对应注:key是参数名
附:WechatConfig.java
-
// 创建菜单
-
public static final String MENU_CREATE_URL = "https://api.weixin.qq.com/cgi-bin/menu/create";
-
// 查询自定义菜单
-
public static final String MENU_GET_URL = "https://api.weixin.qq.com/cgi-bin/menu/get";
-
// 删除自定义菜单
-
public static final String MENU_DELTE_URL = "https://api.weixin.qq.com/cgi-bin/menu/delete";
-
-
微信公众号Java开发记录(四)自定义菜单、识别图片消息文字
2020-10-13 23:02:29自定义菜单接口可实现多种类型按钮,如下: click:点击推事件用户点击click类型按钮后,微信服务器会通过消息接口推送消息类型为event的结构给开发者(参考消息接口指南),并且带上按钮中开发者填写的key值,...自定义菜单接口可实现多种类型按钮,如下:
click:点击推事件用户点击click类型按钮后,微信服务器会通过消息接口推送消息类型为event的结构给开发者(参考消息接口指南),并且带上按钮中开发者填写的key值,开发者可以通过自定义的key值与用户进行交互;
view:跳转URL用户点击view类型按钮后,微信客户端将会打开开发者在按钮中填写的网页URL,可与网页授权获取用户基本信息接口结合,获得用户基本信息。
scancode_push:扫码推事件用户点击按钮后,微信客户端将调起扫一扫工具,完成扫码操作后显示扫描结果(如果是URL,将进入URL),且会将扫码的结果传给开发者,开发者可以下发消息。
scancode_waitmsg:扫码推事件且弹出“消息接收中”提示框用户点击按钮后,微信客户端将调起扫一扫工具,完成扫码操作后,将扫码的结果传给开发者,同时收起扫一扫工具,然后弹出“消息接收中”提示框,随后可能会收到开发者下发的消息。
pic_sysphoto:弹出系统拍照发图用户点击按钮后,微信客户端将调起系统相机,完成拍照操作后,会将拍摄的相片发送给开发者,并推送事件给开发者,同时收起系统相机,随后可能会收到开发者下发的消息。
pic_photo_or_album:弹出拍照或者相册发图用户点击按钮后,微信客户端将弹出选择器供用户选择“拍照”或者“从手机相册选择”。用户选择后即走其他两种流程。
pic_weixin:弹出微信相册发图器用户点击按钮后,微信客户端将调起微信相册,完成选择操作后,将选择的相片发送给开发者的服务器,并推送事件给开发者,同时收起相册,随后可能会收到开发者下发的消息。
location_select:弹出地理位置选择器用户点击按钮后,微信客户端将调起地理位置选择工具,完成选择操作后,将选择的地理位置发送给开发者的服务器,同时收起位置选择工具,随后可能会收到开发者下发的消息。
media_id:下发消息(除文本消息)用户点击media_id类型按钮后,微信服务器会将开发者填写的永久素材id对应的素材下发给用户,永久素材类型可以是图片、音频、视频、图文消息。请注意:永久素材id必须是在“素材管理/新增永久素材”接口上传后获得的合法id。
view_limited:跳转图文消息URL用户点击view_limited类型按钮后,微信客户端将打开开发者在按钮中填写的永久素材id对应的图文消息URL,永久素材类型只支持图文消息。请注意:永久素材id必须是在“素材管理/新增永久素材”接口上传后获得的合法id。一、自定义菜单
接口调用请求说明
http请求方式:POST(请使用https协议) https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN
click和view的请求示例
{
“button”:[
{
“type”:“click”,
“name”:“今日歌曲”,
“key”:“V1001_TODAY_MUSIC”
},
{
“name”:“菜单”,
“sub_button”:[
{
“type”:“view”,
“name”:“搜索”,
“url”:“http://www.soso.com/”
},
{
“type”:“miniprogram”,
“name”:“wxa”,
“url”:“http://mp.weixin.qq.com”,
“appid”:“wx286b93c14bbf93aa”,
“pagepath”:“pages/lunar/index”
},
{
“type”:“click”,
“name”:“赞一下我们”,
“key”:“V1001_GOOD”
}]
}]
}使用对象封装,通过JSONObject.fromObject(button)我们直接将对象转化成josn。
@Data public class Button { private List<AbstractButton> button = new ArrayList<>(); } @Data public class AbstractButton { private String name; public AbstractButton(String name){ this.name = name; } }
注意
使用JSONObject jsonObject = JSONObject.fromObject(button);
方法需要导入依赖,并不是阿里巴巴的fastjson的方法。<!-- https://mvnrepository.com/artifact/net.sf.json-lib/json-lib --> <dependency> <groupId>net.sf.json-lib</groupId> <artifactId>json-lib</artifactId> <version>2.4</version> <classifier>jdk15</classifier> </dependency>
将AbstractButton类修改为抽象类,其他按钮继承它即可。@Data public abstract class AbstractButton { private String name; public AbstractButton(String name){ this.name = name; } }
新建按钮对象
@Data public class ClickButten extends AbstractButton { private String type = "click"; private String key; public ClickButten(String name,String key){ super(name); this.key = key; } } @Data public class ViewButton extends AbstractButton { private String type = "view"; private String url; public ViewButton(String name,String url){ super(name); this.url=url; } } package com.wx.model.button; import lombok.Data; import java.util.ArrayList; import java.util.List; /** * @author :LiuShihao * @date :Created in 2020/10/10 10:52 上午 * @desc : * { * "name": "发图", * "sub_button": [ * { * "type": "pic_sysphoto", * "name": "系统拍照发图", * "key": "rselfmenu_1_0", * "sub_button": [ ] * }, * { * "type": "pic_photo_or_album", * "name": "拍照或者相册发图", * "key": "rselfmenu_1_1", * "sub_button": [ ] * }, * { * "type": "pic_weixin", * "name": "微信相册发图", * "key": "rselfmenu_1_2", * "sub_button": [ ] * } * ] * } */ @Data public class PhotoAlbumButton extends AbstractButton { private String type; private String key; private List<AbstractButton> sub_button = new ArrayList<>(); public PhotoAlbumButton(String name,String type,String key){ super(name); this.key = key; this.type = type; } } @Data public class SubButton extends AbstractButton { private List<AbstractButton> sub_button = new ArrayList<>(); public SubButton(String name ){ super(name); } }
将对象解析成Json
@Test public void test2(){ Button button = new Button(); button.getButton().add(new ClickButten("一级菜单_点击","1")); button.getButton().add(new ViewButton("一级跳转","http://baidu.com")); SubButton subButton = new SubButton("子菜单"); subButton.getSub_button().add(new PhotoAlbumButton("系统拍照发图","pic_sysphoto","rselfmenu_1_0")); subButton.getSub_button().add(new ClickButten("二级菜单_点击","2")); subButton.getSub_button().add(new ViewButton("二级跳转","http://news.163.com")); button.getButton().add(subButton); JSONObject jsonObject = JSONObject.fromObject(button); System.out.println(jsonObject); } {"button":[{"key":"1","name":"一级菜单_点击","type":"click"},{"name":"一级跳转","type":"view","url":"http://baidu.com"},{"name":"子菜单","sub_button":[{"key":"rselfmenu_1_0","name":"系统拍照发图","sub_button":[],"type":"pic_sysphoto"},{"key":"2","name":"二级菜单_点击","type":"click"},{"name":"二级跳转","type":"view","url":"http://news.163.com"}]}]} { "button":[ { "key":"1", "name":"一级菜单_点击", "type":"click" }, { "name":"一级跳转", "type":"view", "url":"http://baidu.com" }, { "name":"子菜单", "sub_button":[ { "key":"rselfmenu_1_0", "name":"系统拍照发图", "sub_button":[ ], "type":"pic_sysphoto" }, { "key":"2", "name":"二级菜单_点击", "type":"click" }, { "name":"二级跳转", "type":"view", "url":"http://news.163.com" } ] } ] }
二、创建自定义菜单
package com.wx.util; import com.wx.model.button.*; import com.wx.service.Impl.WXServiceImpl; import net.sf.json.JSONObject; import org.springframework.beans.factory.annotation.Autowired; /** * @author :LiuShihao * @date :Created in 2020/10/10 12:32 下午 * @desc : */ public class CreateMenu { @Autowired WXServiceImpl wxService; public static void main(String[] args) { Button button = new Button(); button.getButton().add(new ClickButten("一级菜单_点击","1")); button.getButton().add(new ViewButton("一级跳转","http://baidu.com")); SubButton subButton = new SubButton("子菜单"); subButton.getSub_button().add(new PhotoAlbumButton("系统拍照发图","pic_sysphoto","rselfmenu_1_0")); subButton.getSub_button().add(new ClickButten("二级菜单_点击","2")); subButton.getSub_button().add(new ViewButton("二级跳转","http://news.163.com")); button.getButton().add(subButton); JSONObject jsonObject = JSONObject.fromObject(button); System.out.println(jsonObject); String url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN"; String token = WXServiceImpl.getToken(); url = url.replace("ACCESS_TOKEN",token); com.alibaba.fastjson.JSONObject post = CommonUtil.httpsRequest(url, "POST", jsonObject.toString()); System.out.println("post:"+post); } }
处理图片信息(识别图片文字)调用百度AI开放平台的API
当用户发送一个图片时,会发送到微信服务器,我们服务器接收的微信服务器发送过来的xml数据包,进行解析
/** * 处理消息和事件推送 * @param request * @throws IOException */ @PostMapping public String method2(HttpServletRequest request) throws IOException { Map<String,String> map = wxService.parseRequest(request.getInputStream()); System.out.println("处理消息和事件推送:"+map); return wxService.getRespose(map); }
将xml数据包解析成map形式
/** * 使用dom4j包 解析xml数据包 成Map形式 * @param inputStream * @return */ @Override public Map<String, String> parseRequest(ServletInputStream inputStream) { HashMap<String, String> hashMap = new HashMap<>(); SAXReader reader = new SAXReader(); try { //读取输入流 回去文档对象 Document document = reader.read(inputStream); //根据文档对象 回去根节点 Element rootElement = document.getRootElement(); //根据根节点获取所有的子节点 List<Element> elements = rootElement.elements(); for (Element element : elements) { hashMap.put(element.getName(), element.getStringValue()); } } catch (DocumentException e) { e.printStackTrace(); } return hashMap; }
然后对不同的消息类型进行相应的处理:
/** * 用于处理所有的事件和消息de 回复 * 将Map解析成xml数据包 回复消息 * @param map * @return 返回的是xml数据包 */ @Override public String getRespose(Map<String, String> map) { String msgType = map.get("MsgType"); BaseMessage msg = null; switch (msgType){ case "text": msg = dealText(map); break; case "image": msg = dealImage(map); break; case "voice": msg = dealVoice(map); break; case "video": break; case "shortvideo": break; case "location": break; case "link": break; case "event": msg = dealEvent(map); break; default: break; } if (msg != null){ String xml = beanToXml(msg); System.out.println(xml); log.info(xml); return xml; }else { return "success"; } }
msgType
类型如果为image,就调用百度API;/** * 处理图片消息 * @param map * @return */ private BaseMessage dealImage(Map<String, String> map) { String url = map.get("PicUrl"); String toText = bdUtil.imageToText(url); return new TextMessage(map,toText); }
package com.wx.util; import com.baidu.aip.ocr.AipOcr; import com.wx.model.weather.*; import lombok.extern.slf4j.Slf4j; import net.sf.json.JSONArray; import net.sf.json.JSONObject; import org.json.JSONException; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; import java.util.HashMap; import java.util.Iterator; import java.util.List; /** * @author :LiuShihao * @date :Created in 2020/10/10 3:24 下午 * @desc : */ @Slf4j @Component public class BDUtil { //你的对应信息 public static final String APP_ID = "228****23"; public static final String API_KEY = "2D0gCVQP***********gGdjgUCs"; public static final String SECRET_KEY = "UXL0pNYD***********ZO357kmXBa"; public static AipOcr client; static { // 初始化一个AipOcr client = new AipOcr(APP_ID, API_KEY, SECRET_KEY); } /** * 识别 图片 文字 * @param picUrl * @return * @throws JSONException */ public String imageToText(String picUrl) throws JSONException { String totext = null; // 传入可选参数调用接口 HashMap<String, String> options = new HashMap<String, String>(); options.put("language_type", "CHN_ENG"); options.put("detect_direction", "true"); options.put("detect_language", "true"); options.put("probability", "true"); // // 参数为本地路径 // String image = "test.jpg"; // JSONObject res = client.basicGeneral(image, options); // System.out.println(res.toString(2)); // // // 参数为二进制数组 // byte[] file = readFile("test.jpg"); // res = client.basicGeneral(file, options); // System.out.println(res.toString(2)); // 通用文字识别, 图片参数为远程url图片 org.json.JSONObject res = client.basicGeneralUrl(picUrl, options); /** * 返回成功: * { * "words_result": [{ * "probability": { * "average": 0.950565, * "min": 0.74773, * "variance": 0.005733 * }, * "words": "该公众号提供的服务出现故障,请稍后再试" * }], * "log_id": 1314882863493021696, * "words_result_num": 1, * "language": 3, * "direction": 0 * } * * 返回失败: * */ System.out.println(res.toString(2)); String s = res.toString(2); //将 字符创 转化成 JSONObject package net.sf.json; JSONObject jsonObject = JSONObject.fromObject(s); System.out.println("jsonObject:"+jsonObject); try{ String error_code = jsonObject.getString("error_code"); if(!StringUtils.isEmpty(error_code)){ if ("216202".equals(error_code)){ totext = "上传的图片大小错误,现阶段我们支持的图片大小为:base64编码后小于4M,分辨率不高于4096*4096,请重新上传图片"; } if ("216201".equals(error_code)){ totext = "上传的图片格式错误,现阶段我们支持的图片格式为:PNG、JPG、JPEG、BMP,请进行转码或更换图片"; } } }catch (net.sf.json.JSONException e){ e.printStackTrace(); JSONArray words_result = jsonObject.getJSONArray("words_result"); StringBuilder stringBuilder = new StringBuilder(); Iterator it = words_result.iterator(); while (it.hasNext()){ JSONObject next = (JSONObject)it.next(); stringBuilder.append(next.getString("words")); } log.info("imageToText:"+stringBuilder); totext= stringBuilder.toString(); } return totext; } }
打开百度AI开放平台网站,选择文字识别服务,如果没有应用,创建一个应用
删除菜单
使用接口创建自定义菜单后,开发者还可使用接口删除当前使用的自定义菜单。另请注意,在个性化菜单时,调用此接口会删除默认菜单及全部个性化菜单。
请求说明
http请求方式:GET https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=ACCESS_TOKEN
返回说明
对应创建接口,正确的Json返回结果:
{“errcode”:0,“errmsg”:“ok”}
package com.wx.util; import com.wx.model.button.*; import com.wx.service.Impl.WXServiceImpl; import net.sf.json.JSONObject; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; /** * @author :LiuShihao * @date :Created in 2020/10/10 12:32 下午 * @desc : */ @Component public class CreateMenu { @Autowired WXServiceImpl wxService; public static void main(String[] args) { } public void createMenu(){ Button button = new Button(); button.getButton().add(new ClickButten("一级菜单_点击","1")); button.getButton().add(new ViewButton("一级跳转","http://baidu.com")); SubButton subButton = new SubButton("子菜单"); subButton.getSub_button().add(new PhotoAlbumButton("拍照或者相册发图","pic_photo_or_album","rselfmenu_1_0")); subButton.getSub_button().add(new ClickButten("二级菜单_点击","2")); subButton.getSub_button().add(new ViewButton("二级跳转","http://news.163.com")); subButton.getSub_button().add(new ViewButton("我的博客","http://116.62.13.104:8090/")); subButton.getSub_button().add(new ViewButton("我的网盘","http://116.62.13.104:8081/")); button.getButton().add(subButton); JSONObject jsonObject = JSONObject.fromObject(button); System.out.println(jsonObject); String url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN"; String token = WXServiceImpl.getToken(); url = url.replace("ACCESS_TOKEN",token); com.alibaba.fastjson.JSONObject post = CommonUtil.httpsRequest(url, "POST", jsonObject.toString()); System.out.println("post:"+post); } /** * http请求方式:GET https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=ACCESS_TOKEN */ public void delMenu(){ String url = "https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=ACCESS_TOKEN"; String token = wxService.getRedisToken(); url = url.replace("ACCESS_TOKEN",token); com.alibaba.fastjson.JSONObject post = CommonUtil.httpsRequest(url, "GET", null); System.out.println("post:"+post); } /** * http请求方式: GET(请使用https协议)https://api.weixin.qq.com/cgi-bin/get_current_selfmenu_info?access_token=ACCESS_TOKEN */ public void findMenu(){ String url = "https://api.weixin.qq.com/cgi-bin/get_current_selfmenu_info?access_token=ACCESS_TOKEN"; String token = wxService.getRedisToken(); url = url.replace("ACCESS_TOKEN",token); com.alibaba.fastjson.JSONObject post = CommonUtil.httpsRequest(url, "GET", null); System.out.println("post:"+post); } } @Test public void test3(){ // menu.delMenu(); menu.createMenu(); menu.findMenu(); }
-
JAVA微信公众号开发之自定义菜单
2017-07-27 23:20:31微信上文档说明: 1、click:点击推事件用户点击click类型按钮后...2、view:跳转URL用户点击view类型按钮后,微信客户端将会打开开发者在按钮中填写的网页URL,可与网页授权获取用户基本信息接口结合,获得用户...微信上文档说明:
1、click:点击推事件用户点击click类型按钮后,微信服务器会通过消息接口推送消息类型为event的结构给开发者(参考消息接口指南),并且带上按钮中开发者填写的key值,开发者可以通过自定义的key值与用户进行交互; 2、view:跳转URL用户点击view类型按钮后,微信客户端将会打开开发者在按钮中填写的网页URL,可与网页授权获取用户基本信息接口结合,获得用户基本信息。 3、scancode_push:扫码推事件用户点击按钮后,微信客户端将调起扫一扫工具,完成扫码操作后显示扫描结果(如果是URL,将进入URL),且会将扫码的结果传给开发者,开发者可以下发消息。 4、scancode_waitmsg:扫码推事件且弹出“消息接收中”提示框用户点击按钮后,微信客户端将调起扫一扫工具,完成扫码操作后,将扫码的结果传给开发者,同时收起扫一扫工具,然后弹出“消息接收中”提示框,随后可能会收到开发者下发的消息。 5、pic_sysphoto:弹出系统拍照发图用户点击按钮后,微信客户端将调起系统相机,完成拍照操作后,会将拍摄的相片发送给开发者,并推送事件给开发者,同时收起系统相机,随后可能会收到开发者下发的消息。 6、pic_photo_or_album:弹出拍照或者相册发图用户点击按钮后,微信客户端将弹出选择器供用户选择“拍照”或者“从手机相册选择”。用户选择后即走其他两种流程。 7、pic_weixin:弹出微信相册发图器用户点击按钮后,微信客户端将调起微信相册,完成选择操作后,将选择的相片发送给开发者的服务器,并推送事件给开发者,同时收起相册,随后可能会收到开发者下发的消息。 8、location_select:弹出地理位置选择器用户点击按钮后,微信客户端将调起地理位置选择工具,完成选择操作后,将选择的地理位置发送给开发者的服务器,同时收起位置选择工具,随后可能会收到开发者下发的消息。 9、media_id:下发消息(除文本消息)用户点击media_id类型按钮后,微信服务器会将开发者填写的永久素材id对应的素材下发给用户,永久素材类型可以是图片、音频、视频、图文消息。请注意:永久素材id必须是在“素材管理/新增永久素材”接口上传后获得的合法id。 10、view_limited:跳转图文消息URL用户点击view_limited类型按钮后,微信客户端将打开开发者在按钮中填写的永久素材id对应的图文消息URL,永久素材类型只支持图文消息。请注意:永久素材id必须是在“素材管理/新增永久素材”接口上传后获得的合法id。
请注意,3到8的所有事件,仅支持微信iPhone5.4.1以上版本,和Android5.4以上版本的微信用户,旧版本微信用户点击后将没有回应,开发者也不能正常接收到事件推送。9和10,是专门给第三方平台旗下未微信认证(具体而言,是资质认证未通过)的订阅号准备的事件类型,它们是没有事件推送的,能力相对受限,其他类型的公众号不必使用。
接口调用请求说明
http请求方式:POST(请使用https协议) https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN
然后是自定义菜单的构造与参数:
{ "button":[ { "type":"click", "name":"今日歌曲", "key":"V1001_TODAY_MUSIC" }, { "name":"菜单", "sub_button":[ { "type":"view", "name":"搜索", "url":"http://www.soso.com/" }, { "type":"miniprogram", "name":"wxa", "url":"http://mp.weixin.qq.com", "appid":"wx286b93c14bbf93aa", "pagepath":"pages/lunar/index" }, { "type":"click", "name":"赞一下我们", "key":"V1001_GOOD" }] }] }
button 是 一级菜单数组,个数应为1~3个 sub_button 否 二级菜单数组,个数应为1~5个 type 是 菜单的响应动作类型,view表示网页类型,click表示点击类型,miniprogram表示小程序类型 name 是 菜单标题,不超过16个字节,子菜单不超过60个字节 key click等点击类型必须 菜单KEY值,用于消息接口推送,不超过128字节 url view、miniprogram类型必须 网页链接,用户点击菜单可打开链接,不超过1024字节。type为miniprogram时,不支持小程序的老版本客户端将打开本url。 media_id media_id类型和view_limited类型必须 调用新增永久素材接口返回的合法media_id appid miniprogram类型必须 小程序的appid(仅认证公众号可配置) pagepath
miniprogram类型必须 小程序的页面路径 1、首先组装实体类,创建主菜单与子菜单属性。这个就不介绍了,很简单。
组装完一个菜单后然后创建菜单。
public static int createMenu(String menu) throws ClientProtocolException, IOException{ int result=0; String access_token = GetMapSign.getTicket().get("access_token");//获取access_token String url = ConfigUtil.MENU_CREATE_URL.replace("ACCESS_TOKEN",access_token); JSONObject jsonObject = doPostStr(url, menu); if(jsonObject!=null){ result = jsonObject.getInt("errcode"); } return result; }
/** * post请求 */ public static JSONObject doPostStr(String url,String outStr){ DefaultHttpClient httpClient = new DefaultHttpClient(); HttpPost httpPost = new HttpPost(url); JSONObject jsonObject = null; String result=""; try { httpPost.setEntity(new StringEntity(outStr,"utf-8")); HttpResponse response = httpClient.execute(httpPost); result = EntityUtils.toString(response.getEntity(),"utf-8"); } catch (Exception e) { } jsonObject = JSONObject.fromObject(result); return jsonObject; }
然后创建一个测试类,直接运行就好了,这里成功后errcode会返回0,发布后微信公众号就不用管了,以后一直就是这样了,以后想改的时候再改再运行就好了。public static void main(String[] args) throws Exception { //创建自定义菜单 String menu = JSONObject.fromObject(SignUtil.initMenu()).toString(); int result = SignUtil.createMenu(menu); if(result==0){ System.out.println("菜单创建成功!"); }else{ System.out.println("菜单创建失败!"); }
}
最近在整理一些资源工具,放在网站分享 http://tools.maqway.com
欢迎关注公众号:麻雀唯伊 , 不定时更新资源文章,生活优惠,或许有你想看的 -
Java 微信公众平台开发(四)——自定义菜单的实现
2018-08-24 17:34:26菜单实际上就是按钮,自定义菜单接口可实现多种类型按钮: 1.click:点击推事件用户点击click类型按钮后,微信服务器会通过消息接口推送消息类型为event的结构给开发者(参考消息接口指南),并且带上按钮中开发者... -
Java事件类型小结
2015-09-19 19:30:19ActionEvent动作事件类ActionListener接口 actionPerformed(ActionEvent e)单击按钮、选择菜单项或在文本框中按回车时 AdjustmentEvent调整事件类AdjustmentListener接口 adjustmentValueChanged(AdjustmentEvent e... -
微信自定义菜单的创建(JAVA版)
2015-10-09 11:39:26微信自定义菜单的创建与使用微信自定义菜单的创建与使用 需求 菜单类介绍 场景 代码 总结需求当微信公众号设置...由于新版微信添加的挺多按钮类型,目前只实现click(点击推事件)和view(跳转URL),其他类型的大致相同。 -
微信开发之自定义菜单--weixin-java-tools
2016-06-11 14:46:001、click:点击推事件用户点击click类型按钮后,微信服务器会通过消息接口推送消息类型为event的结构给开发者(参考消息接口指南),并且带上按钮中开发者填写的key值,开发者可以通过自定义的key值与用户进行... -
使用Java语言开发微信公众平台(八)——自定义菜单功能
2018-12-26 15:42:40一、了解自定义菜单 自定义菜单是微信公众平台最常用也是最重要... 而自定义菜单可以实现的功能也是多种多样的,根据实现功能的不同,微信自定义菜单按钮共分为10种类型: 请注意,3到8的所有事件,仅支持... -
java引用类型有啥_再谈Python的引用和变量
2021-01-05 23:07:22引用观察代码框下方的布局,可以看到两个按钮之下还有三个下拉菜单,依次点击之后本酱发现了一个神奇的选项:render all objects on the heap (Python/Java)。即图中红框处下拉菜单的第三个选项:这个... -
第六篇 :微信公众平台开发实战Java版之如何自定义微信公众号菜单
2017-07-11 11:15:35用户点击click类型按钮后,微信服务器会通过消息接口推送消息类型为event 的结构给开发者(参考消息接口指南),并且带上按钮中开发者填写的key值,开发者可以通过自定义的key值与用户进行交互; 2、view:跳转URL ... -
TNWX-微信公众号自定义菜单
2019-05-05 23:59:55文章目录简介接口权限编辑模式开发模式TNW 中具体实现读取配置文件来创建菜单动态创建自定义菜单Java 版本自定义菜单开源推荐 简介 TNW: TypeScript(The) + Node.js...菜单规则以及按钮类型说明 实现自定义菜单有... -
java界面编程(5) ------ 按钮和按钮组
2014-11-16 00:31:37了解了布局管理器和Swing事件模型,那么剩下的就是Swing 的各个组件了,下面就开始逐个学习Swing的各个组件的用法及功能,本节... Swing提供了许多类型的按钮,有普通的按钮,复选框,单选等按钮,甚至菜单项,所 -
java 按钮组_java编程接口(5) ------ button和button组
2021-02-12 17:49:32了解了布局管理器和Swing事件模型,...1. buttonSwing提供了很多类型的button,有普通的button,复选框,单选等button,甚至菜单项,全部的这些button都是从AbstractButton继承而来。例如以下图的继承关系:能够看... -
Swing 菜单JMenu
2012-08-19 21:25:25Swing菜单和菜单项是按钮,因为JMenuItem扩展AbstractButton,JMenu扩展JMenuItem。因此,Swing菜单和菜单项继承了如下功能,即包含文本和(或)图标、显示光标进入时的图标和助记符等。 JMenuItem和JMenu的父... -
java源码包---java 源码 大量 实例
2013-04-18 23:15:26Java右键弹出菜单源码 简单 Java圆形按钮实例代码,含注释 两个目标文件,自绘button。 Java圆形电子时钟源代码 1个目标文件 内容索引:JAVA源码,系统相关,电子钟 用JAVA编写的指针式圆形电子钟,效果图如下所示... -
Servlet--微信自定义菜单
2017-03-11 18:25:49有三种类型的按钮:click类、复合类、view类 - 由上面对Json文件的分析,我们可以用Java类的方式来封装,因为类是具有相同特性和行为的对象的集合,Json文件实际上需要很小心才可以写得好,所以为了简化操作,就... -
java源码包
2015-12-01 16:29:37Java右键弹出菜单源码 简单 Java圆形按钮实例代码,含注释 两个目标文件,自绘button。 Java圆形电子时钟源代码 1个目标文件 内容索引:JAVA源码,系统相关,电子钟 用JAVA编写的指针式圆形电子钟,效果图如下所示... -
java源码包2
2013-04-20 11:28:17Java右键弹出菜单源码 简单 Java圆形按钮实例代码,含注释 两个目标文件,自绘button。 Java圆形电子时钟源代码 1个目标文件 内容索引:JAVA源码,系统相关,电子钟 用JAVA编写的指针式圆形电子钟,效果图如下... -
java源码包3
2013-04-20 11:30:13Java右键弹出菜单源码 简单 Java圆形按钮实例代码,含注释 两个目标文件,自绘button。 Java圆形电子时钟源代码 1个目标文件 内容索引:JAVA源码,系统相关,电子钟 用JAVA编写的指针式圆形电子钟,效果图如下... -
用Java开发微信公众号
2017-03-08 11:21:20也就是说,你开发后台接口按照微信规定的格式提供数据,不管你点菜单上哪个按钮,微信会调用你提供的唯一接口并告诉你是哪个按钮调的接口,你根据按钮类型返回数据,微信就会自动处理并显示你返回的数据。... -
Java Web中表单数据的获取
2016-05-12 19:28:30分为单一表单数据和捆绑表单数据,其中单一表单数据是指表单元素的值送给服务器端时,仅仅是一个变量,这种类型的表单元素主要有:文本框、密码框、多行文本框、多选按钮、下拉菜单等,对于捆绑表单就是指多个同名... -
按钮(Button)
2013-08-31 17:45:03Swing提供了许多类型的按钮。所有的按钮,包括检查框,单选按钮,甚至菜单项都是从 AbstractButton(因为包含了菜单项,所以将其命名为“AbstractSelector” 或者其它 概括的名字,似乎更恰当一些)继承而来。... -
疯狂JAVA讲义
2014-10-17 13:35:01学生提问:图11.15和图11.16显示的所有按钮都紧挨在一起,如果希望像FlowLayout、GridLayout等布局管理器指定组件的间距该怎么办? 397 11.4 AWT 常用组件 398 11.4.1 基本组件 398 11.4.2 对话框 400 11.5 事件... -
Java典型模块
2012-02-25 18:27:40第1篇 Java开发必备基础 第1章 搭建Java开发环境 1.1 Java的过去、现在和未来 1.1.1 Java的历史 1.1.2 Java的语言特点 1.1.3 Java API简介 1.1.4 Java未来发展 1.2 Java程序设计环境 1.2.1 命令行工具——JDK 6.0 ... -
Java2游戏编程.pdf
2013-01-31 15:20:462.2.7 Java数据类型、数组和标识符需要记忆的要点 2.3 Java中的运算符 2.3.1 赋值运算符 2.3.2 比较运算符 2.3.3 算术运算符 2.3.4 自增和自减运算符 2.3.5 更多的整数运算符 2.3.6 使用点运算符 2.3.7 instanceof... -
Java代码实例
2016-06-21 22:44:51第2章 基本数据类型——构建Java 大厦的基础 12 2.1 源代码注释 12 2.1.1 单行注释 12 2.1.2 区域注释 12 2.1.3 文档注释 13 2.2 基本数据类型 14 2.2.1 整型 15 2.2.2 浮点型 17 2.2.3 char型 17... -
Java开发详解.zip
2019-09-02 17:46:13010301_【第3章:Java基础程序设计】_Java数据类型笔记.pdf 010302_【第3章:Java基础程序设计】_运算符、表达式与语句笔记.pdf 010303_【第3章:Java基础程序设计】_判断与循环语句笔记.pdf 010401_【第4章:数组与... -
Java开发技术大全(500个源代码).
2012-12-02 19:55:48代码范例列表 第1章 示例描述:本章演示如何开始使用JDK进行程序的开发。 HelloWorldApp.java 第一个用Java开发的应用程序。 firstApplet.java 第一个用... demoForceChange.java 演示强制类型转换 demoGeneric.java ...
-
access应用的3个开发实例
-
MySQL NDB Cluster 负载均衡和高可用集群
-
华为机试题之字符串分隔
-
华为1+X——网络系统建设与运维(高级)
-
Web前端开发规范手册.rar
-
OC.Gen-X.2.9.2.dmg
-
使用vue搭建微信H5公众号项目
-
RxJava3.0.0 操作符篇 - 转换操作符
-
【正点原子】I.MX6U网络环境TFTP&NFS搭建手册V1.2.pdf
-
佳能打印机G2800不需要软件的清零方法.txt
-
FTP 文件传输服务
-
Algorithm_BaekJoon:백준리즘제문-源码
-
视频转换器WonderFox便携注册版 UI界面好看.rar
-
朱老师C++课程第3部分-3.6智能指针与STL查漏补缺
-
质量保证书-源码
-
【考研初试】安徽建筑大学702公共管理学考研真题库资料
-
参数列表 是调用方给予方法的参数用于方法内的使用
-
ELF视频教程
-
MySQL 基础篇 一【常用命令&语法规范】
-
ROSE-HA-V8.9+Win2008+SQL2008双机配置详细指南(图文).pdf