How do I implement Java swing GUI start screen for a game with drawString and drawImage?

痞子三分冷 提交于 2019-12-23 05:13:17

问题


I'm not sure how I would fix the errors in my program and how I would highlight the option the user is hovering on. I want it to highlight the code for each position, i.e position 1 would be highlighted(as a different color) to start game,etc. and up/down would change position and I would change the position with up ,down, left, right. This is what I have so far. At the moment its bugged and when compiled with my window it comes out as:

Which works for the main game and altered for this titleboard, what am I doing wrong and how do I fix it?

TitleBoard class

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--;
        }
    }
    }

}

Window Class

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();
    }
}

回答1:


There are any number of ways you might achieve this, for example, you could use some kind of delegation model.

That is, rather then trying to mange of each element in a single method (or methods), you could devise a delegate which provide a simple interface method that the paint method would call and it would know how to do the rest.

For example, Swing uses this type of concept with it's cell renderers for JList, JTable and JTree.

For example...

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);
        }

    }

}

For here, you could add ActionListener




回答2:


When a GUI needs a button, use a JButton! The JButton API allows the possibility to add icons for many different circumstances. This example shows different icons for the standard icon, the hover icon, and the pressed icon. Your GUI would obviously use icons with text on them for the required effect.

The icons are pulled directly (hot-linked) from Example images for code and mark-up Q&As.

Standard

Hover over triangle

Press triangle

Code

import java.awt.*;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.net.URL;

public class IconHoverFocusIndication {

    // the GUI as seen by the user (without frame)
    // swap the 1 and 0 for single column
    JPanel gui = new JPanel(new GridLayout(1,0,50,50));
    public static final int GREEN = 0, YELLOW = 1, RED = 2;
    String[][] urls = {
        {
            "http://i.stack.imgur.com/T5uTa.png",
            "http://i.stack.imgur.com/IHARa.png",
            "http://i.stack.imgur.com/wCF8S.png"
        },
        {
            "http://i.stack.imgur.com/gYxHm.png",
            "http://i.stack.imgur.com/8BGfi.png",
            "http://i.stack.imgur.com/5v2TX.png"
        },
        {
            "http://i.stack.imgur.com/1lgtq.png",
            "http://i.stack.imgur.com/6ZXhi.png",
            "http://i.stack.imgur.com/F0JHK.png"
        }
    };

    IconHoverFocusIndication() throws Exception {
        // adjust to requirement..
        gui.setBorder(new EmptyBorder(15, 30, 15, 30));
        gui.setBackground(Color.BLACK);
        Insets zeroMargin = new Insets(0,0,0,0);
        for (int ii = 0; ii < 3; ii++) {
            JButton b = new JButton();
            b.setBorderPainted(false);
            b.setMargin(zeroMargin);
            b.setContentAreaFilled(false);
            gui.add(b);

            URL url1 = new URL(urls[ii][GREEN]);
            BufferedImage bi1 = ImageIO.read(url1);
            b.setIcon(new ImageIcon(bi1));

            URL url2 = new URL(urls[ii][YELLOW]);
            BufferedImage bi2 = ImageIO.read(url2);
            b.setRolloverIcon(new ImageIcon(bi2));

            URL url3 = new URL(urls[ii][RED]);
            BufferedImage bi3 = ImageIO.read(url3);
            b.setPressedIcon(new ImageIcon(bi3));
        }
    }

    public JComponent getGUI() {
        return gui;
    }

    public static void main(String[] args) {
        Runnable r = new Runnable() {

            @Override
            public void run() {
                try {
                    IconHoverFocusIndication ihfi =
                            new IconHoverFocusIndication();
                    JFrame f = new JFrame("Button Icons");
                    f.add(ihfi.getGUI());
                    // Ensures JVM closes after frame(s) closed and
                    // all non-daemon threads are finished
                    f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                    // See https://stackoverflow.com/a/7143398/418556 for demo.
                    f.setLocationByPlatform(true);

                    // ensures the frame is the minimum size it needs to be
                    // in order display the components within it
                    f.pack();
                    // should be done last, to avoid flickering, moving,
                    // resizing artifacts.
                    f.setVisible(true);
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        };
        // Swing GUIs should be created and updated on the EDT
        // http://docs.oracle.com/javase/tutorial/uiswing/concurrency
        SwingUtilities.invokeLater(r);
    }
}


来源:https://stackoverflow.com/questions/21225760/how-do-i-implement-java-swing-gui-start-screen-for-a-game-with-drawstring-and-dr

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!