java - 如何使用drawString和drawImage实现游戏的Java swing GUI启动屏幕?

标签 java swing user-interface awt

我不确定如何修复程序中的错误以及如何突出显示用户悬停的选项。我希望它突出显示每个位置的代码,即位置 1 将突出显示(作为不同的颜色)以开始游戏等。上/下会改变位置,我会用上、下、左、右改变位置。这是我到目前为止所拥有的。目前它有问题,当用我的窗口编译时,它显示为:

enter image description here

这适用于主游戏并针对此标题板进行了更改,我做错了什么以及如何修复它?

TitleBoard 类

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.ArrayList;

//sound + file opening
import java.io.*;
import javax.sound.sampled.*;
public class TitleBoard extends JPanel implements ActionListener{

    private ArrayList<String> OptionList;
    private Image background;
    private ImageIcon bgImageIcon;
    private String cheatString;
    private int position;
    private Timer timer;

    public TitleBoard(){

    setFocusable(true);
    addKeyListener(new TAdapter());
    bgImageIcon = new ImageIcon("");
    background = bgImageIcon.getImage();
    String[] options = {"Start Game","Options","Quit"};
    OptionList = new ArrayList<String>();
    optionSetup(options);
    position = 1;
    timer = new Timer(8, this);
    timer.start();
    /*
      1 mod 3 =>1 highlight on start
      2 mod 3 =>2 highlight on options
      3 mod 3 =>0 highlight on quit
    */

    try{
        Font numFont = Font.createFont(Font.TRUETYPE_FONT,new File("TwistedStallions.ttf"));
        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
        ge.registerFont(numFont);
        setFont(numFont.deriveFont(24f)); //adjusthislater
    }catch(IOException|FontFormatException e){
        e.printStackTrace();
    }

    }
    private void optionSetup(String[] s){
    for(int i=0; i<s.length;i++) {
        OptionList.add(s[i]);
    }
    }



    public void paint(Graphics g){
    super.paint(g);
    Graphics g2d = (Graphics2D)g;

    g2d.drawImage(background,0,0,this);
    for (int i=0;i<OptionList.size();i++){
        g2d.drawString(OptionList.get(i),200,120+120*i);
    }/*
    g2d.drawString(OptionList.get(1),400,240);
    g2d.drawString(OptionList.get(2),400,360);
    //instructions on start screen maybe??
    //800x500
    //highlighting*/
    Toolkit.getDefaultToolkit().sync();
    g.dispose();
    }

    public void actionPerformed(ActionEvent e){
    repaint();
    }



    public class TAdapter extends KeyAdapter {
    public void keyPressed(KeyEvent e){
        if(e.getKeyCode() == KeyEvent.VK_UP||
           e.getKeyCode() == KeyEvent.VK_RIGHT){
        position++;
        }
        if(e.getKeyCode() == KeyEvent.VK_DOWN||
           e.getKeyCode() == KeyEvent.VK_LEFT){
        position--;
        }
    }
    }

}

窗口类

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class Window extends JFrame{
    public Window(){
    int width = 800, height = 600;
    //TO DO: make a panel in TITLE MODE
    ///////////////////////////////////
    //panel in GAME MODE.
    add(new TitleBoard());
    //set default close
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setSize(width,height);
    //centers window
    setLocationRelativeTo(null);
    setTitle("Title");
    setResizable(false);
    setVisible(true);   
    }
    public static void main(String[] args){
    new Window();
    }
}

最佳答案

您可以通过多种方式实现这一目标,例如,您可以使用某种委托(delegate)模型。

也就是说,您可以设计一个委托(delegate),它提供一个简单的接口(interface)方法,paint 方法将调用该方法,并且它知道如何执行其余的操作,而不是尝试在单个方法(或多个方法)中管理每个元素。

例如,Swing 将这种类型的概念用于 JListJTableJTree 的单元格渲染器。

例如...

