[Swing] The button is blocked after JPanel rewrites paint(), and the keyboard monitoring fails when the button is clicked

Effect picture

Content description

The picture above is the bubble hall made by our team. At the end of the project, I took over a small task, which is to add 3 buttons in the screenshot at the bottom of the game interface and implement some functions (the function members of some buttons have already been implemented Yes, I just need to call their methods). Next, I will extract the problems encountered and record them on the blog. I believe that some students will encounter these problems.

1. How to lay out the button group better at the bottom center of the panel? And it looks like it is floating above the map.

2. Because the paint() method is overwritten in the panel, the button group is blocked. But when the mouse is moved up, the button group can be revealed again.

3. After clicking any button at the bottom, the keyboard monitoring is disabled. Press the keyboard, the characters in the game cannot be operated.

Question 1

In fact, I am not too familiar with the layout of Java Swing, and it feels not easy to use. To achieve the above layout effects, you can use layout nesting.

(1) First of all, the button group (can be multiple buttons), regardless of the width, are displayed in the center, we can think of FlowLayout.CENTER .

(2) So how to lay out the button group to the bottom? Obviously, we can put these multiple buttons in a JPanel (can be named: btnPanel), and then use BorderLayout.SOUTH to put the panel at the bottom.

(3) There is another problem. What we want to see is that the button group seems to be floating above the game map. However, the panel of the btnPanel with the button group is gray, which will obscure the game map. Then, we can set the panel background to transparent through setOpaque(false), so that only the button is displayed and the background is transparent.

Below, give the specific code

// 布局嵌套。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);

Question 2

After testing, there are two solutions.

(1) When rewriting the paint() method, add super.paintChildren(g) at the end to rewrite the component.

(2) Do not rewrite the paint() method, but directly rewrite the paintComponent() method

Below I have the first (1) solution, give the code

        /**
	 * 重写绘画方法。绘画时是有固定的顺序,先绘画的图片会在底层,后绘画的图片会覆盖先绘画的
	 * 约定:本方法只执行一次,想实时刷新需要使用多线程
	 */
	@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);
			
	}

Question 3

Obviously, keyboard monitoring is used to manipulate the characters in the game. Then during the game, if I click the bottom button, why does the keyboard monitor fail?

Because our keyboard monitoring works on the form (JFrame), when the bottom button is clicked, the form loses focus, and the focus falls on the button. So the keyboard will fail. So, only need to requestFocus() to let the form regain the focus.

How does the code work? In the click event of the button, after completing all the logic of the click event, get the instance object of the current form and call its requestFocus() to let it regain focus.

The code is relatively simple, I will not post the code in my project.

Guess you like

Origin blog.csdn.net/qq_43290318/article/details/107612241