Перерисовать строки в CardLayout - PullRequest
4 голосов
/ 20 июня 2020

Я создал игру, используя CardLayout, и у меня есть одна панель JPanel для таблицы лидеров. В таблице лидеров я читаю два файла (один с именами, другой со временем), сортирую их и рисую 5 самых быстрых результатов следующим образом:

private void setBoard(){
        reset();
        try{
            br = new BufferedReader (new FileReader("username.txt"));
            accounts = ""+br.readLine().trim();
            arrNames = accounts.split(" ");
            br.close();
            br = new BufferedReader (new FileReader("time.txt"));
            allTimes = ""+br.readLine().trim();
            arrTimesTemp = allTimes.split(" ");
            arrTime = new double [arrTimesTemp.length];
            br.close();
        } catch (Exception er){
            System.out.print("Error" + er);
        }   
        for (int i=0;i<arrTime.length;i++)
            arrTime[i]=Double.parseDouble(arrTimesTemp[i]);;
        scores = new Score[arrTime.length];
        for (int i=0;i<arrTime.length;i++)
            scores[i] = new Score (arrNames[i],arrTime[i]);
        Arrays.sort(scores, new MyComparator());

        System.out.println("\n\n\n");
        for (int i=0;i<arrTime.length;i++)
            System.out.println(arrTime[i]+" "+arrNames[i]);
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawImage(title, getWidth()/2-title.getWidth()/2+10, 125, this);
        g.drawImage(txt, getWidth()/2-txt.getWidth()/2+10, 250, this);
        setBoard();
        g.setFont(new Font("Serif", Font.PLAIN, 25));
        g.setColor(Color.white);

        for (int i=0;i<5;i++){
            g.drawString((i+1)+"-", numX, lineY);
            g.drawString(scores[i].getName(), nameX, lineY);
            g.drawString(""+scores[i].getTime(), timeX, lineY);
            g.drawString("s", 515, lineY);
            lineY+=40;
        }
    }

Нет проблем при первом открытии таблицы лидеров. Однако, если я вернусь в меню, а затем вернусь в таблицу лидеров, строки будут рисоваться не, а изображения. Я тоже так не получаю никаких ошибок. Я не могу понять, почему это происходит.

Как вернуться в меню:

public void actionPerformed(ActionEvent e) {
        if (e.getSource()==back)
            RunGame.card.first(RunGame.c);
    }

Как я go в таблицу лидеров из меню:

    else if (e.getSource()==d) //d is a JButton
            RunGame.card.show(RunGame.c,"Leaderboard");

таблица лидеров в первый раз таблица лидеров при возврате в нее

1 Ответ

3 голосов
/ 20 июня 2020

Я решил свою проблему. Мне просто приходилось сбрасывать numX nameX timeX lineY каждый раз, когда я переключался на таблицу лидеров

Хорошо, мы выучили урок, глобальное состояние - это плохо ...

Хорошо , поскольку я потратил некоторое время на сборку примера, я бы опубликовал его, чтобы продемонстрировать базовую c концепцию общего состояния.

В этом примере создается LeaderBoardModel, который используется совместно основными представлениями. Это позволяет разделять состояние между различными аспектами вашего кода без необходимости явного понимания того, как оно на самом деле работает - модель становится автономной единицей работы и может управлять своим собственным состоянием.

Другой аспект здесь , пытается сохранить ваш путь рисования как можно быстрее - поэтому даже в этом примере сортировку и разделение списка можно было бы рассмотреть для оптимизации ... но мы не пытаемся достичь 200 кадров в секунду ... итак, балансировка .. .