Menu

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class MyAwesomeMenu {

    public static void main(String[] args) {
        new MyAwesomeMenu();
    }

    public MyAwesomeMenu() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private List<String> menuItems;
        private String selectMenuItem;
        private String focusedItem;

        private MenuItemPainter painter;
        private Map<String, Rectangle> menuBounds;

        public TestPane() {
            setBackground(Color.BLACK);
            painter = new SimpleMenuItemPainter();
            menuItems = new ArrayList<>(25);
            menuItems.add("Start Game");
            menuItems.add("Options");
            menuItems.add("Exit");
            selectMenuItem = menuItems.get(0);

            MouseAdapter ma = new MouseAdapter() {

                @Override
                public void mouseClicked(MouseEvent e) {
                    String newItem = null;
                    for (String text : menuItems) {
                        Rectangle bounds = menuBounds.get(text);
                        if (bounds.contains(e.getPoint())) {
                            newItem = text;
                            break;
                        }
                    }
                    if (newItem != null && !newItem.equals(selectMenuItem)) {
                        selectMenuItem = newItem;
                        repaint();
                    }
                }

                @Override
                public void mouseMoved(MouseEvent e) {
                    focusedItem = null;
                    for (String text : menuItems) {
                        Rectangle bounds = menuBounds.get(text);
                        if (bounds.contains(e.getPoint())) {
                            focusedItem = text;
                            repaint();
                            break;
                        }
                    }
                }

            };

            addMouseListener(ma);
            addMouseMotionListener(ma);
        
            InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
            ActionMap am = getActionMap();
        
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), "arrowDown");
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), "arrowUp");
        
            am.put("arrowDown", new MenuAction(1));
            am.put("arrowUp", new MenuAction(-1));

        }

        @Override
        public void invalidate() {
            menuBounds = null;
            super.invalidate();
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            if (menuBounds == null) {
                menuBounds = new HashMap<>(menuItems.size());
                int width = 0;
                int height = 0;
                for (String text : menuItems) {
                    Dimension dim = painter.getPreferredSize(g2d, text);
                    width = Math.max(width, dim.width);
                    height = Math.max(height, dim.height);
                }

                int x = (getWidth() - (width + 10)) / 2;

                int totalHeight = (height + 10) * menuItems.size();
                totalHeight += 5 * (menuItems.size() - 1);

                int y = (getHeight() - totalHeight) / 2;

                for (String text : menuItems) {
                    menuBounds.put(text, new Rectangle(x, y, width + 10, height + 10));
                    y += height + 10 + 5;
                }

            }
            for (String text : menuItems) {
                Rectangle bounds = menuBounds.get(text);
                boolean isSelected = text.equals(selectMenuItem);
                boolean isFocused = text.equals(focusedItem);
                painter.paint(g2d, text, bounds, isSelected, isFocused);
            }
            g2d.dispose();
        }
    
        public class MenuAction extends AbstractAction {

            private final int delta;
        
            public MenuAction(int delta) {
                this.delta = delta;
            }

            @Override
            public void actionPerformed(ActionEvent e) {
                int index = menuItems.indexOf(selectMenuItem);
                if (index < 0) {
                    selectMenuItem = menuItems.get(0);
                }
                index += delta;
                if (index < 0) {
                    selectMenuItem = menuItems.get(menuItems.size() - 1);
                } else if (index >= menuItems.size()) {
                    selectMenuItem = menuItems.get(0);
                } else {
                    selectMenuItem = menuItems.get(index);
                }
                repaint();
            }
        
        }

    }

    public interface MenuItemPainter {

        public void paint(Graphics2D g2d, String text, Rectangle bounds, boolean isSelected, boolean isFocused);

        public Dimension getPreferredSize(Graphics2D g2d, String text);

    }

    public class SimpleMenuItemPainter implements MenuItemPainter {

        public Dimension getPreferredSize(Graphics2D g2d, String text) {
            return g2d.getFontMetrics().getStringBounds(text, g2d).getBounds().getSize();
        }

        @Override
        public void paint(Graphics2D g2d, String text, Rectangle bounds, boolean isSelected, boolean isFocused) {
            FontMetrics fm = g2d.getFontMetrics();
            if (isSelected) {
                paintBackground(g2d, bounds, Color.BLUE, Color.WHITE);
            } else if (isFocused) {
                paintBackground(g2d, bounds, Color.MAGENTA, Color.BLACK);
            } else {
                paintBackground(g2d, bounds, Color.DARK_GRAY, Color.LIGHT_GRAY);
            }
            int x = bounds.x + ((bounds.width - fm.stringWidth(text)) / 2);
            int y = bounds.y + ((bounds.height - fm.getHeight()) / 2) + fm.getAscent();
            g2d.setColor(isSelected ? Color.WHITE : Color.LIGHT_GRAY);
            g2d.drawString(text, x, y);
        }

        protected void paintBackground(Graphics2D g2d, Rectangle bounds, Color background, Color foreground) {
            g2d.setColor(background);
            g2d.fill(bounds);
            g2d.setColor(foreground);
            g2d.draw(bounds);
        }

    }

}

从这里,您可以添加ActionListener

关于java - 如何使用drawString和drawImage实现游戏的Java swing GUI启动屏幕?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21225760/

相关文章:

java - 运行我的应用程序时 LOGCAT 显示此错误

java - 可运行 jar 时出现 NoClassDefFoundError

java JFrame 设置大小

java - 如何使用 JavaFX 创建三角形?

java - Gwt,如何使文本框具有多于 1 条可见行?

java - 在 web 服务调用上传递 LPTA token 不起作用

java - Android 应用程序不会将数据存储在数据库中

Java 从另一个类获取选定的组合框

java - 如何找到 Java Desktop API 在 Linux 上需要哪些库?

c# - 切换任务时不会触发 Control.Enter 事件。有替代方案吗?