既然有javafx scene builderr,是否没有必要自己写javafx代码

JavaFX入门:简单Demo-学习NetBeans开发平台 - 简书
JavaFX入门:简单Demo-学习NetBeans开发平台
JavaFX入门参考,高优质资料:
版权所有,转载注明。
零、 最终目标
通过两种方式(纯代码控制、FXML),实现一个简单的登录界面:
Paste_Image.png
涉及到的控件:
文本(Text,动态显示内容)、标签(Label,显示文本)、文本域(TextField,用户交互输入)、按钮(Button,登录点击)
一、 控件通过Code动态添加实现方法
1、 新建项目
新建JavaFXLoginDemo项目,具体新建方法参见前篇:
完成项目新建后,进入开发正题。
入口参数:
public class JavaFXLoginDemo extends Application {
public void start(Stage primaryStage) {
* @param args the command line arguments
public static void main(String[] args) {
launch(args);
2、 布局方式
JavaFX的UI控件均摆放在Scene上,一般通过增加控制布局的Panel,并将实际的UI摆放在布局Panel上,有点类似于Android的布局方式。Panel有多种样式,包括了行、列、栈等等,如BorderPane、GridPane、Hbox、VBox等等。
本文将使用GridPane进行布局。
GridPane grid = new GridPane();//网格式布局,由行列网格控制
grid.setAlignment(Pos.CENTER);//对齐方式,默认靠左对齐,当前设置居中对齐
grid.setHgap(10);//设置水平间隔
grid.setVgap(10);//设置垂直间隔
grid.setPadding(new Insets(25, 25, 25, 25));//设置Padding,顺序是:上、右、下、左
Scene scene = new Scene(grid, 300, 275);//新建Scene,并将网格式Panel置于其中
primaryStage.setScene(scene);//设置场景
primaryStage.show();
3、 添加控件
Text scenetitle = new Text("欢迎标题");
//scenetitle.setFont(Font.font("Times New Roman", FontWeight.NORMAL, 20));
grid.add(scenetitle, 0, 0, 2, 1);
//创建Label对象,放到第0列,第1行
Label userName = new Label("用户名:");
grid.add(userName, 0, 1);
//创建文本输入框,放到第1列,第1行
TextField userTextField = new TextField();
grid.add(userTextField, 1, 1);
Label pw = new Label("密 码:");
grid.add(pw, 0, 2);
PasswordField pwBox = new PasswordField();
grid.add(pwBox, 1, 2);
Button btn = new Button("登录");
HBox hbBtn = new HBox(10);
hbBtn.setAlignment(Pos.BOTTOM_RIGHT);
hbBtn.getChildren().add(btn);//将按钮控件作为子节点
grid.add(hbBtn, 1, 4);//将HBox pane放到grid中的第1列,第4行
final Text actiontarget = new Text();//增加用于显示信息的文本
grid.add(actiontarget, 1, 6);
4、 添加处理事件
只有一个按钮需要事件处理:
btn.setOnAction(new EventHandler&ActionEvent&() {//注册事件handler
public void handle(ActionEvent e) {
actiontarget.setFill(Color.FIREBRICK);//将文字颜色变成 firebrick red
actiontarget.setText("登录中...");
5、 添加样式CSS
步骤一:新建CSS文件:
在包上右击:
Paste_Image.png
Paste_Image.png
输入文件名Login.css,完成样式表文件的创建:
Paste_Image.png
样式表中定义的内容,主要用在控件的样式控制上,需要在UI中应用。样式表需要应用到Root容器中:
scene.getStylesheets().add(JavaFXLoginDemo.class.getResource("Login.css").toExternalForm());
设置后,将会在JavaFXLoginDemo.class相对路径下寻找给出的样式表Login.css,并应用到scene中。
步骤二:添加一张背景图,到当前包路径下:
Paste_Image.png
步骤三:添加CSS样式控制
//根元素样式布局,设置背景图
-fx-background-image: url("background.jpg");
//标签控件样式
-fx-font-size: 12
-fx-font-weight:
-fx-text-fill: #333333;
-fx-effect: dropshadow( gaussian , rgba(255,255,255,0.5) , 0,0,0,1 );
//给Button增加样式
-fx-text-fill:
-fx-font-family: "Arial Narrow";
-fx-font-weight:
-fx-background-color: linear-gradient(#61a2b1, #2A5058);
-fx-effect: dropshadow( three-pass-box , rgba(0,0,0,0.6) , 5, 0.0 , 0 , 1 );
.button:hover {
-fx-background-color: linear-gradient(#2A5058, #61a2b1);
//增加文本效果
#welcome-text {
-fx-font-size: 32
-fx-fill: #818181;
-fx-effect: innershadow( three-pass-box , rgba(0,0,0,0.7) , 6, 0.0 , 0 , 2 );
//登录点击事件显示效果
#actiontarget {
-fx-fill: FIREBRICK;
-fx-font-weight:
-fx-effect: dropshadow( gaussian , rgba(255,255,255,0.5) , 0,0,0,1 );
注意,最后两个是采用了CSS中的ID控制样式,而非Label、Button中针对类型设置的样式,因此需要给目标控件增加ID规则:
scenetitle.setId("welcome-text");
actiontarget.setId("actiontarget");
☆☆☆ 中文字体库应用
任何事情,涉及到了中文之后,字体库使用有点麻烦。
(1)新建文件夹,在当前包下建立resources/fonts,如图所示:
Paste_Image.png
将字体库粘贴进去,一般是ttf文件,Windows常用,Mac可以用,Linux也是兼容的。我粘贴的是微软雅黑和粗体版,在Windows操作系统的系统盘下Windows/Fonts目录下。
(2)增加fonts.mf文件
使用“文件”选项卡查看工程:
Paste_Image.png
fonts.mf内容:
msyh=/javafxlogindemo/resources/fonts/msyh.ttf
msyhbd=/javafxlogindemo/resources/fonts/msyhbd.ttf
hwxk=/javafxlogindemo/resources/fonts/STXINGKA.TTF
hwcy=/javafxlogindemo/resources/fonts/STCAIYUN.TTF
Paste_Image.png
Paste_Image.png
"="前面,是项目使用时的字体名称,即font-family,后面是字体库文件的路径。
(3)fonts.mf需要在打包时放到jar包的META-INF目录下,因此需要配置NetBeans工程的build.xml文件内容:
NetBeans工程使用Ant管理项目,配置的build.xml文件,根文件在工程根目录下,具体配置文件在nbproject目录下的build-impl.xml文件中。
在build.xml中增加如下内容:
&target name="-post-compile"&
&mkdir dir="${build.classes.dir}/META-INF"/&
&copy todir="${build.classes.dir}/META-INF" file="fonts.mf"/&
完成之后,运行一下项目,在项目目录的dist目录下,可以看到打包的jar包,用压缩文件查看器打开(WinRAR):
Paste_Image.png
Paste_Image.png
包含了配置文件和字体库文件。
(4)code中使用:
import javafx.scene.text.F
Font font = Font.font("hwcy", 32);//字体,尺寸,注意不能使用加粗,即FontWeight
Paste_Image.png
(5)在CSS样式文件中使用:
//增加文本效果
#welcome-text {
-fx-font-size: 32
-fx-font-family: "hwcy";
-fx-fill: #818181;
-fx-effect: innershadow( three-pass-box , rgba(0,0,0,0.7) , 6, 0.0 , 0 , 2 );
注意,-fx-font-weight:加粗不能一起使用,会使字体失效。
经过上述的配置,中文字体也能够轻松走起啦。
6、 完成编码,启动项目,运行测试。
二、 FXML实现界面
NetBeans实现方法
1、 新建工程JavaFXLoginFXMLDemo:
与前一种方法新的工程种类稍有区别,这里选择JavaFX FXML应用程序
Paste_Image.png
Paste_Image.png
对比一下工程结构,FXML工程多了一些FXML文件和控制器文件:
Paste_Image.png
新建工程后,立刻运行:
Paste_Image.png
代码也稍有区别,FXML文件中定义了控件和控制器映射关系等等:
&?xml version="1.0" encoding="UTF-8"?&
&?import java.lang.*?&
&?import java.util.*?&
&?import javafx.scene.*?&
&?import javafx.scene.control.*?&
&?import javafx.scene.layout.*?&
&AnchorPane id="AnchorPane" prefHeight="200" prefWidth="320" xmlns:fx="http://javafx.com/fxml/1" fx:controller="javafxloginfxmldemo.FXMLDocumentController"&
&children&
&Button layoutX="126" layoutY="90" text="Click Me!" onAction="#handleButtonAction" fx:id="button" /&
&Label layoutX="126" layoutY="120" minHeight="16" minWidth="69" fx:id="label" /&
&/children&
&/AnchorPane&
默认生成的FXML样例界面文件中,根容器是一个AnchorPane:
AnchorPane布局面板可锚定节点于面板的顶、底、左边、右边或中间。当窗口尺寸调整时,相应节点维护它们相对于锚点的位置。节点可被锚定于多个位置,多个节点也可锚定于同一个位置。
在后面,将要修改实际的布局容器。
控制器Controller定义了事件处理方法:
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
import java.net.URL;
import java.util.ResourceB
import javafx.event.ActionE
import javafx.fxml.FXML;
import javafx.fxml.I
import javafx.scene.control.L
* @author guorui.he
public class FXMLDocumentController implements Initializable {
private void handleButtonAction(ActionEvent event) {
System.out.println("You clicked me!");
label.setText("Hello World!");
public void initialize(URL url, ResourceBundle rb) {
主文件内,与之前的纯代码实现基本类似,但是加载页面的机制稍有不同,这时通过FXML文件加载,搞过Android的人很熟悉:
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
import javafx.application.A
import javafx.fxml.FXMLL
import javafx.scene.P
import javafx.scene.S
import javafx.stage.S
* @author guorui.he
public class JavaFXLoginFXMLDemo extends Application {
public void start(Stage stage) throws Exception {
//通过fxml的UI布局文件加载实际的界面内容
Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
* @param args the command line arguments
public static void main(String[] args) {
launch(args);
由于默认文件名定义的比较弱,我们要自己改一下文件名,这样才能更清晰的展示:
Paste_Image.png
注意不要忘记修改控制器和FXML的映射,以及主类加载的FXML界面名称。
2、在FXML文件中,编写界面内容:
&?xml version="1.0" encoding="UTF-8"?&
//整理引入包
&?import java.net.*?&
&?import javafx.geometry.*?&
&?import javafx.scene.control.*?&
&?import javafx.scene.layout.*?&
&?import javafx.scene.text.*?&
//编写界面
&GridPane xmlns:fx="http://javafx.com/fxml"
fx:controller="javafxloginfxmldemo.FXMLLoginDemoDocumentController"
alignment="center" hgap="10" vgap="10"&
&Insets top="25" right="25" bottom="10" left="25"/&
&/padding&
&Text text="欢迎登录FXML Demo系统"
GridPane.columnIndex="0" GridPane.rowIndex="0"
GridPane.columnSpan="2"/&
&Label text="用户名:"
GridPane.columnIndex="0" GridPane.rowIndex="1"/&
&TextField
GridPane.columnIndex="1" GridPane.rowIndex="1"/&
&Label text="密
GridPane.columnIndex="0" GridPane.rowIndex="2"/&
&PasswordField fx:id="passwordField"
GridPane.columnIndex="1" GridPane.rowIndex="2"/&
&HBox spacing="10" alignment="bottom_right"
GridPane.columnIndex="1" GridPane.rowIndex="4"&
&Button text="登录" /&
&Text fx:id="actiontarget"
GridPane.columnIndex="0" GridPane.columnSpan="2"
GridPane.halignment="RIGHT" GridPane.rowIndex="6"/&
&/GridPane&
此时,没有添加事件处理,可以试运行:
Paste_Image.png
大致内容都在了,但是没有样式,没有登录按钮点击处理事件。
3、 添加处理事件:
方法一:使用Java处理
//给Button增加一个事件处理
&Button text="登录" onAction="#handleSubmitButtonAction"/&
添加之后,会报错:
Paste_Image.png
需要在控制器中为其添加事件处理:
Paste_Image.png
会自动的在控制器内添加处理程序:
import java.net.URL;
import java.util.ResourceB
import javafx.event.ActionE
import javafx.fxml.FXML;
import javafx.fxml.I
import javafx.scene.control.L
import javafx.scene.control.PasswordF
import javafx.scene.text.T
* @author guorui.he
public class FXMLLoginDemoDocumentController implements Initializable {
private PasswordField passwordF
public void initialize(URL url, ResourceBundle rb) {
private void handleSubmitButtonAction(ActionEvent event) {
actiontarget.setText("登录中...");
@FXML注解,可以删除,最好保留,阅读方便。
添加好处理事件后,点击登录按钮,就会有反应了:
Paste_Image.png
方法二.1:使用内置JS脚本处理
&?xml version="1.0" encoding="UTF-8"?&
&?language javascript?&
添加脚本声明。
修改Button的事件处理方法(局部代码):
&GridPane xmlns:fx="http://javafx.com/fxml"
fx:controller="javafxloginfxmldemo.FXMLLoginDemoDocumentController"
alignment="center" hgap="10" vgap="10"&
&!-- 脚本处理代码 --&
&fx:script&
function handleSubmitButtonAction() {
actiontarget.setText("Calling the JavaScript");
&/fx:script&
&HBox spacing="10" alignment="bottom_right"
GridPane.columnIndex="1" GridPane.rowIndex="4"&
&Button text="登录" onAction="handleSubmitButtonAction(event);"/&
&Text fx:id="actiontarget"
GridPane.columnIndex="0" GridPane.columnSpan="2"
GridPane.halignment="RIGHT" GridPane.rowIndex="6"/&
&/GridPane&
点击之后,调用脚本:
Paste_Image.png
脚本语言提供与JSR 223规范兼容的引擎即可。例如JavaScript、Groovy、Jython、Clojure。
方法二.2:使用外置JS脚本处理
脚本可以放在外部,正确引用即可:
Paste_Image.png
Paste_Image.png
Paste_Image.png
function handleSubmitButtonAction() {
actiontarget.setText("Calling the Outline JavaScript");
同时,在FXML中引入脚本:
&GridPane xmlns:fx="http://javafx.com/fxml"
fx:controller="javafxloginfxmldemo.FXMLLoginDemoDocumentController"
alignment="center" hgap="10" vgap="10"&
&fx:script source="FXMLJSLoginDemo.js"/&
&HBox spacing="10" alignment="bottom_right"
GridPane.columnIndex="1" GridPane.rowIndex="4"&
&Button text="登录" onAction="handleSubmitButtonAction(event);"/&
&Text fx:id="actiontarget"
GridPane.columnIndex="0" GridPane.columnSpan="2"
GridPane.halignment="RIGHT" GridPane.rowIndex="6"/&
&/GridPane&
试运行,得到结果:
Paste_Image.png
4、 添加样式控制:
添加样式表文件、字体库文件、背景图片,增加fonts.mf配置文件,修改build.xml等等,与前面纯代码开发基本一致,注意路径名(包名有变化)。
在FXML中引入样式表,并给特定的控件增加id,以便于CSS样式筛选器能够正确筛选适配:
&GridPane xmlns:fx="http://javafx.com/fxml"
fx:controller="javafxloginfxmldemo.FXMLLoginDemoDocumentController"
alignment="center" hgap="10" vgap="10"
styleClass="root" &
&stylesheets&
&URL value="@Login.css" /&
&/stylesheets&
&Text id="welcome-text" text="欢迎登录FXML Demo系统"
GridPane.columnIndex="0" GridPane.rowIndex="0"
GridPane.columnSpan="2"/&
&Text id="actiontarget" fx:id="actiontarget"
GridPane.columnIndex="0" GridPane.columnSpan="2"
GridPane.halignment="RIGHT" GridPane.rowIndex="6"/&
&/GridPane&
5、 最终运行结果:
Paste_Image.png
FXML方式开发界面完成。
JavaFX Scene Builder 2.0协助开发
下载完成,一路安装,开始运行:
Paste_Image.png
非常简单的一个界面,就是做做界面……
配置一下:
Paste_Image.png
Paste_Image.png
选择JavaFX Scene Builder安装主目录,即可。
然后,双击或者右击打开FXML,则会自动使用SB编辑器打开。
NetBeans是JavaFX的一个开发工具,比较好用。
除此之外,e(fx)clipse也是一个不错的JavaFX开发工具,有时间可以适当查下资料,看看如何使用。
程序猿,移动客户端开发。关注各类开发技术和思想。
CSS 绝对底部 - 前端 - 掘金来自国外的设计达人,纯CSS,可以实现: 当正文内容很少时,底部位于窗口最下面。当改变窗口高度时,不会出现重叠问题。甚至,创造该CSS的人还专门成立一个网站介绍这个CSS底部布局方案。不知道他有没有去申请专利:)&!DOCTYPE htm...
Ubuntu的发音 Ubuntu,源于非洲祖鲁人和科萨人的语言,发作 oo-boon-too 的音。了解发音是有意义的,您不是第一个为此困惑的人,当然,也不会是最后一个:)大多数的美国人读 ubuntu 时,将 u 作为元音发音,类似单词 who 或者 boo ,重音在第二...
用到的组件1、通过CocoaPods安装项目名称项目信息AFNetworking网络请求组件FMDB本地数据库组件SDWebImage多个缩略图缓存组件UICKeyChainStore存放用户账号密码组件Reachability监测网络状态DateTools友好化时间MBP...
发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注
09:45字数 61697阅读 3316评论 2喜欢 85 用到的组件 1、通过CocoaPods安装 项目名称 项目信息 AFNetworking 网络请求组件 FM...
星星之队徐逸翔打卡《黄花梨棋盘》第31天。
今天听了李华老师的讲解《黄花梨棋盘》这本书。 妈妈:那他在讲解的时候有没有什么惊喜呢?
我:这次,李华老师给我们带来了一个大惊喜!她请来了《黄花梨棋盘》这本书的作者——雏凡凡。惊不惊喜,意不意外?
研究所的胡椒园是一个充满智慧,充满特点,充满故事的园子。 01 园子不大,里面却间种了好几种农作物:胡椒、槟榔、花梨、粽子叶、鸡屎藤、地瓜,一年四季,和谐共生,沐浴阳光。胡椒需要精心侍候,其它的基本放养,但都能带来一定的经济效益,充分用好用足了每一寸土地。 园子原来是一片竹...
——记5.21行动派大夫山森林公园骑行活动 公元日上午十时,这可能是本世纪既北京申奥,金融危机,特朗普上台……之后又一历史性时刻。因为在这一天,一群有趣的灵魂终于相聚,一些面纱将被掀开,一些种子将会萌芽,一些故事将会发生…… 以骑行的名义,来见你 5.21...
愿我执迷不悟时,少受些伤,愿我幡然醒悟时,依旧安好。 剽悍晨读:变身社交高手,让你心想事成 今天分享三个沟通技巧,简单实用,有助于我们进行有效社交。 001 「听众档案」 在我们开始社交之前,先思考以下几个问题,也就是「听众档案」的建立。 第一、沟通的对象是谁?
今天偶然看了一本名为〈Magic Letter〉的英语绘本故事,觉得很有小创意。 故事主要是要教给小朋友关于四季的单词和描述。分别有Winter,SSpring,WSummer,Hot 和Fall, Windy。就这么些个单词和描述,大家会用什么样的方式教授...网站已改版,请使用新地址访问:
javafx_scenebuilder_samples-2_0-ea-b12-3 Applet 238万源代码下载- www.pudn.com
&文件名称: javafx_scenebuilder_samples-2_0-ea-b12-30_jan_201
& & & & &&]
&&所属分类:
&&开发工具: Java
&&文件大小: 283 KB
&&上传时间:
&&下载次数: 0
&&提 供 者:
&详细说明:JavaFX Scene Builder sampler
文件列表(点击判断是否您需要的文件,如果是垃圾请在下面评价投诉):
&&HelloI18N&&.........\nbproject&&.........\.........\configs&&.........\src&&.........\...\helloi18n&&IssueTrackingLite&&.................\nbproject&&.................\.........\configs&&.................\src&&.................\...\issuetrackinglite&&.................\...\.................\model&&Login&&.....\nbproject&&.....\.........\configs&&.....\src&&.....\...\login&&.....\...\.....\model&&.....\...\.....\security&&UnlockCustom&&............\nbproject&&............\.........\configs&&............\src&&............\...\unlock&&UnlockInclude&&.............\nbproject&&.............\.........\configs&&.............\src&&.............\...\unlock&&HelloI18N\build.xml&&.........\manifest.mf&&.........\nbproject\build-impl.xml&&.........\.........\configs\Run_as_WebStart.properties&&.........\.........\.......\Run_in_Browser.properties&&.........\.........\jfx-impl.xml&&.........\.........\project.properties&&.........\.........\project.xml&&.........\src\helloi18n\Bundle.properties&&.........\...\.........\Bundle_fr_FR.properties&&.........\...\.........\HelloI18N.fxml&&.........\...\.........\HelloI18NController.java&&.........\...\.........\Main.java&&IssueTrackingLite\build.xml&&.................\manifest.mf&&.................\nbproject\build-impl.xml&&.................\.........\configs\Run_as_WebStart.properties&&.................\.........\.......\Run_in_Browser.properties&&.................\.........\jfx-impl.xml&&.................\.........\project.properties&&.................\.........\project.xml&&.................\src\issuetrackinglite\IssueTrackingLite.css&&.................\...\.................\IssueTrackingLite.fxml&&.................\...\.................\IssueTrackingLite.png&&.................\...\.................\IssueTrackingLiteController.java&&.................\...\.................\Main.java&&.................\...\.................\model\Issue.java&&.................\...\.................\.....\ObservableIssue.java&&.................\...\.................\.....\TrackingService.java&&.................\...\.................\.....\TrackingServiceStub.java&&Login\build.xml&&.....\manifest.mf&&.....\nbproject\build-impl.xml&&.....\.........\configs\Run_as_WebStart.properties&&.....\.........\.......\Run_in_Browser.properties&&.....\.........\jfx-impl.xml&&.....\.........\project.properties&&.....\.........\project.xml&&.....\src\login\CoarseGrid.png&&.....\...\.....\Login.css&&.....\...\.....\Login.fxml&&.....\...\.....\LoginController.java&&.....\...\.....\LoginLogo.png&&.....\...\.....\Main.java&&.....\...\.....\Profile.fxml&&.....\...\.....\ProfileController.java&&.....\...\.....\model\User.java&&.....\...\.....\security\Authenticator.java&&UnlockCustom\build.xml&&............\manifest.mf&&............\nbproject\build-impl.xml&&............\.........\configs\Run_as_WebStart.properties&&............\.........\.......\Run_in_Browser.properties&&............\.........\jfx-impl.xml&&............\.........\project.properties&&............\.........\project.xml&&............\src\unlock\Keypad.fxml&&............\...\......\Keypad.java&&............\...\......\KeypadController.java&&............\...\......\Unlock.css&&............\...\......\Unlock.fxml&&............\...\......\Unlock.java&&............\...\......\UnlockController.java&&............\...\......\lock.png&&......Include\build.xml&&.............\manifest.mf&&.............\nbproject\build-impl.xml&&.............\.........\configs\Run_as_WebStart.properties&&.............\.........\.......\Run_in_Browser.properties&&.............\.........\jfx-impl.xml&&.............\.........\project.properties&&.............\.........\project.xml
&输入关键字,在本站238万海量源码库中尽情搜索:既然有scene builder,是否没有必要自己写javafx代码_百度知道
既然有scene builder,是否没有必要自己写javafx代码
我有更好的答案
没有规定必须放在哪个目录下,当时FXML的根节点上的 fx:controller要能找到对应的Java类,并且在FXML中元素定义的fx:id 要在对应的Java类里有相应类型的属性。这样就不会有no injectable field found in fxml controller。 这句意思就是FXML文件中定义了类似&TableView fx:id=&tableView& ………………&&/TableView& 的元素,在fx:controller对应的类里就得要声明一个 TableView tableView 的属性
采纳率:85%
来自团队:
为您推荐:
其他类似问题
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。}

我要回帖

更多关于 idea scene builder 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信