文章目录
- 开发工具
- 设置
- 实战示例
- 自定义组件
- 常用组件
- 总览
- JFrame
- JDialog
- JPanel
- Layout布局
- 高级扩展
- 扩展皮肤
- FlatLaf
- weblaf
- 扩展组件
- 自定义组件
- SwingX
- 打包部署
- 打包成可执行Jar
- 打包成成品
- 参考
开发工具
传统套件IDEA+UI Designer。
UI Designer是一个idea插件,可以帮助我们通过拖拽控件的方式快速开发swing界面,因此我们首先要保证idea启用了该插件。一般情况下,安装好idea都是自带了该插件,并且正常启用的。
设置
第一步:设置将GUI生成到Java源代码
第二步:添加生成代码时,所需要的一些依赖
<dependency>
<groupId>com.intellij</groupId>
<artifactId>forms_rt</artifactId>
<version>7.0.3</version>
</dependency>
实战示例
第一步 创建GUI窗体
第二步:组件JPanel起一个字段名
这个很重要,否者在后面生成main时会报错,无法生成main方法。
布局选择为Layout Manager,默认GridLayoutManager.
第三步:拖拽组件画UI
每个组件都要设置属性名称。
可以在编辑框和拖拽框中去定义组件的位置和大小。
第四步:给组件加上事件监听
在组件上1处,右键然后选择创建监听器。然后选择具体的监听器即可。
生成如下代码:
public MainPanel() {
query.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// 这里可以自定义逻辑
// 获取输入框内容
String keywordText = keyword.getText();
System.out.println(keywordText);
// 输出到 msg
msg.setText(keywordText);
}
});
}
此时整体代码如下:
public class MainPanel {
private JPanel mainPanel;
private JLabel lable;
private JTextField keyword;
private JButton query;
private JTextArea msg;
private JLabel tt;
public MainPanel() {
query.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// 获取输入框内容
String keywordText = keyword.getText();
System.out.println(keywordText);
// 输出到 msg
msg.setText(keywordText);
}
});
}
}
第五步:生成main方法
在类名称上右键选择生成或者Alt+Insert
生成代码如下:
public static void main(String[] args) {
JFrame frame = new JFrame("MainPanel");
frame.setContentPane(new MainPanel().mainPanel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
第六步:编译运行
运行main方法,(idea自动)生成GUI对应源码。
重点:不要修改自动生成的源码。
因为每次编译都会覆盖原来生成的源码,之前的修改就没了。
自定义组件
UI Designer可以自定义UI组件,例如同意按钮,拒绝按钮等,参见**高级扩展 **- 自定义组件。
使用场景为自定义的UI组件类和其他第三方扩展UI组件类SwingX,也可以放到UI Designer中去拖拽。
以添加MenuBar组件举例,默认可拖拽列表中没有该组件。
可拖拽列表中就会多出个我们自定义的组件JMenuBar
常用组件
Swing 是 Java 为图形界面应用开发提供的一组工具包,是 Java 基础类的一部分。
Swing 包含了构建图形界面(GUI)的各种组件,如: 窗口、标签、按钮、文本框等。
Swing 提供了许多比 AWT 更好的屏幕显示元素,使用纯 Java 实现,能够更好的兼容跨平台运行。
为了和 AWT 组件区分,Swing 组件在javax.swing.*包下,类名均以 J 开头,例如: JFrame、JLabel、JButton等。
组件按照不同的功能,可分为 顶层容器、中间容器、基本组件。一个简单窗口的组成,如下层级结构所示:
- 顶层容器
- 菜单栏
- 中间容器
- 基本组件
- 基本组件
- 顶层容器 属于窗口类组件,继承自java.awt.Window;顶层容器属于窗口类组件,可以独立显示,一个图形界面至少需要一个窗口;
- 中间容器 和 基本组件 继承自javax.swing.JComponent;中间容器充当基本组件的载体,不可独立显示。中间容器可以添加若干基本组件(也可以嵌套添加中间容器),对容器内的组件进行管理,类似于给各种复杂的组件进行分组管理。最顶层的一个中间容器必须依托在顶层容器(窗口)内。
- 基本组件是直接实现人机交互的组件。
总览
类别 | 组件 | 描述 |
---|---|---|
顶层组件(窗口) | JFrame | 一个普通的窗口(绝大多数 Swing 图形界面程序使用 JFrame 作为顶层容器) |
JDialog | 对话框 | |
中间容器(面板) | JPanel (相当于div) | 一般轻量级面板容器组件(作为JFrame中间容器) |
JScrollPane | 带滚动条的,可以水平和垂直滚动的面板组件 | |
JSplitPane | 分隔面板 | |
JTabbedPane | 选项卡面板 | |
JLayeredPane | 层级面板 | |
中间容器(特殊 菜单栏) | JMenuBar | 菜单栏 |
JToolBar | 工具栏 | |
JPopupMenu | 弹窗菜单 | |
JInternalFrame | 内部窗口 | |
基本组件(按钮,标签等) | JLabel | 标签 |
JButton | 按钮 | |
JTextField | 文本框 | |
JTextArea | 文本区域 | |
JPasswordField | 密码框 | |
JComboBox | 下拉列表框 | |
JRadioButton | 单选按钮 | |
JCheckBox | 复选框 | |
JToggleButton | 开关按钮 | |
JList | 列表 | |
JProgressBar | 进度条 | |
JSlider | 滑块 | |
选取器组件 | JFileChooser | 文件选择器 |
JColorChooser | 颜色选取器 | |
其他组件 | JTable | 表格 |
JTree | 树 |
JFrame
- 设置JFrame左上角的名称
frame.setTitle("laker");
- 动态的设置主体框架为固定的宽和高
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
if (screenSize.getWidth() > 1280) {
frame.setPreferredSize(new Dimension(1280, 800));
} else if (screenSize.getWidth() > 1024) {
frame.setPreferredSize(new Dimension(1200, 768));
} else {
frame.setPreferredSize(new Dimension(960, 640));
}
frame.pack();
- 静态的设置固定的宽和高
frame.setSize(800, 400);
- 设置JFrame在屏幕中间启动
frame.setLocationRelativeTo(null);
- 设置窗体的icon图标
//找到了,当前目录就是本项目的根路径
frame.setIconImage(new ImageIcon("src/main/java/cn/zuo/myres/icon/seal.png").getImage());
- 设置窗口的x,y位置,窗口大小x,y.
frame.setBounds(600, 300, 500, 400);
- 设置默认的关闭窗口
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
- 添加panel面板到容器
frame.add(panel)
- 添加面板到主窗口,布局在北面
frame.getContentPane().add(panel, BorderLayout.NORTH);
添加可滚动面板到主窗口,布局在中间
flame.getContentPane().add(scrollPane, BorderLayout.CENTER);
- 这个最好放在最后,不然视图会看不到
frame.setVisible(true);
- 确保一个漂亮的外观风格
frame.setDefaultLookAndFeelDecorated(true);
JDialog
JOptionPane是一个用于显示标准对话框的类,常用于与JDialog结合使用。常用的方法包括:
showMessageDialog(Component parentComponent, Object message)
: 显示一个包含消息的对话框。showInputDialog(Component parentComponent, Object message)
: 显示一个包含输入框的对话框,用于获取用户输入。showConfirmDialog(Component parentComponent, Object message)
: 显示一个包含确认按钮的对话框,用于获取用户确认。
这种不常用的方式。
JDialog()
: 创建一个默认的、模态的JDialog。JDialog(Dialog owner, String title, boolean modal)
: 创建一个带有指定所有者、标题和模态属性的JDialog。setDefaultCloseOperation(int operation)
: 设置关闭对话框时的操作。setVisible(boolean b)
: 设置对话框是否可见。setResizable(boolean resizable)
: 设置对话框是否可调整大小。setSize(int width, int height)
: 设置对话框的大小。setLocationRelativeTo(Component c)
: 将对话框定位到指定组件的中心。setLayout(LayoutManager mgr)
: 设置对话框的布局管理器。setTitle(String title)
: 设置对话框的标题。setContentPane(Container contentPane)
: 设置对话框的内容面板。
JPanel
JPanel panel = new JPanel(); // 创建面板容器
panel.add(button); // 添加按钮到面板
JScrollPane scrollPane = new JScrollPane(); // 创建可滚动面板
scrollPane.setViewportView(textArea); // 设置面板内容
// 弹出提示框到panel容器
JOptionPane.showMessageDialog(panel3, "没有选中任何文件", "提示", JOptionPane.WARNING_MESSAGE);
Layout布局
无论上面哪种组件,都可以设置布局,比如 frame.setLayout(new BorderLayOut())
或者 panel.setLayout(new FlowLayout())
再或是 button.setLayout(GridLayout)
。常用布局如下:
所属类包 | 布局管理器名称 | 说明 |
---|---|---|
空布局 | ||
Java.awt | BorderLayout(边界布局) | 容器划分为东、西、南、北、中五个区域,每个区域只能放置一个组件。 |
Java.awt | GridLayout(网格布局) | 容器的空间划分成M×N列的网格区域, 每个区域只能放置一个组件。其中col与row可以手动设置 |
Java.awt | FlowLayout(流式布局) | 组件按照加入的先后顺序按照设置的对齐方式从左向右排列,一行排满到下一行开始继续排列 |
Java.awt | GridBagLayout(网格包布局) | GridLayout的升级版,组件仍然是按照行、列放置,但是每个组件可以占据多个网格 |
Java.awt | CardLayout(卡片布局) | 如同一叠牌,每个牌对应一个组件,但每次只能显示其中的一张牌。适用于在一个空间中防止多个组件的情况 |
Java.swing | BoxLayout(箱式布局) | 允许在容器中纵向或者横向防止多个控件 |
Java.swing | SprigLayout(弹簧布局) | 根据一组约束条件放置控件 |
高级扩展
扩展皮肤
FlatLaf
FlatLaf是用于JavaSwing 桌面应用程序的现代开源跨平台外观。
- https://github.com/JFormDesigner/FlatLaf
第一步 首先Maven中引入依赖库:
<dependency>
<groupId>com.formdev</groupId>
<artifactId>flatlaf</artifactId>
<version>3.0</version>
</dependency>
如果想切换IntelliJ主题还可以添加以下包
<dependency>
<groupId>com.formdev</groupId>
<artifactId>flatlaf-intellij-themes</artifactId>
<version>3.0</version>
</dependency>
implementation("com.formdev:flatlaf:${flatlafVersion}")
implementation("com.formdev:flatlaf-swingx:${flatlafVersion}")
implementation("com.formdev:flatlaf-intellij-themes:${flatlafVersion}")
implementation("com.formdev:flatlaf-extras:${flatlafVersion}")
// 语法高亮可视化编辑器
implementation("com.fifesoft:rstaui:${fifesoftVersion}")
com.fifesoft:rsyntaxtextarea
// 提供了一组扩展的Swing组件,例如JXDatePicker、JXTable等,可以帮助开发人员更快速地创建出功能强大的用户界面。
//
implementation("at.swimmesberger:swingx-core:1.6.8")
// 提供了一种简单易用的方式来创建复杂的表单布局。
implementation("com.jgoodies:jgoodies-forms:1.9.0")
第二步 在启动JFrame之前先执行FlatLightLaf.setup()
// 亮色
FlatLightLaf.setup();
// 暗色
FlatDarkLaf.setup();
// 基于 FlatLaf Light)看起来像 IntelliJ IDEA 2019.2+ 中的 IntelliJ 主题
FlatIntelliJLaf.setup();
// (基于 FlatLaf Dark)看起来像来自 IntelliJ IDEA 2019.2+
FlatDarculaLaf.setup();
FlatMacLightLaf.setup();
FlatMacDarkLaf.setup();
UIManager.put("TextComponent.arc", 5);
UIManager.put("Component.focusWidth", 1);
UIManager.put("Component.innerFocusWidth", 1);
UIManager.put("Button.innerFocusWidth", 1);
UIManager.put("TitlePane.unifiedBackground", true);
UIManager.put("TitlePane.menuBarEmbedded", false);
// 设置字体,设置字体抗锯齿
System.setProperty("awt.useSystemAAFontSettings", "on");
System.setProperty("swing.aatext", "true");
Font fontUIResource = new Font("宋体", Font.PLAIN, 22);
for (Enumeration keys = UIManager.getDefaults().keys(); keys.hasMoreElements(); ) {
Object key = keys.nextElement();
Object value = UIManager.get(key);
if (value instanceof FontUIResource) {
UIManager.put(key, fontUIResource);
}
}
UIManager.put("defaultFont", fontUIResource);
weblaf
- https://github.com/mgarin/weblaf
第一步 添加依赖
<dependency>
<groupId>com.weblookandfeel</groupId>
<artifactId>weblaf-ui</artifactId>
<version>1.2.13</version>
</dependency>
第二步 在启动JFrame之前先执行WebLookAndFeel.install ()
public class QuickStart
{
public static void main ( final String[] args )
{
// You should always work with UI inside Event Dispatch Thread (EDT)
// That includes installing L&F, creating any Swing components etc.
SwingUtilities.invokeLater ( new Runnable ()
{
@Override
public void run ()
{
// Install WebLaF as application LaF
WebLookAndFeel.install ();
// You can also specify preferred skin right-away
// WebLookAndFeel.install ( WebDarkSkin.class );
// You can also do that in one of the old-fashioned ways
// UIManager.setLookAndFeel ( new WebLookAndFeel () );
// UIManager.setLookAndFeel ( "com.alee.laf.WebLookAndFeel" );
// UIManager.setLookAndFeel ( WebLookAndFeel.class.getCanonicalName () );
// You can also configure other WebLaF managers as you like now
// StyleManager
// SettingsManager
// LanguageManager
// ...
// Initialize your application once you're done setting everything up
// JFrame frame = ...
// You can also use Web* components to get access to some extended WebLaF features
// WebFrame frame = ...
}
} );
}
}
扩展组件
自定义组件
第一步 新建LakerButton
public class LakerButton extends JButton {
public LakerButton() {
super();
super.putClientProperty(FlatClientProperties.STYLE, "focusedBackground: #263238;borderWidth:0;background: #08f; foreground: #fff;disabledBackground: #9e9e9e;disabledText:#fff;arc:10;");
}
}
第二步 在拖拽列表中增加自定义的组件
第三步 在具体的Panel生成的代码中加入如下:
// 有自定义组件的时候 必须要加
private void createUIComponents() {
lakerButton1 = new LakerButton();
}
SwingX
- https://github.com/arotenberg/swingx
打包部署
打包成可执行Jar
第一步 pom.xml添加打包插件并修改mainClass为自己的main所在类
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<!--包含文件夹以及子文件夹下所有资源-->
<include>**/*.*</include>
</includes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<!-- main类 -->
<mainClass>com.laker.swing.Bootstrap</mainClass>
</transformer>
</transformers>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
第二步 打包完成后执行
缺点:运行环境需要自己去安装jdk。
java -jar xxx.jar
打包成成品
JAR包打包为EXE 常见的将java项目打包为exe的工具有好几种,例如:exe4j,install4j,launch4j,JavaPackager
,还有java14之后的Jpackage
等。
JavaPackager是jdk1.8自带的一个打包工具,可以生成各个系统的安装包,是最简单方便的,可定制性也足够,该插件能够支持桌面系统windows,linux,mac,能随着项目迭代而简单的通过打包命令来得到最新的exe程序,可谓是相当方便了。
- https://github.com/fvarrui/JavaPackager
- windows 打包成exe执行包无需任何依赖;
- windows 打包成exe安装包的时候才需要;
- innosetup-5.6.0.exe(windows下Java8支持6版本以下的,不要下载6及其6以上的版本,否则无法打包成功)
- 我没有安装这个也可以打包成exe,但是不是安装包是执行包。
- https://jrsoftware.org/isinfo.php
- windows 打包msi安装包的时候才需要;
- Wix Toolset(打包成msi必须下载,没有下载
javapackager
会提示缺少wix) - https://wixtoolset.org/
- Wix Toolset(打包成msi必须下载,没有下载
- 生成本机安装包(在linux下生成deb,在windows下生成exe,在mac下生成dkg)
添加如下到pom.xml
:
<plugin>
<groupId>io.github.fvarrui</groupId>
<artifactId>javapackager</artifactId>
<version>{latest.version}</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>package</goal>
</goals>
<configuration>
<!-- mandatory -->
<mainClass>path.to.your.mainClass</mainClass>
<!-- optional -->
// 是否包含jre,这个需要选true,打包后将会包含可运行的jre在exe的同目录下
<bundleJre>true|false</bundleJre>
// 是否生成msi安装软件
<generateInstaller>true|false</generateInstaller>
// 是否必须管理员权限运行程序
<administratorRequired>true|false</administratorRequired>
// 打包的目标平台,auto|linux|mac|windows
<platform>auto|linux|mac|windows</platform>
<additionalResources>
<additionalResource>file path</additionalResource>
<additionalResource>folder path</additionalResource>
<additionalResource>...</additionalResource>
</additionalResources>
<linuxConfig>...</linuxConfig>
<macConfig>...</macConfig>
<winConfig>...</winConfig>
[...]
</configuration>
</execution>
</executions>
</plugin>
项目示例
<build>
<plugins>
<plugin>
<groupId>io.github.fvarrui</groupId>
<artifactId>javapackager</artifactId>
<version>1.6.7</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>package</goal>
</goals>
<configuration>
<mainClass>com.laker.swing.Bootstrap</mainClass>
<!-- 打包的名称 laker.exe -->
<name>laker</name>
<!-- 在应用程序中嵌入定制的 JRE。 -->
<bundleJre>true</bundleJre>
<!-- 为应用程序生成安装程序。-->
<generateInstaller>false</generateInstaller>
<!-- 应用程序将以管理员身份运行(具有提升的权限)。 -->
<administratorRequired>false</administratorRequired>
<platform>windows</platform>
<createZipball>true</createZipball>
<!-- <winConfig>-->
<!-- <headerType>gui</headerType>-->
<!-- <generateMsi>true</generateMsi>-->
<!-- </winConfig>-->
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
打包结果:
参考
- https://blog.csdn.net/justry_deng/article/details/121869629
- https://blog.csdn.net/weixin_43935927/article/details/109003074
- https://www.cnblogs.com/sandeepin/p/flatlaf-swing-ui-theme.html
- https://gitee.com/dromara/RedisFront/blob/master/build.gradle.kts
- https://blog.csdn.net/weixin_43444930/article/details/117855310