[英]How do I make my custom frame re-paint properly?
I am trying to create my own custom GUI toolkit based on swing as a bit of a side project. 我正在尝试创建一个基于Swing的自定义GUI工具包,这只是一个副项目。 My problem is this: I have created a frame with exit and minimize buttons however when I use the minimize button and maximise again, the window is not in the correct format.
我的问题是:我创建了一个带有退出和最小化按钮的框架,但是当我使用最小化按钮并再次最大化时,窗口的格式不正确。 Here is my code for the frame class.
这是我的框架类代码。
package com.SMS.GUI;
import java.awt.Color;
import java.awt.Frame;
import javax.swing.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseListener;
/**
*
* @author Marc
*/
final class SMSFrame extends JFrame implements MouseListener{
GUIButton minimizeButton, exitButton;
JPanel titleBar;
SMSFrame(int width, int height){
setResizable(false);
setUndecorated(true);
setSize(width,height);
getContentPane().setBackground(Color.decode("#8e44ad"));
setVisible(true);
minimizeButton = new GUIButton((width-100),0,50,50,"#1abc9c");
exitButton = new GUIButton((width-50), 0, 50, 50, "#d35400");
titleBar = new JPanel();
titleBar.setBackground(Color.decode("#2c3e50"));
titleBar.setBounds(0, 0, width, 50);
minimizeButton.addMouseListener(this);
exitButton.addMouseListener(this);
add(titleBar);
titleBar.add(exitButton);
titleBar.add(minimizeButton);
}
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mousePressed(MouseEvent e) {
if(e.getSource() == exitButton){
exitButton.setBackground(Color.decode("#c0392b"));
}
if(e.getSource() == minimizeButton){
minimizeButton.setBackground(Color.decode("#2ecc71"));
}
}
@Override
public void mouseReleased(MouseEvent e) {
if(e.getSource() == exitButton){
System.exit(0);
}
if(e.getSource() == minimizeButton){
super.setState(JFrame.ICONIFIED);
}
}
@Override
public void mouseEntered(MouseEvent e) {
if(e.getSource() == exitButton){
exitButton.setBackground(Color.decode("#e74c3c"));
}
if(e.getSource() == minimizeButton){
minimizeButton.setBackground(Color.decode("#16a085"));
}
}
@Override
public void mouseExited(MouseEvent e) {
if(e.getSource() == exitButton){
exitButton.setBackground(Color.decode("#d35400"));
}
if(e.getSource() == minimizeButton){
minimizeButton.setBackground(Color.decode("#1abc9c"));
}
}
}
Here is the code for the custom buttons(I used JPanels). 这是自定义按钮的代码(我使用了JPanels)。 package com.SMS.GUI;
包com.SMS.GUI;
import java.awt.Color;
import javax.swing.JPanel;
final class GUIButton extends JPanel{
GUIButton(int x, int y, int width, int height, String hexidecimal_colour){
setBackground(Color.decode(hexidecimal_colour));
setBounds(x, y, width, height);
}
GUIButton(int width, int height, String hexidecimal_colour){
setBackground(Color.decode(hexidecimal_colour));
setSize(width, height);
}
}
This is how the frame looks before minimizing: 这是最小化之前的外观:
however when I use the minimize button and maximise again, the window is not in the correct format.
但是,当我使用最小化按钮并再次最大化时,窗口的格式不正确。
You really need to understand how Swing works if you want to customize a component. 如果要自定义组件,您确实需要了解Swing的工作原理。 Swing was designed to be used with
layout managers
. Swing旨在与
layout managers
一起使用。 The default layout manager for the content pane of a JFrame
is a BorderLayout
. JFrame
的内容窗格的默认布局管理器是BorderLayout
。 The default layout manager for a JPanel
is a FlowLayout
. JPanel
的默认布局管理器是FlowLayout
。
The setSize() and/or setBounds() methods only work until the frame is "revalidated". setSize()和/或setBounds()方法仅在“重新验证”框架之前有效。 When the frame is restored to is size the layout managers for each component are invoked and all the components are displayed at their preferred size.
当框架恢复到其大小时,将调用每个组件的布局管理器,并以其首选大小显示所有组件。
titleBar = new JPanel();
So, the buttons on the "titleBar" get resized to their preferred size since they default FlowLayout
is used. 因此,“ titleBar”上的按钮将调整为其首选大小,因为它们使用了默认的
FlowLayout
。 And the FlowLayout
will then position the buttons in the center of the panel. 然后,
FlowLayout
会将按钮定位在面板的中央。
To fix this problem you need to override the getPreferredSize()
method of the GuiButton
class. 要解决此问题,您需要重写
GuiButton
类的getPreferredSize()
方法。 Also, get rid of all the location related code. 同样,摆脱所有与位置相关的代码。 It is up to the layout manager to set the location/size.
由布局管理器来设置位置/大小。
Since you want the buttons aligned to the right of the panel, you will need to change the layout manager to use a right aligned FlowLayout
. 由于您希望按钮与面板的右侧对齐,因此需要更改布局管理器以使用
right aligned FlowLayout
。 Read the FlowLayout
API for the proper constructor to use when creating the layout manager. 阅读
FlowLayout
API,以获取在创建布局管理器时要使用的适当构造函数。
add(titleBar);
This adds the "titleBar" to the CENTER
of the BorderLayout
, so when the frame is revalidated, this panel will now cover the entire frame based on the rules of the BorderLayout
. 这会将“ titleBar”添加到
BorderLayout
的CENTER
上,因此,当重新验证框架时,此面板现在将根据BorderLayout
的规则覆盖整个框架。
To fix this you can use: 要解决此问题,您可以使用:
add(titleBar, BorderLayout.PAGE_START);
Now the titlebar will only appear at the top for the frame. 现在,标题栏将仅出现在框架的顶部。
So you need to read the Swing tutorial on Layout Managers to understand these changes. 因此,您需要阅读有关布局管理器的Swing教程以了解这些更改。 The tutorial has working examples of both the
BorderLayout
and the FlowLayout
. 本教程包含
BorderLayout
和FlowLayout
工作示例。
I also suggest you read the section on How to Make Frames for simple frame basics, including a better structure for you code. 我还建议您阅读有关如何制作框架的部分, 以获取简单的框架基础知识,包括为您的代码提供更好的结构。 The example code shows the order of statement execution such that the
setVisible()
is the last statement. 示例代码显示了语句执行的顺序,以使
setVisible()
是最后一条语句。
You could try to repaint or revalidate when you are Deiconifying you window. 您在取消窗口图标化时可以尝试重新绘制或重新验证。 To do this, implements WindowListener and use this method :
为此,实现WindowListener并使用以下方法:
@Override
public void windowDeiconified(WindowEvent e) {
//back to normal you could use this.setState(JFrame.NORMAL);
//do stuff here.
}
don't forget the this.addWindowListener(this);
不要忘记
this.addWindowListener(this);
Also you extends JFrame so you could call this.setState(JFrame.ICONIFIED);
您还扩展了JFrame,因此可以调用
this.setState(JFrame.ICONIFIED);
instead of super
method. 而不是
super
方法。 It's not a complete solution but it's definitly a problem of component painting. 这不是一个完整的解决方案,但绝对是组件绘制的问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.