import java.awt.CardLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Test {

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

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                LeaderBoardModel model = new LeaderBoardModel();
                JFrame frame = new JFrame();
                frame.setLayout(new GridBagLayout());

                GridBagConstraints gbc = new GridBagConstraints();
                gbc.weightx = 1;
                gbc.weighty = 1;
                gbc.gridx = 0;
                gbc.gridy = 0;

                CardLayout cardLayout = new CardLayout();

                JPanel mainPane = new JPanel(cardLayout);
                mainPane.add(new GamePanel(model), "main");
                mainPane.add(new LeaderBoardPanel(model), "leaderBoard");

                cardLayout.show(mainPane, "main");

                frame.add(mainPane, gbc);

                JPanel buttons = new JPanel(new GridBagLayout());
                JButton main = new JButton("Main");
                JButton board = new JButton("Board");

                buttons.add(main);
                buttons.add(board);

                main.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        cardLayout.show(mainPane, "main");
                    }
                });
                board.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        cardLayout.show(mainPane, "leaderBoard");
                    }
                });

                gbc.weightx = 1;
                gbc.weighty = 0;
                gbc.gridy++;
                frame.add(buttons, gbc);

                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    // I'd prefer to use interfaces as a base line concept, but, this is
    // is a demonstration of a concept, not a tutorial
    public class Score implements Comparable<Score> {

        private String name;
        private int score;

        public Score(String name, int score) {
            this.name = name;
            this.score = score;
        }

        public String getName() {
            return name;
        }

        public int getScore() {
            return score;
        }

        @Override
        public int compareTo(Score o) {
            return o.score - score;
        }

        @Override
        public String toString() {
            return name + " ~ " + score;
        }

    }

    // I'd prefer to use interfaces as a base line concept, but, this is
    // is a demonstration of a concept, not a tutorial
    public class LeaderBoardModel {

        private List<Score> scores;

        public LeaderBoardModel() {
            // This is where you'd consider loading the scores from
            // the original file...
            scores = new ArrayList<>(25);

            Random rnd = new Random();

            add(new Score("Shekhar", rnd.nextInt(99) + 1));
            add(new Score("Priyanka", rnd.nextInt(99) + 1));
            add(new Score("Vivi", rnd.nextInt(99) + 1));
            add(new Score("Darwin", rnd.nextInt(99) + 1));
            add(new Score("Hálfdan", rnd.nextInt(99) + 1));
            add(new Score("Emmerson", rnd.nextInt(99) + 1));
            add(new Score("Marie", rnd.nextInt(99) + 1));
            add(new Score("Mikha'il", rnd.nextInt(99) + 1));
            add(new Score("Jayanta", rnd.nextInt(99) + 1));
            add(new Score("Theodosia", rnd.nextInt(99) + 1));
            add(new Score("Sharleen", rnd.nextInt(99) + 1));
            add(new Score("Kristian", rnd.nextInt(99) + 1));
            add(new Score("Alberte", rnd.nextInt(99) + 1));
            add(new Score("Maylis", rnd.nextInt(99) + 1));
            add(new Score("Katayun", rnd.nextInt(99) + 1));
        }

        public void save() {
            // Well, because it's nice to remember this stuff
        }

        public void add(Score score) {
            // We could sort the list here, lots of ways to do it ...
            // but waste the time if we don't actually need to
            scores.add(score);
        }

        public List<Score> getScores() {
            // Could use a flag to determine if this actually needs to be
            // sorted or not ... but this is just a demonstration :/
            Collections.sort(scores);
            return Collections.unmodifiableList(scores);
        }

    }

    public class GamePanel extends JPanel {

        private LeaderBoardModel model;
        private Random rnd = new Random();

        public GamePanel(LeaderBoardModel model) {
            this.model = model;

            setLayout(new GridBagLayout());

            JButton btn = new JButton("Win");
            add(btn);
            btn.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    model.add(new Score("l334", rnd.nextInt(99) + 100));
                }
            });
        }

    }

    public class LeaderBoardPanel extends JPanel {

        private LeaderBoardModel model;

        public LeaderBoardPanel(LeaderBoardModel model) {
            this.model = model;
        }

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

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();

            String highScore = "High Score";

            FontMetrics fm = g2d.getFontMetrics();
            int xPos = (getWidth() - fm.stringWidth(highScore)) / 2;
            int yPos = 10;
            g2d.drawString(highScore, xPos, yPos + fm.getAscent());

            yPos += fm.getHeight() * 2;

            List<Score> scores = model.getScores();
            scores = scores.subList(0, Math.min(10, scores.size() - 1));

            for (Score score : scores) {
                String name = score.getName();
                String value = Integer.toString(score.getScore());

                xPos = (getWidth() / 2) - fm.stringWidth(name) - 5;
                g2d.drawString(name, xPos, yPos + fm.getAscent());
                xPos = (getWidth() / 2) + 5;
                g2d.drawString(value, xPos, yPos + fm.getAscent());

                yPos += fm.getHeight();
            }

            g2d.dispose();
        }

    }
}
...