簡體   English   中英

如何將GUI的狀態恢復為原始外觀?

[英]How can I restore the state of my GUI to its original appearance?

我用Java編寫了一個GUI,用於使用2D圖形的吉他和弦查找器應用程序。 該程序在畫布上打開.jpg圖像。 然后它將每個單獨的音符(音柱之間的空格)繪制為帶有音符名稱的橢圓。 該程序允許用戶通過改變和弦的各個音符的顏色,從工具欄中選擇和弦顯示在指板上的和弦。 但是,每當用戶選擇新的和弦時,不會刪除前一個和弦。 我怎樣才能解決這個問題? 這是我的一些代碼(該程序超過1000行代碼)。

    public class Fretboard extends JFrame  implements ActionListener{
        public static void main(String[] args) {
            JFrame frame = new Fretboard();
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.pack();
            frame.setVisible(true);
        }
        // Variables to be used throughout the program
        ImagePanel imageSrc;                                    
        // Declare fonts to be used
        Font font1 = new Font("SansSerif", Font.BOLD, 18);          // Font to be used for notes with # or b
        Font chordFont = new Font("SansSerif", Font.BOLD, 50);      // Font for the name of the chord displayed
        Font font = new Font("SansSerif", Font.BOLD, 20);           // Font to be used for whole note

        int h = 40, w = 26, x = 695, y = 254;

        // Declare the note variables
        // First string
        Ellipse2D E1 = new Ellipse2D.Double(x, y-110, w, h);        // E note, open 1st string
        Ellipse2D F1 = new Ellipse2D.Double(x, y, w, h);            // F note, 1st string, 1st fret
        Ellipse2D fSharp1 = new Ellipse2D.Double(x, y+125, w, h);   // F#/Gb note, 1st string, 2nd fret
        Ellipse2D G1 = new Ellipse2D.Double(x+2, y+240, w, h);      // G note, 1st string, 3rd fret

        /**
         * Create the menu bar and set title
         */

        public Fretboard() {
            // Change the title of the window
            setTitle("Fretboard Chord Finder");
            // Create a menu bar where user will be given choice of chords
            JMenuBar mb = new JMenuBar();
            setJMenuBar(mb);

            JMenu menu = new JMenu("Chords");
            // Add names of chords to the menu
            JMenuItem mi = new JMenuItem("A Major");
            mi.addActionListener(this);
            menu.add(mi);
            mi = new JMenuItem("A Minor");
            mi.addActionListener(this);
            menu.add(mi);

            Container cp = this.getContentPane();
            cp.setLayout(new FlowLayout());
            imageSrc = new ImagePanel();
            cp.add(imageSrc);
        }


        /**
         * Obtain the user's chord selection from the chord menu
         */
        public void actionPerformed(ActionEvent e) {
            String command = e.getActionCommand();
            if("A Major".equals(command))
                paintAMajor();
            if("A Minor".equals(command))
                paintAMinor();
            }

    /**
     * Displays the notes for the A Major chord when the user selects
     * "A Major" from the toolbar.
     */
    public void paintAMajor() {
        // Declare local variables
        Graphics g = getGraphics();
        Graphics2D g2 = (Graphics2D) g;

        // Display the name of the chord
        g2.drawString("A Major Chord", 40, 150);
        g2.drawString("Notes: A, C#, E", 40, 180);

        // Display notes for the A Major chord
        // Draw the E note on the open 1st string
        // Change color to blue
        g2.setColor(Color.red);
        g2.draw(E1);
        g2.fill(E1);
        g2.setColor(Color.white);
        g2.setFont(font);
        g2.drawString("E", x+7, y-82);
        // Change color back to red
        g2.setColor(Color.red);
    }

class ImagePanel extends JPanel {
    BufferedImage image = null; 

    public ImagePanel() {
        File fretBoardFile = new File("/Users/macbook/documents/workspace/Fretboard App/Gibson_Fretboard.jpg");     // The location of the fretboard image
        // Open the image
        try {
            image = ImageIO.read(fretBoardFile);
        } 
        catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        setPreferredSize(new Dimension(1280, 960));
    }

    /**
     * 
     * @param bi
     */
    public ImagePanel(BufferedImage bi) {
        image = bi; 
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        // Draw the image of the fretboard on the canvas.
        // Check to see if the image is available
        if(image != null) {
            g2.drawImage(image, 25, 0, null);
        }
        else
            g2.drawRect(0, 0, getWidth()-1, getHeight()-1);

        // Draw notes
        // Draw the E note on the open 1st string
        // Change color to blue
        g2.setColor(Color.blue);
        g2.draw(E1);
        g2.fill(E1);
        g2.setColor(Color.white);
        g2.setFont(font);
        g2.drawString("E", x+7, y-82);
        // Change color back to blue
        g2.setColor(Color.blue);
}

這是該計划的要點。 其他所有內容基本上都是每個音符或類似方法的位置以顯示和弦。 我被困住了,不知道如何修復這個程序。 這是我編程的第一個GUI。 請幫忙。 謝謝!

跳出來的第一件事就是使用getGraphics() 您應該避免使用此方法。

Java中的圖形是無狀態的。 也就是說,用於渲染組件的Graphics上下文在循環之間不保證是相同的。 您不應該保持對Graphics上下文的引用。

所有繪畫都應該在組件paint方法的上下文中完成,最好是JComponent#paintComponent ,因為paint方法是acomplex方法,做了很多重要的工作,你真的不想復制。

我會創建一種和弦的“模型”,每個實例都能夠自己繪制它。 然后我會創建一個能夠畫出音品和和弦的視圖。

以示例更新

這是一個概念證明的例子。 假設吉他弦從5(叢林)開始到0(最小)。

我不是音樂家,我沒有節拍或節奏,所以我可能犯了一些根本性的錯誤。

在此輸入圖像描述

public class TestFretBoard {

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

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

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

    public class ChordsPane extends JPanel {

        public ChordsPane() {
            setLayout(new BorderLayout());
            FretPane fretPane = new FretPane();
            fretPane.setChord(new AChord());
            add(fretPane);
        }
    }

    public static interface FretBoard {

        public Rectangle getFretBounds(int index);

        public GuitarString getGuitarString(int index);

        public GuitarString[] getGuitarStrings(int... index);
    }

    public static class FretPane extends JPanel implements FretBoard {

        private static final Point BOARD_OFFSET = new Point(9, 9);
        private static final int BOARD_WIDTH = 84;
        private static final Rectangle[] FRET_BOUNDS = {
            new Rectangle(BOARD_OFFSET.x, 20, BOARD_WIDTH, 68 - 20),
            new Rectangle(BOARD_OFFSET.x, 71, BOARD_WIDTH, 113 - 71),
            new Rectangle(BOARD_OFFSET.x, 116, BOARD_WIDTH, 153 - 116),
            new Rectangle(BOARD_OFFSET.x, 156, BOARD_WIDTH, 189 - 156),
            new Rectangle(BOARD_OFFSET.x, 192, BOARD_WIDTH, 222 - 192),
            new Rectangle(BOARD_OFFSET.x, 225, BOARD_WIDTH, 254 - 225),
            new Rectangle(BOARD_OFFSET.x, 257, BOARD_WIDTH, 289 - 257),
            new Rectangle(BOARD_OFFSET.x, 287, BOARD_WIDTH, 312 - 287),
            new Rectangle(BOARD_OFFSET.x, 315, BOARD_WIDTH, 338 - 315),
            new Rectangle(BOARD_OFFSET.x, 341, BOARD_WIDTH, 364 - 341),
            new Rectangle(BOARD_OFFSET.x, 367, BOARD_WIDTH, 389 - 367),
            new Rectangle(BOARD_OFFSET.x, 392, BOARD_WIDTH, 412 - 392),};
        private static final GuitarString[] GUITAR_STRINGS = {
            new GuitarString(85 - BOARD_OFFSET.x, 1),
            new GuitarString(72 - BOARD_OFFSET.x, 1),
            new GuitarString(58 - BOARD_OFFSET.x, 1),
            new GuitarString(43 - BOARD_OFFSET.x, 2),
            new GuitarString(29 - BOARD_OFFSET.x, 2),
            new GuitarString(15 - BOARD_OFFSET.x, 2),};
        private BufferedImage background;
        private Chord chord;

        public FretPane() {
            try {
                background = ImageIO.read(new File("fretboard02.png"));
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }

        @Override
        public Dimension getPreferredSize() {
            return background == null ? super.getPreferredSize() : new Dimension(background.getWidth(), background.getHeight());
        }

        public Chord getChord() {
            return chord;
        }

        public void setChord(Chord chord) {
            this.chord = chord;
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            if (background != null) {
                int x = (getWidth() - background.getWidth()) / 2;
                int y = (getHeight() - background.getHeight()) / 2;
                g2d.drawImage(background, x, y, this);
                Chord chord = getChord();
                if (chord != null) {
                    g2d.translate(x, y);
                    chord.paint(this, g2d);
                    g2d.translate(-x, -y);
                }
            }
            g2d.dispose();
        }

        @Override
        public Rectangle getFretBounds(int index) {
            Rectangle bounds = null;
            if (index >= 0 && index < FRET_BOUNDS.length) {
                bounds = FRET_BOUNDS[index];
            }
            return bounds;
        }

        @Override
        public GuitarString getGuitarString(int index) {
            GuitarString gs = null;
            if (index >= 0 && index < GUITAR_STRINGS.length) {
                gs = GUITAR_STRINGS[index];
            }
            return gs;
        }

        @Override
        public GuitarString[] getGuitarStrings(int... indices) {
            List<GuitarString> strings = new ArrayList<GuitarString>(indices.length);
            for (int index : indices) {
                strings.add(getGuitarString(index));
            }
            return strings.toArray(new GuitarString[strings.size()]);
        }
    }

    public static class GuitarString {

        private int x;
        private int width;

        public GuitarString(int x, int width) {
            this.x = x;
            this.width = width;
        }

        public int getX() {
            return x;
        }

        public int getWidth() {
            return width;
        }
    }

    public interface Chord {

        public String getName();

        public void paint(FretBoard board, Graphics2D g2d);
    }

    public abstract class AbstractChord implements Chord {

        public abstract int[] getFrets();

        public abstract GuitarString[] getGuitarStrings(FretBoard board, int fret);

        @Override
        public void paint(FretBoard board, Graphics2D g2d) {
            for (int fret : getFrets()) {
                Rectangle fretBounds = board.getFretBounds(fret);
                // Guitar Strings start at 5 (thickest) to 0 (smallest)
                GuitarString[] guitarStrings = getGuitarStrings(board, fret);

                int y = fretBounds.y + (fretBounds.height / 2);

                g2d.setColor(Color.RED);
                Ellipse2D dot = new Ellipse2D.Float(0, 0, 10, 10);

                for (GuitarString gs : guitarStrings) {
                    int x = ((gs.x + fretBounds.x) + (gs.width / 2)) - 5;
                    g2d.fill(getDot(dot, x, y - 5));
                }
            }
        }

        public Shape getDot(Ellipse2D dot, int x, int y) {

            PathIterator pathIterator = dot.getPathIterator(AffineTransform.getTranslateInstance(x, y));
            Path2D path = new Path2D.Float();
            path.append(pathIterator, true);

            return path;

        }
    }

    public class AChord extends AbstractChord {

        private int index;

        @Override
        public String getName() {
            return "A";
        }

        @Override
        public int[] getFrets() {
            return new int[]{1};
        }

        @Override
        public GuitarString[] getGuitarStrings(FretBoard board, int fret) {
            GuitarString[] strings = new GuitarString[0];
            switch (fret) {
                case 1:
                    strings = board.getGuitarStrings(3, 2, 1);
                    break;
            }
            return strings;
        }

    }
}

圖像和用戶界面之間的映射有很多工作,你可以自己搞清楚,我打開了PhotoShop並手動測出了所有的點數。 如果你自己畫出音板,它會變得更容易。

基本概念圍繞“和弦”。 和弦有一個名字,可以畫自己。 我創建了一個簡單的Chord接口抽象實現,它占用了大部分腿部工作,並且更容易創建新的和弦(因為你只需要為構成該和弦的每個音品提供音品和弦樂)

我也建議你仔細閱讀

一種方法是在每次調用paintComponent時從頭開始繪制所有內容。 無條件地繪制指板圖像,移動代碼在paintComponent中繪制選定的線,並根據某個變量繪制線,並使actionListner將該變量設置為選定的線。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM