我试图通过透明按钮为游戏开发菜单。 我的问题是,每次我徘徊时,按钮堆积起来。 所以我添加了一个执行myJFrame.repaint()的MouseListener;每次我徘徊他们。 问题是,重新绘制如此缓慢,这会扰乱用户。 我希望有人知道更好的方式。
对不起,如果有错误,我的英语不是最好的。
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
}}
答案 0 :(得分:1)
如果您从半透明/透明度获取工件,请尝试在按钮上调用setOpaque(false)
。它可以帮助您获得预期的结果,而无需在父组件上调用重绘。在窗帘后面摆动,可能会重新绘制第一个不透明的父母,但只有所需的区域。
答案 1 :(得分:1)
我很遗憾地说,但是你的代码在很多方面都失败了。您尝试重新绘制的尝试只是其他一些问题的解决方法。如果您知道正确的提示,则代码变得相当容易。但是,相反解释所有出错的细节,我只是将整个固定代码放在这里,其中包含有关重要事项的评论。
Main.java
拥有主类。它只是打开并配置主窗口。 (菜单本身位于另一个名为MainMenu
的类中。
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Toolkit;
import javax.swing.JFrame;
/**
* Main class
*/
public class Main {
/**
* Create the GUI and show it. For thread safety, this method should be
* invoked from the event-dispatching thread.
*/
private static void createAndShowGUI() {
// Create and set up the window.
JFrame frame = new JFrame("Game");
frame.setUndecorated(true);
// Center on screen
Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
int width = (int) (d.getWidth() * 0.23);
int height = (int) (d.getHeight() * 0.5);
int x = (int) ((d.getWidth() - width) * 0.5);
int y = (int) ((d.getHeight() - height) * 0.5);
frame.setBounds(x, y, width, height);
// Set the menu bar and add the label to the content pane.
MainMenu menu = new MainMenu();
// We only add components to the content pane, NEVER directly via
// add(...)!!!
frame.getContentPane().add(menu, BorderLayout.CENTER);
// Display the window.
frame.setVisible(true);
}
public static void main(String[] args) {
// Schedule a job for the event-dispatching thread:
// creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
MainMenu.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!
}
}
答案 2 :(得分:0)
当然,
repaint(x ,y ,width, height);
将重新绘制这些边界,加速它们,并省略不必要的工作。
答案 3 :(得分:0)
调用任何repaint()方法只是将组件排队,以便稍后重新绘制。如果在RepaintManager实际重新绘制Component之前多次调用repaint(),则只需将它们组合成一个重绘操作。
您应该尝试使用其中一个paintImmediately()方法,因为这些方法会立即执行重绘(假设您无法从名称中猜出)。
有关其他信息,请阅读: Painting in AWT and Swing