当前位置: 移动技术网 > 科技>操作系统>windows > 【Swing】JPanel重写paint()后按钮被遮挡,点击按钮键盘监听失效

【Swing】JPanel重写paint()后按钮被遮挡,点击按钮键盘监听失效

2020年07月28日  | 移动技术网科技  | 我要评论
效果图内容说明上图是我们小组做的泡泡堂,在接近项目结尾时,我接手一个小任务,就是在游戏进行界面底部增加截图中的3个按钮,并实现部分功能(有些按钮的功能组员已经实现了,我只需要调用他们的方法就可以了)。下面,我来将遇到的问题抽离出来,记录到博客。我相信应该也有同学会遇到这些问题。1、如何布局能更好的将按钮组放在面板的底部居中位置?并且看起来像悬浮在地图之上。2、由于面板中复写了paint()方法,导致按钮组被遮挡。但是当鼠标移上去,按钮组又可以显现出来。3、点击底部任意一个按钮后,键

效果图

内容说明

上图是我们小组做的泡泡堂,在接近项目结尾时,我接手一个小任务,就是在游戏进行界面底部增加截图中的3个按钮,并实现部分功能(有些按钮的功能组员已经实现了,我只需要调用他们的方法就可以了)。下面,我来将遇到的问题抽离出来,记录到博客。我相信应该也有同学会遇到这些问题。

1、如何布局能更好的将按钮组放在面板的底部居中位置?并且看起来像悬浮在地图之上。

2、由于面板中复写了paint()方法,导致按钮组被遮挡。但是当鼠标移上去,按钮组又可以显现出来。

3、点击底部任意一个按钮后,键盘监听失效。按键盘,无法操作游戏中的人物。

问题1

其实我对于Java Swing的布局也不是太熟悉,并且感觉不太好用。要实现上述布局效果,可以利用布局嵌套。

(1)首先,按钮组(可以是多个按钮),无论宽度多少,都居中显示,我们可以想到FlowLayout.CENTER

(2)那么如何将按钮组布局到底部呢?显然,我们可以将这多个按钮放到一个JPanel(可命名为:btnPanel)中,然后将该面板利用BorderLayout.SOUTH放到底部。

(3)又有一个问题,我们想要看到的想过是按钮组像是悬浮在游戏地图之上。但是,放按钮组的btnPanel的面板是灰色的,它会遮挡游戏地图。那么,我们可以通过setOpaque(false)将面板背景设置为透明,这样只有按钮是显示的,背景是透明的。

下面,给出具体代码

// 布局嵌套。BorderLayout.SOUTH和FlowLayout.CENTER)实现按钮组底部居中
// 游戏面板的布局
this.setLayout(new BorderLayout()); 

// 按钮组面板
JPanel btnPanel = new JPanel();
btnPanel.setOpaque(false);	// 将面板设置为透明,否则灰色面板会遮挡地图
btnPanel.setLayout(new FlowLayout(FlowLayout.CENTER));
bgmBtn = new JButton("开启BGM");
runBtn = new JButton("暂停游戏");
overBtn = new JButton("结束游戏");
btnPanel.add(bgmBtn);
btnPanel.add(runBtn);
btnPanel.add(overBtn);

// 将按钮组面板,放置到游戏面板的南部
this.add(btnPanel, BorderLayout.SOUTH);

问题2

经测试,有两种解决方法。

(1)重写paint()方法时,最后加上super.paintChildren(g),重写组件。

(2)不要重写paint()方法,而是直接重写paintComponent()方法

下面我已第(1)种解决方法,给出代码

        /**
	 * 重写绘画方法。绘画时是有固定的顺序,先绘画的图片会在底层,后绘画的图片会覆盖先绘画的
	 * 约定:本方法只执行一次,想实时刷新需要使用多线程
	 */
	@Override
	public void paint(Graphics g) {
		super.paint(g);

        /*
        // 自己的代码......
		// 所有元素的显示
		Map<GameElement, List<ElementObj>> all = em.getGameElements();
		// GameElement.values()是隐藏方法,无法点进去
		// 返回的数组的顺序时是枚举变量声明时的顺序
		for (GameElement ge : GameElement.values()) {
			List<ElementObj> list = all.get(ge);
//			if(ge.equals(GameElement.MAPS)) {
////			if(ge == GameElement.MAPS) {
//				Collections.sort(list);
//			}
			for (int i = 0; i < list.size(); i++) {
				ElementObj obj = list.get(i);
				obj.showElement(g);
			}
		}
        */
		
		// !!!重新绘制子组件,否则paint之后会遮挡住组件!!!
		super.paintChildren(g);
			
	}

问题3

显然,键盘监听是用来操作游戏中的人物的。那么在游戏进行过程中,点击了底部按钮,键盘监听为什么会失效?

因为,我们的键盘监听是作用在窗体上(JFrame),当点击底部按钮,窗体失去了焦点,焦点落在了按钮上。所以键盘会失效。所以,只需要通过requestFocus()让窗体重新获得焦点即可。

代码如何操作呢?在按钮的点击事件中,在完成了点击事件的所以逻辑之后,拿到当前窗体的实例对象,调用它的requestFocus()让它重新获得焦点即可。

代码比较简单,我就不把我项目中的代码贴出来了。

本文地址:https://blog.csdn.net/qq_43290318/article/details/107612241

如您对本文有疑问或者有任何想说的,请点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网