感谢大佬:https://blog.csdn.net/ltx06/article/details/28996839

最近在书上看到这篇文章,觉得挺有意思。与大家分享一下,具体可以参见明日科技出版的《Java经典编程300例》。

默认情况下,我们用java设计的界面窗体是这样的:



默认的标题栏、最大化、最小化、关闭按钮、窗体边框。

如何自定义窗体达到如下效果呢?



大致说下代码要点:

  1. 设置窗体的Undecorated属性为true,阻止窗体采用本机系统修饰,这样窗体就没有标题栏和边框了。
  2. 设计背景面板类。BackgroundPanel extends JPanel。
  3. 窗体面板添加标题栏面板,位置在上方。
  4. 标题栏面板添加背景面板显示标题栏图片、标题栏面板添加面板用于放置最大化、最小化、关闭按钮。
  5. 窗体面板添加背景面板在中间。contentPane.add(mianPanel,BorderLayout.Center);
  6. 添加按钮响应、添加标题栏拖动代码。

代码:

首先是带背景图片面板类:

package cn.chengmaoning.customframe;      

import java.awt.Graphics;
import java.awt.Image; import javax.swing.JPanel; public class BackgroundPanel extends JPanel { /**
*
*/
private static final long serialVersionUID = -898997756345637309L;
private Image image; /**
* Constructor
*/
public BackgroundPanel() {
super();
setOpaque(false);
setLayout(null);
} /**
* @param image
* 要设置的 image
*/
public void setImage(Image image) {
this.image = image;
} @Override
protected void paintComponent(Graphics g) {
if (image != null) {
int width = getWidth();// 获取组件大小
int height = getHeight();
g.drawImage(image, 0, 0, width, height, this);// 绘制图片与组件大小相同
}
super.paintComponent(g);// 执行超类方法
} }

其次再是主类:

package cn.chengmaoning.customframe;     

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter; import javax.jws.Oneway;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JToggleButton; public class ControlFormStatus extends JFrame { /**
*
*/
private static final long serialVersionUID = -2214759764324605473L;
private JPanel contentPane;
private Point pressedPoint; /**
* @param args
*/
public static void main(String[] args) {
// TODO 自动生成的方法存根
EventQueue.invokeLater(new Runnable() { @Override
public void run() {
// TODO 自动生成的方法存根
try {
ControlFormStatus frame = new ControlFormStatus();
frame.setVisible(true);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
});
} /**
* Constructor
*/
public ControlFormStatus(){
setUndecorated(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new JPanel();
contentPane.setBorder(null);
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane); BackgroundPanel topPanel = new BackgroundPanel();
topPanel.addMouseMotionListener(new MouseMotionAdapter() {
@Override
public void mouseDragged(MouseEvent e){
do_topPanel_mouseDragged(e);
}
});
topPanel.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
// TODO 自动生成的方法存根
do_topPanel_mousePressed(e);
}
});
Image centerImage = new ImageIcon(getClass().getResource("frameTop.png")).getImage();
Dimension dimension = new Dimension(centerImage.getWidth(this), centerImage.getHeight(this));
topPanel.setPreferredSize(dimension);
topPanel.setImage(centerImage); contentPane.add(topPanel,BorderLayout.NORTH);
topPanel.setLayout(new FlowLayout(FlowLayout.RIGHT, 5, 5)); JPanel panel = new JPanel();
panel.setPreferredSize(new Dimension(60, 22));
panel.setOpaque(false);
topPanel.add(panel);
panel.setLayout(new GridLayout(1, 0, 0, 0)); JButton button = new JButton("");
button.setRolloverIcon(new ImageIcon(ControlFormStatus.class.getResource("minBH.jpg")));
button.addActionListener(new ActionListener() { @Override
public void actionPerformed(ActionEvent e) {
// TODO 自动生成的方法存根
do_button_actionPerformed(e);
}
});
button.setFocusPainted(false);
button.setBorderPainted(false);
button.setContentAreaFilled(false);
button.setIcon(new ImageIcon(ControlFormStatus.class.getResource("minB.jpg")));
panel.add(button); JToggleButton button_1 = new JToggleButton("");
button_1.addItemListener(new ItemListener() { @Override
public void itemStateChanged(ItemEvent e) {
// TODO 自动生成的方法存根
do_button_1_itemStateChanged(e);
}
});
button_1.setRolloverIcon(new ImageIcon(ControlFormStatus.class.getResource("maxBH.jpg")));
button_1.setRolloverSelectedIcon(new ImageIcon(ControlFormStatus.class.getResource("maxBH.jpg")));
button_1.setIcon(new ImageIcon(getClass().getResource("maxB.jpg")));
button_1.setContentAreaFilled(false);
button_1.setBorderPainted(false);
button_1.setFocusPainted(false);
panel.add(button_1); JButton button_2 = new JButton("");
button_2.addActionListener(new ActionListener() { @Override
public void actionPerformed(ActionEvent e) {
// TODO 自动生成的方法存根
do_button_2_actionPerformed(e);
}
});
button_2.setRolloverIcon(new ImageIcon(getClass().getResource("closeBH.jpg")));
button_2.setIcon(new ImageIcon(getClass().getResource("closeB.jpg")));
button_2.setFocusPainted(false);
button_2.setContentAreaFilled(false);
button_2.setBorderPainted(false);
panel.add(button_2); BackgroundPanel baclBackgroundPanel_1 = new BackgroundPanel();
Image topImage = new ImageIcon(getClass().getResource("frameCenter.png")).getImage();
baclBackgroundPanel_1.setImage(topImage);
contentPane.add(baclBackgroundPanel_1, BorderLayout.CENTER); } protected void do_button_2_actionPerformed(ActionEvent e) {
// TODO 自动生成的方法存根
dispose();
} protected void do_button_1_itemStateChanged(ItemEvent e) {
// TODO 自动生成的方法存根
if (e.getStateChange() == ItemEvent.SELECTED) {
setExtendedState(MAXIMIZED_BOTH);
} else {
setExtendedState(NORMAL);
}
} protected void do_button_actionPerformed(ActionEvent e) {
// TODO 自动生成的方法存根
setExtendedState(ICONIFIED);
} protected void do_topPanel_mousePressed(MouseEvent e) {
// TODO 自动生成的方法存根
pressedPoint = e.getPoint();
} protected void do_topPanel_mouseDragged(MouseEvent e) {
// TODO 自动生成的方法存根
Point point = e.getPoint();
Point locationPoint = getLocation(); int x = locationPoint.x + point.x - pressedPoint.x;
int y = locationPoint.y + point.y - pressedPoint.y; setLocation(x, y);
} }

代码中用到的图片如下:(我不知道有什么更好的方法可以把图片保存到这篇文章里,所以只有贴到这里了,试验的同学可以直接另存图片到本机,放置到与.java相同路径下即可)















