Java 如何更新JFrame比使用repaint()更快;
我正在尝试为游戏开发一个带有透明按钮的菜单。 我的问题是,每次我悬停按钮时,它们都会堆积起来。 因此,我添加了一个执行myJFrame.repaint()的MouseStener;每次我在它们上面盘旋。 问题是,重新绘制的速度太慢,用户感到不安。 我希望有人知道更好的方法 如果有错误,我很抱歉,我的英语不是最好的Java 如何更新JFrame比使用repaint()更快;,java,swing,jframe,jbutton,repaint,Java,Swing,Jframe,Jbutton,Repaint,我正在尝试为游戏开发一个带有透明按钮的菜单。 我的问题是,每次我悬停按钮时,它们都会堆积起来。 因此,我添加了一个执行myJFrame.repaint()的MouseStener;每次我在它们上面盘旋。 问题是,重新绘制的速度太慢,用户感到不安。 我希望有人知道更好的方法 如果有错误,我很抱歉,我的英语不是最好的 public class Hauptmenue extends javax.swing.JFrame implements ActionListener { private stati
public class Hauptmenue extends javax.swing.JFrame implements ActionListener {
private static final long serialVersionUID = 8132389688291883346L;
//Toolkit für das Freie Skalieren des Hauptmenüs
private Toolkit t;
//variablen für das Fenster
private int x, y, width, height;
//variablen für die Köpfe
private int kx, kwidth, kheight;
//Variablen für die Knöpfe im Hauptmenü:
private JButton2 single;
private JButton2 multi;
private JButton2 einstellungen;
private JButton2 info;
private JButton2 ende;
//Hintergrund des Hauptmenüs
Image background;
public Hauptmenue(){
//Bildschirmgröße messen:
t = Toolkit.getDefaultToolkit();
Dimension d = t.getScreenSize();
width = (int)(d.getWidth() * 0.23);
height = (int)(d.getHeight() * 0.5);
x = (int)((d.getWidth() - width) * 0.5);
y = (int)((d.getHeight() - height) * 0.5);
setTitle("Hauptmenü");
setBounds(x, y, width, height);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(null);
setBackground(null);
//Hintergrnd Bild
//setFocusable(true);
File pfad = new File("res/Images/Hintergrund_1.png");
ImageIcon u = new ImageIcon(pfad.getPath());
background = u.getImage();
//background = background.getScaledInstance(width, height, Image.SCALE_DEFAULT);
//sorgt dafür, dass das Menü keinen Rahmen hat
setUndecorated(true);
//knopfpositionen und Größen berechnen
kwidth = (int)(width * 0.8);
kheight = (int)(height * 0.125);
kx = (int)(width - kwidth) / 2;
//die Knöpfe:
single = new JButton2("Singelplayer");
single.setBounds(kx, (kheight * 1), kwidth, kheight);
single.addActionListener(this);
single.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseEntered(java.awt.event.MouseEvent evt) {
JFrame frme = (JFrame) info.getParent().getParent().getParent().getParent();
frme.repaint();
}
public void mouseExited(java.awt.event.MouseEvent evt) {
JFrame frme = (JFrame) info.getParent().getParent().getParent().getParent();
frme.repaint();
}
});
add(single);
multi = new JButton2("Multiplayer");
multi.setBounds(kx, (int)(kheight * 2.25), kwidth, kheight);
multi.addActionListener(this);
multi.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseEntered(java.awt.event.MouseEvent evt) {
JFrame frme = (JFrame) info.getParent().getParent().getParent().getParent();
frme.repaint();
}
public void mouseExited(java.awt.event.MouseEvent evt) {
JFrame frme = (JFrame) info.getParent().getParent().getParent().getParent();
frme.repaint();
}
});
add(multi);
einstellungen = new JButton2("Einstellungen");
einstellungen.setBounds(kx, (int)(kheight * 3.5), kwidth, kheight);
einstellungen.addActionListener(this);
einstellungen.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseEntered(java.awt.event.MouseEvent evt) {
JFrame frme = (JFrame) info.getParent().getParent().getParent().getParent();
frme.repaint(1);
}
public void mouseExited(java.awt.event.MouseEvent evt) {
JFrame frme = (JFrame) info.getParent().getParent().getParent().getParent();
frme.repaint(1);
}
});
add(einstellungen);
info = new JButton2("Info");
info.setBounds(kx, (int)(kheight * 4.75), kwidth, kheight);
info.addActionListener(this);
info.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseEntered(java.awt.event.MouseEvent evt) {
JFrame frme = (JFrame) info.getParent().getParent().getParent().getParent();
frme.repaint();
}
public void mouseExited(java.awt.event.MouseEvent evt) {
JFrame frme = (JFrame) info.getParent().getParent().getParent().getParent();
frme.repaint();
}
});
add(info);
ende = new JButton2("Beenden");
ende.setBounds(kx, (kheight * 6), kwidth, kheight);
ende.addActionListener(this);
ende.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseEntered(java.awt.event.MouseEvent evt) {
JFrame frme = (JFrame) info.getParent().getParent().getParent().getParent();
frme.repaint();
}
public void mouseExited(java.awt.event.MouseEvent evt) {
JFrame frme = (JFrame) info.getParent().getParent().getParent().getParent();
frme.repaint();
}
});
add(ende);
setVisible(true);
}
//der Hintergrund:
//zum Zeichnen des Hintergrundes:
public void paint(Graphics g){
super.paint(g);
Graphics2D f2 = (Graphics2D)g;
f2.drawImage(background, 0, 0, width, height, null);
//Knöpfe in den Vordergrund holen
this.single.paint(this.single.getGraphics());
this.multi.paint(this.multi.getGraphics());
this.einstellungen.paint(this.einstellungen.getGraphics());
this.info.paint(this.info.getGraphics());
this.ende.paint(this.ende.getGraphics());
g.dispose();
}
//Funktionen hinter den Knöpfen:
private void Singleplayer(){
}
private void Multiplayer(){
}
private void Einstellungen(){
new Einstellungsfenster();
}
private void Info(){
new Infofenster();
}
private void Beenden(){
System.exit(0);
}
//Reaktionen auf die Knopfdrücke:
public void actionPerformed (ActionEvent e){
if(e.getSource() == single){
Singleplayer();
}
if(e.getSource() == multi){
Multiplayer();
}
if(e.getSource() == einstellungen){
Einstellungen();
}
if(e.getSource() == info){
Info();
}
if(e.getSource() == ende){
Beenden();
}
}
//Programmstart
public static void main(String[]args){
//das Hauptmenü wird erzeugt
new Hauptmenue();
}}
我还对JButton做了一些更改:
public class JButton2 extends JButton {
private static final long serialVersionUID = 5193885870007603559L;
public JButton2(){
}
public JButton2(String text){
this.setText(text);
//this.setOpaque(false);
//this.setContentAreaFilled(false);
//this.setBackground(null);
}
@Override
public void paint(Graphics g){
//super.paint(g);
Graphics2D g2 = (Graphics2D) g.create();
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, (float) 0.8));
super.paint(g2);
g.dispose();
g2.dispose();
}
//@Override
public void repaint(){
//hier passiert nichts
}}
当然
将只重新绘制这些边界,加快它们的速度,并省略不必要的工作。调用任何repaint()方法只是将组件排队等待稍后重新绘制。如果在RepaitManager实际重新绘制组件之前多次调用Repait(),则它们将简单地合并到一个重新绘制操作中
您应该尝试使用其中一个paintInstance()方法,因为这些方法会立即执行重新绘制(我打赌您无法从名称中猜到)
欲了解更多信息,请阅读:
如果您从半透明/透明中获得瑕疵,请尝试在按钮上调用
setOpaque(false)
。它可以帮助您获得预期的结果,而无需调用父组件上的重绘。在courtains后面的Swing可能会重新绘制第一个不透明的父对象,但只需要绘制所需的区域。很抱歉,您的代码在很多方面都失败了。您尝试重新绘制只是解决其他一些问题的一种方法。如果您知道正确的提示,代码就会变得相当简单。但是,我没有解释所有出错的小细节,而是将整个固定代码放在这里,其中包含有关重要内容的注释
Main.java
持有主类。它只是打开并配置主窗口。(菜单本身在另一个名为MainMenu
的类中)
main menu.java
是最大的文件
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
/**
* Main menu is a JPanel.
*/
public class MainMenu extends JPanel {
private JButton single;
private JButton multi;
private JButton settings;
private JButton info;
private JButton exit;
private BufferedImage background;
public MainMenu() {
super();
// We use a layout manager to do all layouting for us
// So we can lean back and do not have to do odd maths
GridLayout layout = new GridLayout(5, 1);
layout.setVgap(20);
setLayout(layout);
// An empty border to ensure distance form the bounds of the panel
setBorder(new EmptyBorder(50, 30, 50, 30));
single = new AlphaButton("Single", 0.8f);
multi = new AlphaButton("Multi", 0.8f);
settings = new AlphaButton("Settings", 0.8f);
info = new AlphaButton("Info", 0.8f);
exit = new AlphaButton("Exit", 0.8f);
exit.addActionListener(evt -> System.exit(0));
// Add the buttons to this panel.
// It will take care of the rest (repainting etc.)
add(single); add(multi); add(settings); add(info); add(exit);
try {
// load background image
background = ImageIO.read(
getClass().getResource("res/Images/Hintergrund_1.png"));
} catch (IOException e) {
// TODO exception handling
e.printStackTrace();
}
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// Here, we just draw the background. Nothing else!
// Use this as image observer so repainting occurs if the image changes
// (which doesn't happen here, but we want to do it right).
g.drawImage(background, 0, 0, getWidth(), getHeight(), this);
// DO NOT DISPOSE g - you did not create it!
}
}
最后,但并非最不重要的是,半透明按钮的代码:
import java.awt.AlphaComposite;
import java.awt.Composite;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JButton;
/**
* Semi-transparent {@link JButton}.
*/
public class AlphaButton extends JButton {
private float alpha;
public AlphaButton(String text, float alpha) {
super(text);
this.alpha = alpha;
// This is important! It tells the painting system that the underlying
// pixels may shine through, so it must always paint the background
// before this component can be painted.
setOpaque(false);
}
@Override
protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
Composite old = g2.getComposite(); // remember old composite
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha));
super.paintComponent(g2);
g2.setComposite(old); // restore old composite
// DO NOT DISPOSE g (or g2) - you did not create it!
}
}
不要覆盖
paint()
,而要覆盖paintComponent()
。不要忘记调用super.paintComponent(g)
您不应该在paint
中手动绘制子组件(按钮)。这是自动完成的,因为它们是主JFrame
的子对象!还有:不要处理你没有创建的图形对象!
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
/**
* Main menu is a JPanel.
*/
public class MainMenu extends JPanel {
private JButton single;
private JButton multi;
private JButton settings;
private JButton info;
private JButton exit;
private BufferedImage background;
public MainMenu() {
super();
// We use a layout manager to do all layouting for us
// So we can lean back and do not have to do odd maths
GridLayout layout = new GridLayout(5, 1);
layout.setVgap(20);
setLayout(layout);
// An empty border to ensure distance form the bounds of the panel
setBorder(new EmptyBorder(50, 30, 50, 30));
single = new AlphaButton("Single", 0.8f);
multi = new AlphaButton("Multi", 0.8f);
settings = new AlphaButton("Settings", 0.8f);
info = new AlphaButton("Info", 0.8f);
exit = new AlphaButton("Exit", 0.8f);
exit.addActionListener(evt -> System.exit(0));
// Add the buttons to this panel.
// It will take care of the rest (repainting etc.)
add(single); add(multi); add(settings); add(info); add(exit);
try {
// load background image
background = ImageIO.read(
getClass().getResource("res/Images/Hintergrund_1.png"));
} catch (IOException e) {
// TODO exception handling
e.printStackTrace();
}
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// Here, we just draw the background. Nothing else!
// Use this as image observer so repainting occurs if the image changes
// (which doesn't happen here, but we want to do it right).
g.drawImage(background, 0, 0, getWidth(), getHeight(), this);
// DO NOT DISPOSE g - you did not create it!
}
}
import java.awt.AlphaComposite;
import java.awt.Composite;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JButton;
/**
* Semi-transparent {@link JButton}.
*/
public class AlphaButton extends JButton {
private float alpha;
public AlphaButton(String text, float alpha) {
super(text);
this.alpha = alpha;
// This is important! It tells the painting system that the underlying
// pixels may shine through, so it must always paint the background
// before this component can be painted.
setOpaque(false);
}
@Override
protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
Composite old = g2.getComposite(); // remember old composite
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha));
super.paintComponent(g2);
g2.setComposite(old); // restore old composite
// DO NOT DISPOSE g (or g2) - you did not create it!
}
}