Java 自定义窗体(标题栏、窗体背景)的更多相关文章

  1. WPF 之 自定义窗体标题栏

    在WPF中自定义窗体标题栏,首先需要将窗体的WindowStyle属性设置为None,隐藏掉WPF窗体的自带标题栏.然后可以在窗体内部自定义一个标题栏. 例如,标题栏如下: <WrapPanel ...

  2. WinForm拖动没有标题栏窗体的方法

    建立窗体的名称修改为:Form_HoverTree 文后附有源码下载. 主要代码: Point _HoverTreePosition; public Form_HoverTree() { Initia ...

  3. 【转】【C#】C#重绘windows窗体标题栏和边框

    摘要 windows桌面应用程序都有标准的标题栏和边框,大部分程序也默认使用这些样式,一些对视觉效果要求较高的程序,如QQ, MSN,迅雷等聊天工具的样式则与传统的windows程序大不相同,其中迅雷 ...

  4. WPF修改窗体标题栏的颜色

    WPF程序通常情况下没办法修改窗体标题栏的样式,包括标题栏的背景颜色. 不过借助一个叫Fluent.Ribbon的第三方控件,貌似可以修改标题栏的背景颜色. 可以通过NuGet来安装这个控件:Inst ...

  5. C#之移动无标题栏窗体功能的实现!...

    为实现移动无标题栏窗体的功能,我从网上寻找.整理了以下资料,以备不时之需: 该方法适用于有标题栏和无标题栏窗体,适用于窗体内控件,当然 Form 也不例外, 只须添加 MouseDown.MouseM ...

  6. Delphi组件开发-在窗体标题栏添加按钮(使用MakeObjectInstance(NewWndProc),并处理好多消息)

    这是一个在窗体标题栏添加自定义按钮的组件(TTitleBarButton)开发实例,标题栏按钮组件TTitleBarButton以TComponent为直接继承对象,它是一个可以在窗体标题栏上显示按钮 ...

  7. C# 移动无标题栏窗体的几种方法

    第一种,手工移动. 该方法根据鼠标位置实现窗体的移动.网上有很多相关的例子,这里不再多讲. 第二种,调用系统API原理:是当鼠标左键按下时,让系统认为是在标题栏按下的.这里我们用到了winapi里的W ...

  8. C#自定义运行时窗体设计器Runtime FormDesigner

    写在前面:因为业务的需要,有时会使用到自定义运行时窗体设计器Runtime FormDesigner,实现的功能,就是IDE设计器的简化.设想一下,如果可以在程序运行时,再设计一个Form,然后编译代 ...

  9. C#实现无标题栏窗体点击任务栏图标正常最小化或还原的解决方法

    对于无标题栏窗体,也就是FormBorderStyle等于System.Windows.Forms.FormBorderStyle.None的窗体,点击任务栏图标的时候,是不能象标准窗体那样最小化或还 ...

随机推荐

  1. <数据结构>图的最短路径问题

    目录 最短路径问题 Dijstra算法:中介点优化 基本步骤 伪代码 在实现过程中的关键问题 代码实现 邻接矩阵版 邻接表版 时间复杂度:O(VlogV+E) 算法存在的问题:存在负权边时会失效 Be ...

  2. Java初学者作业——为某超市设计管理系统,需要在控制台展示系统菜单,菜单之间可以完成跳转。

    返回本章节 返回作业目录 需求说明: 为某超市设计管理系统,需要在控制台展示系统菜单,菜单之间可以完成跳转. 实现思路: 定义mainMenu方法,用于显示主菜单. 主菜单主要负责显示4个选项,分别是 ...

  3. 为什么操作dom会消耗性能

    因为对DOM的修改为影响网页的用户界面,重绘页面是一项昂贵的操作.太多的JavaScript DOM操作会导致一系列的重绘操作,为了确保执行结果的准确性,所有的修改操作是按顺序同步执行的.我们称这个过 ...

  4. 从Base64编码转换为图片文件

    package luckyclient.utils;import java.io.FileInputStream;import java.io.FileOutputStream;import java ...

  5. 解读与部署(三):基于 Kubernetes 的微服务部署即代码

    在基于 Kubernetes 的基础设施即代码一文中,我概要地介绍了基于 Kubernetes 的 .NET Core 微服务和 CI/CD 动手实践工作坊使用的基础设施是如何使用代码描述的,以及它的 ...

  6. 面试官问,Redis 是单线程还是多线程?我懵了

    我们平时看到介绍 Redis 的文章,都会说 Redis 是单线程的.但是我们学习的时候,比如 Redis 的 bgsave 命令,它的作用是在后台异步保存当前数据库的数据到磁盘,那既然是异步了,肯定 ...

  7. redis的使用场景和优缺点

    使用场景和优缺点: 2 Redis用来做什么? 通常局限点来说,Redis也以消息队列的形式存在,作为内嵌的List存在,满足实时的高并发需求.而通常在一个电商类型的数据处理过程之中,有关商品,热销, ...

  8. [论文翻译] 分布式训练 Parameter Sharding 之 Google Weight Sharding

    [论文翻译] 分布式训练 Parameter sharding 之 Google Weight Sharding 目录 [论文翻译] 分布式训练 Parameter sharding 之 Google ...

  9. GeoServer介绍

    GeoServer本质上是一个地图服务器,它是遵循OpenGIS Web 服务器规范的J2EE实现,通过它可以方便的将地图数据发布为地图服务,实现地理空间数据在用户之间的共享.另外,它也提供了相应的接 ...

  10. 【VictoriaMetrics】vm-select源码阅读

    调用层次表格 源文件 行号 函数 说明 app/vmselect/main.go 63 main 入口 92行调用 requestHandler app/vmselect/main.go 132 -r ...